KVM patch queue for the 2.6.24 merge window
cover KVM patch queue for the 2.6.24 merge window
The following represents the patch queue for the 2.6.24, posted here for review. Most of the patches have already been on kvm-devel (and all of them on kvm-commits), but some folding has occured to merge fixes and to make the whole series bisect-friendly.
A few patches are likely to change in the near future; they will be reposted if they do.
The most visible new feature is the in-kernel lapic/ioapic/pic emulation; others include making kvm preemptible (a first step for guest swapping), additional x86 emulator work, and Rusty Unleashed.
Amit Shah (1):
KVM: Set the ET flag in CR0 after initializing FX
Aurelien Jarno (1):
KVM: Remove dead code in the cmpxchg instruction emulation
Avi Kivity (11):
KVM: Future-proof the exit information union ABI
KVM: x86 emulator: fix cmov for writeback changes
KVM: x86 emulator: fix faulty check for two-byte opcode
KVM: Use the scheduler preemption notifiers to make kvm preemptible
KVM: Close minor race in signal handling
KVM: X86 emulator: fix 'push reg' writeback
KVM: MMU: Don't do GFP_NOWAIT allocations
KVM: VMX: Move vm entry failure handling to the exit handler
KVM: Move main vcpu loop into subarch independent code
KVM: Improve emulation failure reporting
KVM: Skip pio instruction when it is emulated, not executed
Christian Ehrhardt (1):
KVM: Rename kvm_arch_ops to kvm_x86_ops
Eddie Dong (11):
KVM: In-kernel string pio write support
KVM: Add support for in-kernel PIC emulation
KVM: Define and use cr8 access functions
KVM: Emulate local APIC in kernel
KVM: In-kernel I/O APIC model
KVM: Emulate hlt in the kernel
KVM: Protect in-kernel pio using kvm->lock
KVM: in-kernel LAPIC save and restore support
KVM: pending irq save/restore
KVM: Keep track of missed timer irq injections
KVM: Migrate lapic hrtimer when vcpu moves to another cpu
Gabriel C (1):
KVM: Fix defined but not used warning in drivers/kvm/vmx.c
Gregory Haskins (1):
KVM: Remove arch specific components from the general code
He, Qing (7):
KVM: Add get/set irqchip ioctls for in-kernel PIC live migration support
KVM: Bypass irq_pending get/set when using in kernel irqchip
KVM: in-kernel IOAPIC save and restore support
KVM: disable tpr/cr8 sync when in-kernel APIC is used
KVM: round robin for APIC lowest priority delivery mode
KVM: enable in-kernel APIC INIT/SIPI handling
KVM: VMX: Fix exit qualification width on i386
Izik Eidus (2):
KVM: VMX: allow rmode_tss_base() to work with >2G of guest memory
KVM: Support more memory slots
Jeff Dike (2):
KVM: Set exit_reason to KVM_EXIT_MMIO where run->mmio is initialized.
KVM: add hypercall nr to kvm_run
Laurent Vivier (7):
KVM: Change the emulator_{read,write,cmpxchg}_* functions to take a vcpu
KVM: Remove kvm_{read,write}_guest()
KVM: Remove useless assignment
KVM: Cleanup string I/O instruction emulation
KVM: Clean up kvm_setup_pio()
KVM: VMX: Split segments reload in vmx_load_host_state()
KVM: Simplify memory allocation
Li, Xin B (1):
KVM: VMX: Remove a duplicated ia32e mode vm entry control
Nguyen Anh Quynh (1):
KVM: Fix *nopage() in kvm_main.c
Nitin A Kamble (14):
KVM: x86 emulator: implement 'and $imm, %{al|ax|eax}'
KVM: x86 emulator: implement 'jmp rel' instruction (opcode 0xe9)
KVM: x86 emulator: Implement 'jmp rel short' instruction (opcode 0xeb)
KVM: x86 emulator: implement 'push reg' (opcodes 0x50-0x57)
KVM: x86 emulator: push imm8
KVM: x86 emulator: call near
KVM: x86 emulator: pushf
KVM: x86 emulator: sort opcodes into ascending order
KVM: x86 emulator: imlpement jump conditional relative
KVM: X86 emulator: jump conditional short
KVM: x86 emulator: lea
KVM: x86 emulator: jmp abs
KVM: x86 emulator: fix src, dst value initialization
KVM: x86 emulator: popf
Qing He (2):
KVM: SMP: Add vcpu_id field in struct vcpu
KVM: deliver PIC interrupt only to vcpu0
Rusty Russell (33):
KVM: Trivial: /dev/kvm interface is no longer experimental.
KVM: Trivial: Remove unused struct cpu_user_regs declaration
KVM: Trivial: Make decode_register() static
KVM: Trivial: Comment spelling may escape grep
KVM: Trivial: Avoid hardware_disable predeclaration
KVM: Trivial: Use standard CR0 flags macros from asm/cpu-features.h
KVM: Use standard CR3 flags, tighten checking
KVM: Use standard CR4 flags, tighten checking
KVM: Trivial: Use standard BITMAP macros, open-code userspace-exposed header
KVM: Use standard CR8 flags, and fix TPR definition
KVM: Return if the pdptrs are invalid when the guest turns on PAE.
KVM: load_pdptrs() cleanups
KVM: Dynamically allocate vcpus
KVM: fx_init() needs preemption disabled while it plays with the FPU state
KVM: VMX: pass vcpu_vmx internally
KVM: Remove three magic numbers
KVM: SVM: de-containization
KVM: SVM: internal function name cleanup
KVM: Use kmem cache for allocating vcpus
KVM: Use alignment properties of vcpu to simplify FPU ops
KVM: kvm_vm_ioctl_get_dirty_log restore "nothing dirty" optimization
KVM: Don't assign vcpu->cr3 if it's invalid: check first, set last
KVM: Cleanup mark_page_dirty
KVM: SVM: Make set_msr_interception more reliable
KVM: Remove redundant alloc_vmcs_cpu declaration
KVM: Remove stat_set from debugfs
KVM: Remove unneeded kvm_dev_open and kvm_dev_release functions.
KVM: Add and use pr_unimpl for standard formatting of unimplemented features
KVM: Use kmem_cache_free for kmem_cache_zalloc'ed objects
KVM: Remove the unused invlpg member of struct kvm_arch_ops.
KVM: Clean up unloved invlpg emulation
KVM: Keep control regs in sync
KVM: Hoist SVM's get_cs_db_l_bits into core code.
Shaohua Li (3):
KVM: Hoist kvm_mmu_reload() out of the critical section
KVM: Move gfn_to_page out of kmap/unmap pairs
KVM: Convert vm lock to a mutex
Yang, Sheng (5):
KVM: VMX: Import some constants of vmcs from IA32 SDM
KVM: VMX: Improve the method of writing vmcs control
KVM: VMX: Add cpu consistency check
KVM: Communicate cr8 changes to userspace
KVM: VMX: Use shadow TPR/cr8 for 64-bits guests
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 1/104 KVM: Fix *nopage() in kvm_main.c
From: Nguyen Anh Quynh <[email protected]>
*nopage() in kvm_main.c should only store the type of mmap() fault if the pointers are not NULL. This patch fixes the problem.
--- drivers/kvm/kvm_main.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
drivers/kvm/kvm_main.c +6 -2
@@ -2285,7 +2285,6 @@ static struct page *kvm_vcpu_nopage(struct vm_area_struct *vma,unsigned long pgoff;struct page *page; - *type =VM_FAULT_MINOR ; pgoff = ((address - vma->vm_start) >>PAGE_SHIFT ) + vma->vm_pgoff;if (pgoff ==0 ) page =virt_to_page (vcpu->run);
@@ -2294,6 +2293,9 @@ static struct page *kvm_vcpu_nopage(struct vm_area_struct *vma,else return NOPAGE_SIGBUS ;get_page (page); +if (type !=NULL ) + *type =VM_FAULT_MINOR ; +return page; }
@@ -2768,12 +2770,14 @@ static struct page *kvm_vm_nopage(struct vm_area_struct *vma,unsigned long pgoff;struct page *page; - *type =VM_FAULT_MINOR ; pgoff = ((address - vma->vm_start) >>PAGE_SHIFT ) + vma->vm_pgoff; page =gfn_to_page (kvm, pgoff);if (!page)return NOPAGE_SIGBUS ;get_page (page); +if (type !=NULL ) + *type =VM_FAULT_MINOR ; +return page; }
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 001/104] KVM: Fix *nopage() in kvm_main.c
Quoted 4 lines · Avi Kivity
From: Nguyen Anh Quynh <[email protected]>
*nopage()inkvm_main.cshould only store the type ofmmap()fault if the pointers are not NULL. This patch fixes the problem.
Care to convert it to ->faul while you're at it?
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 001/104] KVM: Fix *nopage() in kvm_main.c
Quoted 10 lines · Christoph Hellwig
Quoted 5 lines · Avi Kivity
From: Nguyen Anh Quynh <[email protected]>
*nopage()inkvm_main.cshould only store the type ofmmap()fault if the pointers are not NULL. This patch fixes the problem.Care to convert it to ->faul while you're at it?
I'll add this to my todo, though not sure It'll be in time for .24. If someone sends a patch I'll apply it.
Signature · 7 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 001/104] KVM: Fix *nopage() in kvm_main.c
Quoted 11 lines · Avi Kivity
Quoted 9 lines · Christoph Hellwig
Quoted 6 lines · Avi Kivity
From: Nguyen Anh Quynh <[email protected]>
*nopage()inkvm_main.cshould only store the type ofmmap()fault if the pointers are not NULL. This patch fixes the problem.
Quoted 8 lines
Quoted 3 lines
Care to convert it to ->faul while you're at it?
I'll add this to my todo, though not sure It'll be in time for .24. If someone sends a patch I'll apply it.
I should mention that the converting to use ->fault() is a 15-minute change; the tricky part is adding backwards compatibility for the external module package.
Signature · 7 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 001/104] KVM: Fix *nopage() in kvm_main.c
Quoted 8 lines · Avi Kivity
Quoted 7 lines · Avi Kivity
Quoted 6 lines · Christoph Hellwig
Quoted 4 lines · Avi Kivity
From: Nguyen Anh Quynh <[email protected]>
*nopage()inkvm_main.cshould only store the type ofmmap()fault if the pointers are not NULL. This patch fixes the problem.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Care to convert it to ->faul while you're at it?
I'll add this to my todo, though not sure It'll be in time for .24. If someone sends a patch I'll apply it.
I should mention that the converting to use ->fault() is a 15-minute change; the tricky part is adding backwards compatibility for the external module package.
It should be mostly possible to ifdef a nopage() handler, which is just a wrapper function to translate arguments then call your new ->fault() handler. With luck, fault would mostly inline into nopage, and do some constant folding to make it cheaper...
I'm planning to go through and convert the rest of the in-tree users at some point soon, so if you do get a chance to convert your upstream code before I try, it would nice ;)
Thanks,
Nick
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 001/104] KVM: Fix *nopage() in kvm_main.c
Quoted 6 lines · Nick Piggin
Quoted 5 lines
I should mention that the converting to use ->fault() is a 15-minute change; the tricky part is adding backwards compatibility for the external module package.
Quoted 10 lines
It should be mostly possible to ifdef a
nopage()handler, which is just a wrapper function to translate arguments then call your new ->fault() handler. With luck, fault would mostly inline into nopage, and do some constant folding to make it cheaper...I'm planning to go through and convert the rest of the in-tree users at some point soon, so if you do get a chance to convert your upstream code before I try, it would nice ;)
In kvm I don't add compatibility #ifdefs to mainline, instead I have an awk script that massages the sources into something that all kernels can grok.
It isn't pretty but it works.
Signature · 7 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 001/104] KVM: Fix *nopage() in kvm_main.c
Quoted 10 lines · Avi Kivity
Quoted 9 lines · Nick Piggin
Quoted 3 lines
I should mention that the converting to use ->fault() is a 15-minute change; the tricky part is adding backwards compatibility for the external module package.
It should be mostly possible to ifdef a
nopage()handler, which is just a wrapper function to translate arguments then call your new ->fault() handler. With luck, fault would mostly inline into nopage, and do some constant folding to make it cheaper...
Quoted 7 lines
Quoted 3 lines
I'm planning to go through and convert the rest of the in-tree users at some point soon, so if you do get a chance to convert your upstream code before I try, it would nice ;)
In kvm I don't add compatibility #ifdefs to mainline, instead I have an awk script that massages the sources into something that all kernels can grok.
Sure, but my suggestion is just a way to make it possible without having to maintain a lot of duplicated code. The point is simply that we'll be getting rid of nopage from mainline sooner or later, and it will probably be less painful for your out of tree stuff if you do it rather than me. Maybe.
Quoted 1 line
It isn't pretty but it works.
It is pretty for mainline :) I appreciate you going out of your way to make the code nicer rather than just make your life easier.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 001/104] KVM: Fix *nopage() in kvm_main.c
Quoted 22 lines · Nick Piggin
Quoted 11 lines · Avi Kivity
Quoted 9 lines · Nick Piggin
Quoted 4 lines
I should mention that the converting to use ->fault() is a 15-minute change; the tricky part is adding backwards compatibility for the external module package.
It should be mostly possible to ifdef a
nopage()handler, which is just a wrapper function to translate arguments then call your new ->fault() handler. With luck, fault would mostly inline into nopage, and do some constant folding to make it cheaper...Quoted 8 lines
Quoted 4 lines
I'm planning to go through and convert the rest of the in-tree users at some point soon, so if you do get a chance to convert your upstream code before I try, it would nice ;)
In kvm I don't add compatibility #ifdefs to mainline, instead I have an awk script that massages the sources into something that all kernels can grok.
Quoted 6 lines
Sure, but my suggestion is just a way to make it possible without having to maintain a lot of duplicated code. The point is simply that we'll be getting rid of nopage from mainline sooner or later, and it will probably be less painful for your out of tree stuff if you do it rather than me. Maybe.
Certainly it's best done by someone familiar with the kvm external module hackery. I'll do it during 2.6.24 if no one beats me to it.
Signature · 7 lines
error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 2/104 KVM: SMP: Add vcpu_id field in struct vcpu
In reply to Avi KivityFrom: Qing He <[email protected]>
This patch adds a vcpu_id' field in struct vcpu', so we can differentiate BSP and APs without pointer comparison or arithmetic.
--- drivers/kvm/kvm.h | 1 + drivers/kvm/kvm_main.c | 1 + drivers/kvm/svm.c | 2 +- drivers/kvm/vmx.c | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-)
drivers/kvm/kvm.h +1 -0
@@ -328,6 +328,7 @@ void kvm_io_bus_register_dev(struct kvm_io_bus *bus,struct kvm_vcpu {struct kvm *kvm; +int vcpu_id;union {struct vmcs *vmcs;struct vcpu_svm *svm;
drivers/kvm/kvm_main.c +1 -0
@@ -2355,6 +2355,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n) goto out; vcpu = &kvm->vcpus[n]; + vcpu->vcpu_id = n;mutex_lock (&vcpu->mutex);
drivers/kvm/svm.c +1 -1
@@ -591,7 +591,7 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu)fx_init (vcpu); vcpu->fpu_active =1 ; vcpu->apic_base =0xfee00000 |MSR_IA32_APICBASE_ENABLE ; -if (vcpu == &vcpu->kvm->vcpus[0 ]) +if (vcpu->vcpu_id ==0 ) vcpu->apic_base |=MSR_IA32_APICBASE_BSP ;return 0 ;
drivers/kvm/vmx.c +1 -1
@@ -1253,7 +1253,7 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu) vcpu->regs[VCPU_REGS_RDX ] =get_rdx_init_val (); vcpu->cr8 =0 ; vcpu->apic_base =0xfee00000 |MSR_IA32_APICBASE_ENABLE ; -if (vcpu == &vcpu->kvm->vcpus[0 ]) +if (vcpu->vcpu_id ==0 ) vcpu->apic_base |=MSR_IA32_APICBASE_BSP ;fx_init (vcpu);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 3/104 KVM: Future-proof the exit information union ABI
In reply to Avi KivityNote that as the size of struct kvm_run is not part of the ABI, we can add things at the end.
--- include/linux/kvm.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
include/linux/kvm.h +2 -0
@@ -111,6 +111,8 @@ struct kvm_run {__u32 longmode;__u32 pad; } hypercall; +/* Fix the size of the union. */ +char padding[256 ]; }; };
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 4/104 KVM: In-kernel string pio write support
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
Add string pio write support to support some version of Windows.
--- drivers/kvm/kvm_main.c | 48 +++++++++++++++++++++++++++++++++++++----------- 1 files changed, 37 insertions(+), 11 deletions(-)
drivers/kvm/kvm_main.c +37 -11
@@ -1760,18 +1760,35 @@ static int complete_pio(struct kvm_vcpu *vcpu)return 0 ; } -void kernel_pio (struct kvm_io_device *pio_dev,struct kvm_vcpu *vcpu) +static void kernel_pio (struct kvm_io_device *pio_dev, +struct kvm_vcpu *vcpu, +void *pd) {/* TODO: String I/O for in kernel device */ if (vcpu->pio.in)kvm_iodevice_read (pio_dev, vcpu->pio.port, vcpu->pio.size, - vcpu->pio_data); + pd);else kvm_iodevice_write (pio_dev, vcpu->pio.port, vcpu->pio.size, - vcpu->pio_data); + pd); +} + +static void pio_string_write (struct kvm_io_device *pio_dev, +struct kvm_vcpu *vcpu) +{ +struct kvm_pio_request *io = &vcpu->pio; +void *pd = vcpu->pio_data; +int i; + +for (i =0 ; i < io->cur_count; i++) { +kvm_iodevice_write (pio_dev, io->port, + io->size, + pd); + pd += io->size; + } } int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
@@ -1779,7 +1796,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, gva_t address, int rep, unsigned port) { unsigned now, in_page; -int i; +int i, ret =0 ;int nr_pages =1 ;struct page *page;struct kvm_io_device *pio_dev;
@@ -1806,15 +1823,12 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,memcpy (vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX ],4 ); kvm_arch_ops->decache_regs (vcpu);if (pio_dev) { -kernel_pio (pio_dev, vcpu); +kernel_pio (pio_dev, vcpu, vcpu->pio_data);complete_pio (vcpu);return 1 ; }return 0 ; } -/* TODO: String I/O for in kernel device */ -if (pio_dev) -printk (KERN_ERR "kvm_setup_pio: no string io support\n" );if (!count) { kvm_arch_ops->skip_emulated_instruction (vcpu);
@@ -1862,9 +1876,21 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, } } -if (!vcpu->pio.in) -return pio_copy_data (vcpu); -return 0 ; +if (!vcpu->pio.in) { +/* string PIO write */ + ret =pio_copy_data (vcpu); +if (ret >=0 && pio_dev) { +pio_string_write (pio_dev, vcpu); +complete_pio (vcpu); +if (vcpu->pio.count ==0 ) + ret =1 ; + } + }else if (pio_dev) +printk (KERN_ERR "no string pio read support yet, " +"port %x size %d count %ld\n" , + port, size, count); + +return ret; }EXPORT_SYMBOL_GPL (kvm_setup_pio);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 5/104 KVM: Trivial: /dev/kvm interface is no longer experimental.
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
KVM interface is no longer experimental.
--- include/linux/kvm.h | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
include/linux/kvm.h +1 -2
@@ -4,8 +4,7 @@/* * Userspace interface for /dev/kvm - kernel based virtual machine * -* Note: this interface is considered experimental and may change without -* notice. +* Note: you must update KVM_API_VERSION if you change this interface. */ #include <asm/types.h>
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 6/104 KVM: Trivial: Remove unused struct cpu_user_regs declaration
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
--- drivers/kvm/x86_emulate.h | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/kvm/x86_emulate.h +0 -2
@@ -112,8 +112,6 @@ struct x86_emulate_ops { }; -struct cpu_user_regs ; -struct x86_emulate_ctxt {/* Register state before/after emulation. */ struct kvm_vcpu *vcpu;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 7/104 KVM: Trivial: Make decode_register() static
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
I have shied away from touching x86_emulate.c (it could definitely use some love, but it is forked from the Xen code, and it would be more productive to cross-merge fixes).
--- drivers/kvm/x86_emulate.c | 9 +++++++-- drivers/kvm/x86_emulate.h | 8 -------- 2 files changed, 7 insertions(+), 10 deletions(-)
drivers/kvm/x86_emulate.c +7 -2
@@ -443,8 +443,13 @@ struct operand { (((reg) + _inc) & ((1UL << (ad_bytes <<3 )) -1 )); \ }while (0 ) -void *decode_register(u8 modrm_reg, unsigned long *regs, - int highbyte_regs) +/* +* Given the 'reg' portion of a ModRM byte, and a register block, return a +* pointer into the block that addresses the relevant register. +* @highbyte_regs specifies whether to decode AH,CH,DH,BH. +*/ +static void *decode_register(u8 modrm_reg, unsigned long *regs, +int highbyte_regs) {void *p;
drivers/kvm/x86_emulate.h +0 -8
@@ -152,12 +152,4 @@ struct x86_emulate_ctxt {int x86_emulate_memop (struct x86_emulate_ctxt *ctxt,struct x86_emulate_ops *ops); -/* -* Given the 'reg' portion of a ModRM byte, and a register block, return a -* pointer into the block that addresses the relevant register. -* @highbyte_regs specifies whether to decode AH,CH,DH,BH. -*/ -void *decode_register (u8 modrm_reg,unsigned long *regs, -int highbyte_regs); -#endif /* __X86_EMULATE_H__ */
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 8/104 KVM: Trivial: Comment spelling may escape grep
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Speling error in comment.
--- drivers/kvm/x86_emulate.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +1 -1
@@ -6,7 +6,7 @@* Copyright (c) 2005 Keir Fraser * * Linux coding style, mod r/m decoder, segment base fixes, real-mode -* privieged instructions: +* privileged instructions: * * Copyright (C) 2006 Qumranet *
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 9/104 KVM: Trivial: Avoid hardware_disable predeclaration
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Don't pre-declare hardware_disable: shuffle the reboot hook down.
--- drivers/kvm/kvm_main.c | 40 +++++++++++++++++++--------------------- 1 files changed, 19 insertions(+), 21 deletions(-)
drivers/kvm/kvm_main.c +19 -21
@@ -54,8 +54,6 @@ static cpumask_t cpus_hardware_enabled;struct kvm_arch_ops *kvm_arch_ops; -static void hardware_disable (void *ignored); -#define STAT_OFFSET (x) offsetof(struct kvm_vcpu, stat.x) static struct kvm_stats_debugfs_item {
@@ -2924,25 +2922,6 @@ static struct miscdevice kvm_dev = { &kvm_chardev_ops, }; -static int kvm_reboot (struct notifier_block *notifier,unsigned long val, -void *v) -{ -if (val ==SYS_RESTART ) { -/* -* Some (well, at least mine) BIOSes hang on reboot if -* in vmx root mode. -*/ -printk (KERN_INFO "kvm: exiting hardware virtualization\n" ); -on_each_cpu (hardware_disable,NULL ,0 ,1 ); - } -return NOTIFY_OK ; -} - -static struct notifier_block kvm_reboot_notifier = { - .notifier_call = kvm_reboot, - .priority =0 , -}; -/* * Make sure that a cpu that is being hot-unplugged does not have any vcpus * cached on it.
@@ -3025,6 +3004,25 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,return NOTIFY_OK ; } +static int kvm_reboot (struct notifier_block *notifier,unsigned long val, +void *v) +{ +if (val ==SYS_RESTART ) { +/* +* Some (well, at least mine) BIOSes hang on reboot if +* in vmx root mode. +*/ +printk (KERN_INFO "kvm: exiting hardware virtualization\n" ); +on_each_cpu (hardware_disable,NULL ,0 ,1 ); + } +return NOTIFY_OK ; +} + +static struct notifier_block kvm_reboot_notifier = { + .notifier_call = kvm_reboot, + .priority =0 , +}; +void kvm_io_bus_init (struct kvm_io_bus *bus) {memset (bus,0 ,sizeof (*bus));
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 10/104 KVM: Trivial: Use standard CR0 flags macros from asm/cpu-features.h
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
The kernel now has asm/cpu-features.h: use those macros instead of inventing our own.
Also spell out definition of CR0_RESEVED_BITS (no code change) and fix typo.
--- drivers/kvm/kvm.h | 19 +++++-------------- drivers/kvm/kvm_main.c | 15 +++++++++------ drivers/kvm/mmu.c | 2 +- drivers/kvm/svm.c | 20 ++++++++++---------- drivers/kvm/vmx.c | 22 +++++++++++----------- 5 files changed, 36 insertions(+), 42 deletions(-)
drivers/kvm/kvm.h +5 -14
@@ -19,15 +19,6 @@#include <linux/kvm.h> #include <linux/kvm_para.h> -#define CR0_PE_MASK (1ULL << 0) -#define CR0_MP_MASK (1ULL << 1) -#define CR0_TS_MASK (1ULL << 3) -#define CR0_NE_MASK (1ULL << 5) -#define CR0_WP_MASK (1ULL << 16) -#define CR0_NW_MASK (1ULL << 29) -#define CR0_CD_MASK (1ULL << 30) -#define CR0_PG_MASK (1ULL << 31) -#define CR3_WPT_MASK (1ULL << 3)#define CR3_PCD_MASK (1ULL << 4)
@@ -42,11 +33,11 @@#define CR4_VMXE_MASK (1ULL << 13)#define KVM_GUEST_CR0_MASK \ - (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK \ - | CR0_NW_MASK | CR0_CD_MASK) + (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE \ + | X86_CR0_NW | X86_CR0_CD)#define KVM_VM_CR0_ALWAYS_ON \ - (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK | CR0_TS_MASK \ - | CR0_MP_MASK) + (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE | X86_CR0_TS \ + | X86_CR0_MP)#define KVM_GUEST_CR4_MASK \ (CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK)#define KVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK)
@@ -667,7 +658,7 @@ static inline int is_pse(struct kvm_vcpu *vcpu)static inline int is_paging (struct kvm_vcpu *vcpu) { -return vcpu->cr0 &CR0_PG_MASK ; +return vcpu->cr0 &X86_CR0_PG ; }static inline int memslot_id (struct kvm *kvm,struct kvm_memory_slot *slot)
drivers/kvm/kvm_main.c +9 -6
@@ -82,7 +82,10 @@ static struct dentry *debugfs_dir;#define MAX_IO_MSRS 256 -#define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL +#define CR0_RESERVED_BITS \ + (~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \ + | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM \ + | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG))#define LMSW_GUEST_MASK 0x0eULL#define CR4_RESEVED_BITS (~((1ULL << 11) - 1))#define CR8_RESEVED_BITS (~0x0fULL)
@@ -466,27 +469,27 @@ out:void set_cr0 (struct kvm_vcpu *vcpu,unsigned long cr0) { -if (cr0 &CR0_RESEVED_BITS ) { +if (cr0 &CR0_RESERVED_BITS ) {printk (KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n" , cr0, vcpu->cr0);inject_gp (vcpu);return ; } -if ((cr0 &CR0_NW_MASK ) && !(cr0 &CR0_CD_MASK )) { +if ((cr0 &X86_CR0_NW ) && !(cr0 &X86_CR0_CD )) {printk (KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n" );inject_gp (vcpu);return ; } -if ((cr0 &CR0_PG_MASK ) && !(cr0 &CR0_PE_MASK )) { +if ((cr0 &X86_CR0_PG ) && !(cr0 &X86_CR0_PE )) {printk (KERN_DEBUG "set_cr0: #GP, set PG flag " "and a clear PE flag\n" );inject_gp (vcpu);return ; } -if (!is_paging (vcpu) && (cr0 &CR0_PG_MASK )) { +if (!is_paging (vcpu) && (cr0 &X86_CR0_PG )) {#ifdef CONFIG_X86_64 if ((vcpu->shadow_efer &EFER_LME )) {int cs_db, cs_l;
@@ -1158,7 +1161,7 @@ int emulate_clts(struct kvm_vcpu *vcpu) {unsigned long cr0; - cr0 = vcpu->cr0 & ~CR0_TS_MASK ; + cr0 = vcpu->cr0 & ~X86_CR0_TS ; kvm_arch_ops->set_cr0 (vcpu, cr0);return X86EMUL_CONTINUE ; }
drivers/kvm/mmu.c +1 -1
@@ -158,7 +158,7 @@ static struct kmem_cache *mmu_page_header_cache;static int is_write_protection (struct kvm_vcpu *vcpu) { -return vcpu->cr0 &CR0_WP_MASK ; +return vcpu->cr0 &X86_CR0_WP ; }static int is_cpuid_PSE36 (void )
drivers/kvm/svm.c +10 -10
@@ -99,7 +99,7 @@ static unsigned get_addr_size(struct kvm_vcpu *vcpu)struct vmcb_save_area *sa = &vcpu->svm->vmcb->save;u16 cs_attrib; -if (!(sa->cr0 &CR0_PE_MASK ) || (sa->rflags &X86_EFLAGS_VM )) +if (!(sa->cr0 &X86_CR0_PE ) || (sa->rflags &X86_EFLAGS_VM ))return 2 ; cs_attrib = sa->cs.attrib;
@@ -563,7 +563,7 @@ static void init_vmcb(struct vmcb *vmcb)* cr0 val on cpu init should be 0x60000010, we enable cpu * cache by default. the orderly way is to enable cache in bios. */ - save->cr0 =0x00000010 |CR0_PG_MASK |CR0_WP_MASK ; + save->cr0 =0x00000010 |X86_CR0_PG |X86_CR0_WP ; save->cr4 =CR4_PAE_MASK ;/* rdx = ?? */ }
@@ -756,25 +756,25 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) {#ifdef CONFIG_X86_64 if (vcpu->shadow_efer &KVM_EFER_LME ) { -if (!is_paging (vcpu) && (cr0 &CR0_PG_MASK )) { +if (!is_paging (vcpu) && (cr0 &X86_CR0_PG )) { vcpu->shadow_efer |=KVM_EFER_LMA ; vcpu->svm->vmcb->save.efer |=KVM_EFER_LMA |KVM_EFER_LME ; } -if (is_paging (vcpu) && !(cr0 &CR0_PG_MASK ) ) { +if (is_paging (vcpu) && !(cr0 &X86_CR0_PG ) ) { vcpu->shadow_efer &= ~KVM_EFER_LMA ; vcpu->svm->vmcb->save.efer &= ~(KVM_EFER_LMA |KVM_EFER_LME ); } }#endif -if ((vcpu->cr0 &CR0_TS_MASK ) && !(cr0 &CR0_TS_MASK )) { +if ((vcpu->cr0 &X86_CR0_TS ) && !(cr0 &X86_CR0_TS )) { vcpu->svm->vmcb->control.intercept_exceptions &= ~(1 <<NM_VECTOR ); vcpu->fpu_active =1 ; } vcpu->cr0 = cr0; - cr0 |=CR0_PG_MASK |CR0_WP_MASK ; - cr0 &= ~(CR0_CD_MASK |CR0_NW_MASK ); + cr0 |=X86_CR0_PG |X86_CR0_WP ; + cr0 &= ~(X86_CR0_CD |X86_CR0_NW ); vcpu->svm->vmcb->save.cr0 = cr0; }
@@ -945,8 +945,8 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)static int nm_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { vcpu->svm->vmcb->control.intercept_exceptions &= ~(1 <<NM_VECTOR ); -if (!(vcpu->cr0 &CR0_TS_MASK )) - vcpu->svm->vmcb->save.cr0 &= ~CR0_TS_MASK ; +if (!(vcpu->cr0 &X86_CR0_TS )) + vcpu->svm->vmcb->save.cr0 &= ~X86_CR0_TS ; vcpu->fpu_active =1 ;return 1 ;
@@ -1702,7 +1702,7 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)if (vcpu->fpu_active) { vcpu->svm->vmcb->control.intercept_exceptions |= (1 <<NM_VECTOR ); - vcpu->svm->vmcb->save.cr0 |=CR0_TS_MASK ; + vcpu->svm->vmcb->save.cr0 |=X86_CR0_TS ; vcpu->fpu_active =0 ; } }
drivers/kvm/vmx.c +11 -11
@@ -436,9 +436,9 @@ static void vmx_fpu_activate(struct kvm_vcpu *vcpu)if (vcpu->fpu_active)return ; vcpu->fpu_active =1 ; -vmcs_clear_bits (GUEST_CR0 ,CR0_TS_MASK ); -if (vcpu->cr0 &CR0_TS_MASK ) -vmcs_set_bits (GUEST_CR0 ,CR0_TS_MASK ); +vmcs_clear_bits (GUEST_CR0 ,X86_CR0_TS ); +if (vcpu->cr0 &X86_CR0_TS ) +vmcs_set_bits (GUEST_CR0 ,X86_CR0_TS );update_exception_bitmap (vcpu); }
@@ -447,7 +447,7 @@ static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)if (!vcpu->fpu_active)return ; vcpu->fpu_active =0 ; -vmcs_set_bits (GUEST_CR0 ,CR0_TS_MASK ); +vmcs_set_bits (GUEST_CR0 ,X86_CR0_TS );update_exception_bitmap (vcpu); }
@@ -1002,17 +1002,17 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) {vmx_fpu_deactivate (vcpu); -if (vcpu->rmode.active && (cr0 &CR0_PE_MASK )) +if (vcpu->rmode.active && (cr0 &X86_CR0_PE ))enter_pmode (vcpu); -if (!vcpu->rmode.active && !(cr0 &CR0_PE_MASK )) +if (!vcpu->rmode.active && !(cr0 &X86_CR0_PE ))enter_rmode (vcpu);#ifdef CONFIG_X86_64 if (vcpu->shadow_efer &EFER_LME ) { -if (!is_paging (vcpu) && (cr0 &CR0_PG_MASK )) +if (!is_paging (vcpu) && (cr0 &X86_CR0_PG ))enter_lmode (vcpu); -if (is_paging (vcpu) && !(cr0 &CR0_PG_MASK )) +if (is_paging (vcpu) && !(cr0 &X86_CR0_PG ))exit_lmode (vcpu); }#endif
@@ -1022,14 +1022,14 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON); vcpu->cr0 = cr0; -if (!(cr0 &CR0_TS_MASK ) || !(cr0 &CR0_PE_MASK )) +if (!(cr0 &X86_CR0_TS ) || !(cr0 &X86_CR0_PE ))vmx_fpu_activate (vcpu); }static void vmx_set_cr3 (struct kvm_vcpu *vcpu,unsigned long cr3) {vmcs_writel (GUEST_CR3 , cr3); -if (vcpu->cr0 &CR0_PE_MASK ) +if (vcpu->cr0 &X86_CR0_PE )vmx_fpu_deactivate (vcpu); }
@@ -1778,7 +1778,7 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)case 2 :/* clts */ vcpu_load_rsp_rip (vcpu);vmx_fpu_deactivate (vcpu); - vcpu->cr0 &= ~CR0_TS_MASK ; + vcpu->cr0 &= ~X86_CR0_TS ;vmcs_writel (CR0_READ_SHADOW , vcpu->cr0);vmx_fpu_activate (vcpu);skip_emulated_instruction (vcpu);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 11/104 KVM: Use standard CR3 flags, tighten checking
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
The kernel now has asm/cpu-features.h: use those macros instead of inventing our own.
Also spell out definition of CR3_RESEVED_BITS, fix spelling and tighten it for the non-PAE case.
--- drivers/kvm/kvm.h | 9 +++------ drivers/kvm/kvm_main.c | 33 +++++++++++++++++++++------------ drivers/kvm/paging_tmpl.h | 2 +- 3 files changed, 25 insertions(+), 19 deletions(-)
drivers/kvm/kvm.h +3 -6
@@ -19,12 +19,9 @@#include <linux/kvm.h> #include <linux/kvm_para.h> -#define CR3_WPT_MASK (1ULL << 3) -#define CR3_PCD_MASK (1ULL << 4) - -#define CR3_RESEVED_BITS 0x07ULL -#define CR3_L_MODE_RESEVED_BITS (~((1ULL << 40) - 1) | 0x0fe7ULL) -#define CR3_FLAGS_MASK ((1ULL << 5) - 1) +#define CR3_PAE_RESERVED_BITS ((X86_CR3_PWT | X86_CR3_PCD) - 1) +#define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | X86_CR3_PCD)) +#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS|0xFFFFFF0000000000ULL)#define CR4_VME_MASK (1ULL << 0)#define CR4_PSE_MASK (1ULL << 4)
drivers/kvm/kvm_main.c +21 -12
@@ -571,23 +571,32 @@ EXPORT_SYMBOL_GPL(set_cr4);void set_cr3 (struct kvm_vcpu *vcpu,unsigned long cr3) {if (is_long_mode (vcpu)) { -if (cr3 &CR3_L_MODE_RESEVED_BITS ) { +if (cr3 &CR3_L_MODE_RESERVED_BITS ) {printk (KERN_DEBUG "set_cr3: #GP, reserved bits\n" );inject_gp (vcpu);return ; } }else { -if (cr3 &CR3_RESEVED_BITS ) { -printk (KERN_DEBUG "set_cr3: #GP, reserved bits\n" ); -inject_gp (vcpu); -return ; - } -if (is_paging (vcpu) &&is_pae (vcpu) && - !load_pdptrs (vcpu, cr3)) { -printk (KERN_DEBUG "set_cr3: #GP, pdptrs " -"reserved bits\n" ); -inject_gp (vcpu); -return ; +if (is_pae (vcpu)) { +if (cr3 &CR3_PAE_RESERVED_BITS ) { +printk (KERN_DEBUG +"set_cr3: #GP, reserved bits\n" ); +inject_gp (vcpu); +return ; + } +if (is_paging (vcpu) && !load_pdptrs (vcpu, cr3)) { +printk (KERN_DEBUG "set_cr3: #GP, pdptrs " +"reserved bits\n" ); +inject_gp (vcpu); +return ; + } + }else { +if (cr3 &CR3_NONPAE_RESERVED_BITS ) { +printk (KERN_DEBUG +"set_cr3: #GP, reserved bits\n" ); +inject_gp (vcpu); +return ; + } } }
drivers/kvm/paging_tmpl.h +1 -1
@@ -99,7 +99,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker, walker->table =kmap_atomic (pfn_to_page (hpa >>PAGE_SHIFT ),KM_USER0 );ASSERT ((!is_long_mode (vcpu) &&is_pae (vcpu)) || - (vcpu->cr3 & ~(PAGE_MASK |CR3_FLAGS_MASK )) ==0 ); + (vcpu->cr3 &CR3_NONPAE_RESERVED_BITS ) ==0 ); walker->inherited_ar =PT_USER_MASK |PT_WRITABLE_MASK ;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 12/104 KVM: Use standard CR4 flags, tighten checking
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
On this machine (Intel), writing to the CR4 bits 0x00000800 and 0x00001000 cause a GPF. The Intel manual is a little unclear, but AFIACT they're reserved, too.
Also fix spelling of CR4_RESEVED_BITS.
--- drivers/kvm/kvm.h | 16 +++++----------- drivers/kvm/kvm_main.c | 16 ++++++++++------ drivers/kvm/svm.c | 7 +++---- drivers/kvm/vmx.c | 8 ++++---- drivers/kvm/vmx.h | 2 -- 5 files changed, 22 insertions(+), 27 deletions(-)
drivers/kvm/kvm.h +5 -11
@@ -23,12 +23,6 @@#define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | X86_CR3_PCD))#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS|0xFFFFFF0000000000ULL) -#define CR4_VME_MASK (1ULL << 0) -#define CR4_PSE_MASK (1ULL << 4) -#define CR4_PAE_MASK (1ULL << 5) -#define CR4_PGE_MASK (1ULL << 7) -#define CR4_VMXE_MASK (1ULL << 13) -#define KVM_GUEST_CR0_MASK \ (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE \ | X86_CR0_NW | X86_CR0_CD)
@@ -36,9 +30,9 @@ (X86_CR0_PG |X86_CR0_PE |X86_CR0_WP |X86_CR0_NE |X86_CR0_TS \ | X86_CR0_MP)#define KVM_GUEST_CR4_MASK \ - (CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK) -#define KVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK) -#define KVM_RMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK | CR4_VME_MASK) + (X86_CR4_VME | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE | X86_CR4_VMXE) +#define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE) +#define KVM_RMODE_VM_CR4_ALWAYS_ON (X86_CR4_VME | X86_CR4_PAE | X86_CR4_VMXE)#define INVALID_PAGE (~(hpa_t)0)#define UNMAPPED_GVA (~(gpa_t)0)
@@ -645,12 +639,12 @@ static inline int is_long_mode(struct kvm_vcpu *vcpu)static inline int is_pae (struct kvm_vcpu *vcpu) { -return vcpu->cr4 &CR4_PAE_MASK ; +return vcpu->cr4 &X86_CR4_PAE ; }static inline int is_pse (struct kvm_vcpu *vcpu) { -return vcpu->cr4 &CR4_PSE_MASK ; +return vcpu->cr4 &X86_CR4_PSE ; }static inline int is_paging (struct kvm_vcpu *vcpu)
drivers/kvm/kvm_main.c +10 -6
@@ -86,8 +86,12 @@ static struct dentry *debugfs_dir; (~(unsigned long )(X86_CR0_PE |X86_CR0_MP |X86_CR0_EM |X86_CR0_TS \ |X86_CR0_ET |X86_CR0_NE |X86_CR0_WP |X86_CR0_AM \ | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG)) -#define LMSW_GUEST_MASK 0x0eULL -#define CR4_RESEVED_BITS (~((1ULL << 11) - 1)) +#define CR4_RESERVED_BITS \ + (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\ + | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ + | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR \ + | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE)) +#define CR8_RESEVED_BITS (~0x0fULL)#define EFER_RESERVED_BITS 0xfffffffffffff2fe
@@ -537,26 +541,26 @@ EXPORT_SYMBOL_GPL(lmsw);void set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4) { -if (cr4 &CR4_RESEVED_BITS ) { +if (cr4 &CR4_RESERVED_BITS ) {printk (KERN_DEBUG "set_cr4: #GP, reserved bits\n" );inject_gp (vcpu);return ; }if (is_long_mode (vcpu)) { -if (!(cr4 &CR4_PAE_MASK )) { +if (!(cr4 &X86_CR4_PAE )) {printk (KERN_DEBUG "set_cr4: #GP, clearing PAE while " "in long mode\n" );inject_gp (vcpu);return ; } - }else if (is_paging (vcpu) && !is_pae (vcpu) && (cr4 &CR4_PAE_MASK ) + }else if (is_paging (vcpu) && !is_pae (vcpu) && (cr4 &X86_CR4_PAE ) && !load_pdptrs (vcpu, vcpu->cr3)) {printk (KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n" );inject_gp (vcpu); } -if (cr4 &CR4_VMXE_MASK ) { +if (cr4 &X86_CR4_VMXE ) {printk (KERN_DEBUG "set_cr4: #GP, setting VMXE\n" );inject_gp (vcpu);return ;
drivers/kvm/svm.c +3 -4
@@ -38,7 +38,6 @@ MODULE_LICENSE("GPL");#define DR7_GD_MASK (1 << 13)#define DR6_BD_MASK (1 << 13) -#define CR4_DE_MASK (1UL << 3)#define SEG_TYPE_LDT 2#define SEG_TYPE_BUSY_TSS16 3
@@ -564,7 +563,7 @@ static void init_vmcb(struct vmcb *vmcb)* cache by default. the orderly way is to enable cache in bios. */ save->cr0 =0x00000010 |X86_CR0_PG |X86_CR0_WP ; - save->cr4 =CR4_PAE_MASK ; + save->cr4 =X86_CR4_PAE ;/* rdx = ?? */ }
@@ -781,7 +780,7 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)static void svm_set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4) { vcpu->cr4 = cr4; - vcpu->svm->vmcb->save.cr4 = cr4 |CR4_PAE_MASK ; + vcpu->svm->vmcb->save.cr4 = cr4 |X86_CR4_PAE ; } static void svm_set_segment(struct kvm_vcpu *vcpu,
@@ -877,7 +876,7 @@ static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value, vcpu->svm->db_regs[dr] = value;return ; case 4 ... 5: -if (vcpu->cr4 &CR4_DE_MASK ) { +if (vcpu->cr4 &X86_CR4_DE ) { *exception =UD_VECTOR ;return ; }
drivers/kvm/vmx.c +4 -4
@@ -764,7 +764,7 @@ static void hardware_enable(void *garbage)if ((old &5 ) !=5 )/* enable and lock */ wrmsrl (MSR_IA32_FEATURE_CONTROL , old |5 ); -write_cr4 (read_cr4 () |CR4_VMXE );/* FIXME: not cpu hotplug safe */ +write_cr4 (read_cr4 () |X86_CR4_VMXE );/* FIXME: not cpu hotplug safe */ asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr), "m"(phys_addr) : "memory", "cc"); }
@@ -879,8 +879,8 @@ static void enter_pmode(struct kvm_vcpu *vcpu) flags |= (vcpu->rmode.save_iopl <<IOPL_SHIFT );vmcs_writel (GUEST_RFLAGS , flags); -vmcs_writel (GUEST_CR4 , (vmcs_readl (GUEST_CR4 ) & ~CR4_VME_MASK ) | - (vmcs_readl (CR4_READ_SHADOW ) &CR4_VME_MASK )); +vmcs_writel (GUEST_CR4 , (vmcs_readl (GUEST_CR4 ) & ~X86_CR4_VME ) | + (vmcs_readl (CR4_READ_SHADOW ) &X86_CR4_VME ));update_exception_bitmap (vcpu);
@@ -937,7 +937,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu) flags |=IOPL_MASK |X86_EFLAGS_VM ;vmcs_writel (GUEST_RFLAGS , flags); -vmcs_writel (GUEST_CR4 ,vmcs_readl (GUEST_CR4 ) |CR4_VME_MASK ); +vmcs_writel (GUEST_CR4 ,vmcs_readl (GUEST_CR4 ) |X86_CR4_VME );update_exception_bitmap (vcpu);vmcs_write16 (GUEST_SS_SELECTOR ,vmcs_readl (GUEST_SS_BASE ) >>4 );
drivers/kvm/vmx.h +0 -2
@@ -285,8 +285,6 @@ enum vmcs_field {#define AR_RESERVD_MASK 0xfffe0f00 -#define CR4_VMXE 0x2000 -#define MSR_IA32_VMX_BASIC 0x480#define MSR_IA32_FEATURE_CONTROL 0x03a#define MSR_IA32_VMX_PINBASED_CTLS 0x481
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 13/104 KVM: Trivial: Use standard BITMAP macros, open-code userspace-exposed header
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Creating one's own BITMAP macro seems suboptimal: if we use manual arithmetic in the one place exposed to userspace, we can use standard macros elsewhere.
--- drivers/kvm/kvm.h | 3 +-- drivers/kvm/kvm_main.c | 2 +- include/linux/kvm.h | 10 ++-------- 3 files changed, 4 insertions(+), 11 deletions(-)
drivers/kvm/kvm.h +1 -2
@@ -324,8 +324,7 @@ struct kvm_vcpu {int guest_mode;unsigned long requests;unsigned long irq_summary;/* bit vector: 1 per word in irq_pending */ -#define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long) -unsigned long irq_pending[NR_IRQ_WORDS ]; +DECLARE_BITMAP (irq_pending,KVM_NR_INTERRUPTS );unsigned long regs[NR_VCPU_REGS ];/* for rsp: vcpu_load_rsp_rip() */ unsigned long rip;/* needs vcpu_load_rsp_rip() */
drivers/kvm/kvm_main.c +1 -1
@@ -2130,7 +2130,7 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,memcpy (vcpu->irq_pending, sregs->interrupt_bitmap,sizeof vcpu->irq_pending); vcpu->irq_summary =0 ; -for (i =0 ; i <NR_IRQ_WORDS ; ++i) +for (i =0 ; i <ARRAY_SIZE (vcpu->irq_pending); ++i)if (vcpu->irq_pending[i])__set_bit (i, &vcpu->irq_summary);
include/linux/kvm.h +2 -8
@@ -12,14 +12,8 @@#define KVM_API_VERSION 12 -/* -* Architectural interrupt line count, and the size of the bitmap needed -* to hold them. -*/ +/* Architectural interrupt line count. */ #define KVM_NR_INTERRUPTS 256 -#define KVM_IRQ_BITMAP_SIZE_BYTES ((KVM_NR_INTERRUPTS + 7) / 8) -#define KVM_IRQ_BITMAP_SIZE (type) (KVM_IRQ_BITMAP_SIZE_BYTES / sizeof(type)) -/* for KVM_CREATE_MEMORY_REGION */ struct kvm_memory_region {
@@ -165,7 +159,7 @@ struct kvm_sregs {__u64 cr0, cr2, cr3, cr4, cr8;__u64 efer;__u64 apic_base; -__u64 interrupt_bitmap[KVM_IRQ_BITMAP_SIZE (__u64)]; +__u64 interrupt_bitmap[(KVM_NR_INTERRUPTS +63 ) /64 ]; };struct kvm_msr_entry {
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 14/104 KVM: Set exit_reason to KVM_EXIT_MMIO where run->mmio is initialized.
In reply to Avi KivityFrom: Jeff Dike <[email protected]>
--- drivers/kvm/kvm_main.c | 2 +- drivers/kvm/svm.c | 1 - drivers/kvm/vmx.c | 1 - 3 files changed, 1 insertions(+), 3 deletions(-)
drivers/kvm/kvm_main.c +1 -1
@@ -1276,6 +1276,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu, r =x86_emulate_memop (&emulate_ctxt, &emulate_ops);if ((r || vcpu->mmio_is_write) && run) { + run->exit_reason =KVM_EXIT_MMIO ; run->mmio.phys_addr = vcpu->mmio_phys_addr;memcpy (run->mmio.data, vcpu->mmio_data,8 ); run->mmio.len = vcpu->mmio_size;
@@ -1937,7 +1938,6 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)/* * Read-modify-write. Back to userspace. */ - kvm_run->exit_reason =KVM_EXIT_MMIO ; r =0 ; goto out; }
drivers/kvm/svm.c +0 -1
@@ -928,7 +928,6 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)return 1 ;case EMULATE_DO_MMIO : ++vcpu->stat.mmio_exits; - kvm_run->exit_reason =KVM_EXIT_MMIO ;return 0 ;case EMULATE_FAIL :vcpu_printf (vcpu,"%s: emulate fail\n" , __FUNCTION__);
drivers/kvm/vmx.c +0 -1
@@ -1610,7 +1610,6 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)return 1 ;case EMULATE_DO_MMIO : ++vcpu->stat.mmio_exits; - kvm_run->exit_reason =KVM_EXIT_MMIO ;return 0 ;case EMULATE_FAIL :vcpu_printf (vcpu,"%s: emulate fail\n" , __FUNCTION__);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 15/104 KVM: Use standard CR8 flags, and fix TPR definition
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Intel manual (and KVM definition) say the TPR is 4 bits wide. Also fix CR8_RESEVED_BITS typo.
--- drivers/kvm/kvm_main.c | 4 ++-- include/asm-i386/processor-flags.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/kvm/kvm_main.c +2 -2
@@ -92,7 +92,7 @@ static struct dentry *debugfs_dir; | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR \ | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE)) -#define CR8_RESEVED_BITS (~0x0fULL) +#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)#define EFER_RESERVED_BITS 0xfffffffffffff2fe#ifdef CONFIG_X86_64
@@ -625,7 +625,7 @@ EXPORT_SYMBOL_GPL(set_cr3);void set_cr8 (struct kvm_vcpu *vcpu,unsigned long cr8) { -if ( cr8 &CR8_RESEVED_BITS ) { +if (cr8 &CR8_RESERVED_BITS ) {printk (KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n" , cr8);inject_gp (vcpu);return ;
include/asm-i386/processor-flags.h +1 -1
@@ -63,7 +63,7 @@/* * x86-64 Task Priority Register, CR8 */ -#define X86_CR8_TPR 0x00000007/* task priority register */ +#define X86_CR8_TPR 0x0000000F/* task priority register */ /* * AMD and Transmeta use MSRs for configuration; see <asm/msr-index.h>
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 16/104 KVM: x86 emulator: fix cmov for writeback changes
In reply to Avi KivityThe writeback fixes (02c03a326a5df825cc01de426f72e160db2b9538) broke cmov emulation. Fix.
--- drivers/kvm/x86_emulate.c | 22 +++++++++++----------- 1 files changed, 11 insertions(+), 11 deletions(-)
drivers/kvm/x86_emulate.c +11 -11
@@ -1235,40 +1235,40 @@ twobyte_insn:break ; case 0x40 ... 0x4f: /* cmov */ dst.val = dst.orig_val = src.val; - d &= ~Mov;/* default to no move */ + no_wb =1 ;/* * First, assume we're decoding an even cmov opcode * (lsb == 0). */ switch ((b &15 ) >>1 ) {case 0 :/* cmovo */ - d |= (_eflags &EFLG_OF ) ? Mov :0 ; + no_wb = (_eflags &EFLG_OF ) ?0 :1 ;break ;case 1 :/* cmovb/cmovc/cmovnae */ - d |= (_eflags &EFLG_CF ) ? Mov :0 ; + no_wb = (_eflags &EFLG_CF ) ?0 :1 ;break ;case 2 :/* cmovz/cmove */ - d |= (_eflags &EFLG_ZF ) ? Mov :0 ; + no_wb = (_eflags &EFLG_ZF ) ?0 :1 ;break ;case 3 :/* cmovbe/cmovna */ - d |= (_eflags & (EFLG_CF |EFLG_ZF )) ? Mov :0 ; + no_wb = (_eflags & (EFLG_CF |EFLG_ZF )) ?0 :1 ;break ;case 4 :/* cmovs */ - d |= (_eflags &EFLG_SF ) ? Mov :0 ; + no_wb = (_eflags &EFLG_SF ) ?0 :1 ;break ;case 5 :/* cmovp/cmovpe */ - d |= (_eflags &EFLG_PF ) ? Mov :0 ; + no_wb = (_eflags &EFLG_PF ) ?0 :1 ;break ;case 7 :/* cmovle/cmovng */ - d |= (_eflags &EFLG_ZF ) ? Mov :0 ; + no_wb = (_eflags &EFLG_ZF ) ?0 :1 ;/* fall through */ case 6 :/* cmovl/cmovnge */ - d |= (!(_eflags &EFLG_SF ) != - !(_eflags &EFLG_OF )) ? Mov :0 ; + no_wb &= (!(_eflags &EFLG_SF ) != + !(_eflags &EFLG_OF )) ?0 :1 ;break ; }/* Odd cmov opcodes (lsb == 1) have inverted sense. */ - d ^= (b &1 ) ? Mov :0 ; + no_wb ^= b &1 ;break ; case 0xb0 ... 0xb1: /* cmpxchg *//*
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 17/104 KVM: x86 emulator: fix faulty check for two-byte opcode
In reply to Avi KivityRight now, the bug is harmless as we never emulate one-byte 0xb6 or 0xb7. But things may change.
Noted by the mysterious Gabriel C.
--- drivers/kvm/x86_emulate.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +1 -1
@@ -819,7 +819,7 @@ done_prefixes:case DstReg: dst.type =OP_REG ;if ((d & ByteOp) - && !(twobyte_table && (b ==0xb6 || b ==0xb7 ))) { + && !(twobyte && (b ==0xb6 || b ==0xb7 ))) { dst.ptr =decode_register (modrm_reg, _regs, (rex_prefix ==0 )); dst.val = *(u8 *) dst.ptr;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 18/104 KVM: Return if the pdptrs are invalid when the guest turns on PAE.
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Don't fall through and turn on PAE in this case.
--- drivers/kvm/kvm_main.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +1 -0
@@ -558,6 +558,7 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) && !load_pdptrs(vcpu, vcpu->cr3)) {printk (KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n" );inject_gp (vcpu); +return ; }if (cr4 &X86_CR4_VMXE ) {
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 19/104 KVM: Hoist kvm_mmu_reload() out of the critical section
In reply to Avi KivityFrom: Shaohua Li <[email protected]>
vmx_cpu_run doesn't handle error correctly and kvm_mmu_reload might sleep with mutex changes, so I move it above.
--- drivers/kvm/vmx.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
drivers/kvm/vmx.c +4 -4
@@ -1999,16 +1999,16 @@ preempted:kvm_guest_debug_pre (vcpu); again: + r =kvm_mmu_reload (vcpu); +if (unlikely (r)) + goto out; +if (!vcpu->mmio_read_completed)do_interrupt_requests (vcpu, kvm_run);vmx_save_host_state (vcpu);kvm_load_guest_fpu (vcpu); - r =kvm_mmu_reload (vcpu); -if (unlikely (r)) - goto out; -/* * Loading guest fpu may have cleared host cr0.ts */
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 20/104 KVM: Move gfn_to_page out of kmap/unmap pairs
In reply to Avi KivityFrom: Shaohua Li <[email protected]>
gfn_to_page might sleep with swap support. Move it out of the kmap calls.
--- drivers/kvm/kvm.h | 2 +- drivers/kvm/kvm_main.c | 7 ++-- drivers/kvm/mmu.c | 2 +- drivers/kvm/paging_tmpl.h | 80 ++++++++++++++++++++++++++------------------ 4 files changed, 52 insertions(+), 39 deletions(-)
drivers/kvm/kvm.h +1 -1
@@ -599,7 +599,7 @@ int kvm_write_guest(struct kvm_vcpu *vcpu,unsigned long segment_base (u16 selector);void kvm_mmu_pte_write (struct kvm_vcpu *vcpu,gpa_t gpa, -const u8 *old,const u8 *new,int bytes); +const u8 *new,int bytes);int kvm_mmu_unprotect_page_virt (struct kvm_vcpu *vcpu,gva_t gva);void __kvm_mmu_free_some_pages (struct kvm_vcpu *vcpu);int kvm_mmu_load (struct kvm_vcpu *vcpu);
drivers/kvm/kvm_main.c +3 -4
@@ -1076,7 +1076,6 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, {struct page *page;void *virt; -unsigned offset =offset_in_page (gpa);if (((gpa + bytes -1 ) >>PAGE_SHIFT ) != (gpa >>PAGE_SHIFT ))return 0 ;
@@ -1085,7 +1084,7 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,return 0 ;mark_page_dirty (vcpu->kvm, gpa >>PAGE_SHIFT ); virt =kmap_atomic (page,KM_USER0 ); -kvm_mmu_pte_write (vcpu, gpa, virt + offset, val, bytes); +kvm_mmu_pte_write (vcpu, gpa, val, bytes);memcpy (virt +offset_in_page (gpa), val, bytes);kunmap_atomic (virt,KM_USER0 );return 1 ;
@@ -1455,7 +1454,7 @@ static int vcpu_register_para(struct kvm_vcpu *vcpu, gpa_t para_state_gpa)mark_page_dirty (vcpu->kvm, para_state_gpa >>PAGE_SHIFT ); para_state_page =pfn_to_page (para_state_hpa >>PAGE_SHIFT ); - para_state =kmap_atomic (para_state_page,KM_USER0 ); + para_state =kmap (para_state_page);printk (KERN_DEBUG ".... guest version: %d\n" , para_state->guest_version);printk (KERN_DEBUG ".... size: %d\n" , para_state->size);
@@ -1491,7 +1490,7 @@ static int vcpu_register_para(struct kvm_vcpu *vcpu, gpa_t para_state_gpa) para_state->ret =0 ; err_kunmap_skip: -kunmap_atomic (para_state,KM_USER0 ); +kunmap (para_state_page);return 0 ; err_gp:return 1 ;
drivers/kvm/mmu.c +1 -1
@@ -1124,7 +1124,7 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, }void kvm_mmu_pte_write (struct kvm_vcpu *vcpu,gpa_t gpa, -const u8 *old,const u8 *new,int bytes) +const u8 *new,int bytes) {gfn_t gfn = gpa >>PAGE_SHIFT ;struct kvm_mmu_page *page;
drivers/kvm/paging_tmpl.h +47 -33
227 lines not on this page · raw message
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 21/104 KVM: VMX: Import some constants of vmcs from IA32 SDM
In reply to Avi KivityFrom: Yang, Sheng <[email protected]>
This patch mainly imports some constants and rename two exist constants of vmcs according to IA32 SDM.
It also adds two constants to indicate Lock bit and Enable bit in MSR_IA32_FEATURE_CONTROL, and replace the hardcode _5_ with these two bits.
--- drivers/kvm/vmx.c | 16 +++++++++--- drivers/kvm/vmx.h | 69 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 30 deletions(-)
drivers/kvm/vmx.c +12 -4
@@ -751,7 +751,10 @@ static __init int vmx_disabled_by_bios(void)u64 msr;rdmsrl (MSR_IA32_FEATURE_CONTROL , msr); -return (msr &5 ) ==1 ;/* locked but not enabled */ +return (msr & (MSR_IA32_FEATURE_CONTROL_LOCKED | +MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED )) + ==MSR_IA32_FEATURE_CONTROL_LOCKED ; +/* locked but not enabled */ }static void hardware_enable (void *garbage)
@@ -761,9 +764,14 @@ static void hardware_enable(void *garbage)u64 old;rdmsrl (MSR_IA32_FEATURE_CONTROL , old); -if ((old &5 ) !=5 ) +if ((old & (MSR_IA32_FEATURE_CONTROL_LOCKED | +MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED )) + != (MSR_IA32_FEATURE_CONTROL_LOCKED | +MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED ))/* enable and lock */ -wrmsrl (MSR_IA32_FEATURE_CONTROL , old |5 ); +wrmsrl (MSR_IA32_FEATURE_CONTROL , old | +MSR_IA32_FEATURE_CONTROL_LOCKED | +MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED );write_cr4 (read_cr4 () |X86_CR4_VMXE );/* FIXME: not cpu hotplug safe */ asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr), "m"(phys_addr) : "memory", "cc");
@@ -1326,7 +1334,7 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)CPU_BASED_HLT_EXITING /* 20.6.2 */ |CPU_BASED_CR8_LOAD_EXITING /* 20.6.2 */ |CPU_BASED_CR8_STORE_EXITING /* 20.6.2 */ - |CPU_BASED_ACTIVATE_IO_BITMAP /* 20.6.2 */ + |CPU_BASED_USE_IO_BITMAPS /* 20.6.2 */ |CPU_BASED_MOV_DR_EXITING |CPU_BASED_USE_TSC_OFFSETING /* 21.3 */ );
drivers/kvm/vmx.h +43 -26
83 lines not on this page · raw message
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 22/104 KVM: Remove dead code in the cmpxchg instruction emulation
In reply to Avi KivityFrom: Aurelien Jarno <[email protected]>
The writeback fixes (02c03a326a5df825cc01de426f72e160db2b9538) let some dead code in the cmpxchg instruction emulation. Remove it.
--- drivers/kvm/x86_emulate.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/kvm/x86_emulate.c +0 -2
@@ -1278,8 +1278,6 @@ twobyte_insn: src.orig_val = src.val; src.val = _regs[VCPU_REGS_RAX ];emulate_2op_SrcV ("cmp" , src, dst, _eflags); -/* Always write back. The question is: where to? */ - d |= Mov;if (_eflags &EFLG_ZF ) {/* Success: write back to memory. */ dst.val = src.orig_val;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 23/104 KVM: load_pdptrs() cleanups
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
load_pdptrs can be handed an invalid cr3, and it should not oops. This can happen because we injected #gp in set_cr3() after we set vcpu->cr3 to the invalid value, or from kvm_vcpu_ioctl_set_sregs(), or memory configuration changes after the guest did set_cr3().
We should also copy the pdpte array once, before checking and assigning, otherwise an SMP guest can potentially alter the values between the check and the set.
Finally one nitpick: ret = 1 should be done as late as possible: this allows GCC to check for unset "ret" should the function change in future.
--- drivers/kvm/kvm_main.c | 22 ++++++++++++---------- 1 files changed, 12 insertions(+), 10 deletions(-)
drivers/kvm/kvm_main.c +12 -10
@@ -442,30 +442,32 @@ static int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)gfn_t pdpt_gfn = cr3 >>PAGE_SHIFT ;unsigned offset = ((cr3 & (PAGE_SIZE -1 )) >>5 ) <<2 ;int i; -u64 pdpte;u64 *pdpt;int ret;struct page *page; +u64 pdpte[ARRAY_SIZE (vcpu->pdptrs)];spin_lock (&vcpu->kvm->lock); page =gfn_to_page (vcpu->kvm, pdpt_gfn); -/* FIXME: !page - emulate? 0xff? */ +if (!page) { + ret =0 ; + goto out; + } + pdpt =kmap_atomic (page,KM_USER0 ); +memcpy (pdpte, pdpt+offset,sizeof (pdpte)); +kunmap_atomic (pdpt,KM_USER0 ); - ret =1 ; -for (i =0 ; i <4 ; ++i) { - pdpte = pdpt[offset + i]; -if ((pdpte &1 ) && (pdpte &0xfffffff0000001e6ull )) { +for (i =0 ; i <ARRAY_SIZE (pdpte); ++i) { +if ((pdpte[i] &1 ) && (pdpte[i] &0xfffffff0000001e6ull )) { ret =0 ; goto out; } } + ret =1 ; -for (i =0 ; i <4 ; ++i) - vcpu->pdptrs[i] = pdpt[offset + i]; - +memcpy (vcpu->pdptrs, pdpte,sizeof (vcpu->pdptrs)); out: -kunmap_atomic (pdpt,KM_USER0 );spin_unlock (&vcpu->kvm->lock);return ret;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 24/104 KVM: Remove arch specific components from the general code
In reply to Avi KivityFrom: Gregory Haskins <[email protected]>
struct kvm_vcpu has vmx-specific members; remove them to a private structure.
--- drivers/kvm/kvm.h | 31 +---- drivers/kvm/kvm_main.c | 26 +--- drivers/kvm/kvm_svm.h | 3 + drivers/kvm/svm.c | 394 ++++++++++++++++++++++++++++-------------------- drivers/kvm/vmx.c | 249 +++++++++++++++++++----------- 5 files changed, 397 insertions(+), 306 deletions(-)
drivers/kvm/kvm.h +2 -29
@@ -15,7 +15,6 @@#include <linux/mm.h> #include <asm/signal.h> -#include "vmx.h" #include <linux/kvm.h> #include <linux/kvm_para.h>
@@ -140,14 +139,6 @@ struct kvm_mmu_page { }; }; -struct vmcs { -u32 revision_id; -u32 abort; -char data[0 ]; -}; - -#define vmx_msr_entry kvm_msr_entry -struct kvm_vcpu ;/*
@@ -309,15 +300,12 @@ void kvm_io_bus_register_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev);struct kvm_vcpu { +int valid;struct kvm *kvm;int vcpu_id; -union { -struct vmcs *vmcs; -struct vcpu_svm *svm; - }; +void *_priv;struct mutex mutex;int cpu; -int launched;u64 host_tsc;struct kvm_run *run;int interrupt_window_open;
@@ -340,14 +328,6 @@ struct kvm_vcpu {u64 shadow_efer;u64 apic_base;u64 ia32_misc_enable_msr; -int nmsrs; -int save_nmsrs; -int msr_offset_efer; -#ifdef CONFIG_X86_64 -int msr_offset_kernel_gs_base; -#endif -struct vmx_msr_entry *guest_msrs; -struct vmx_msr_entry *host_msrs;struct kvm_mmu mmu;
@@ -366,11 +346,6 @@ struct kvm_vcpu {char *guest_fx_image;int fpu_active;int guest_fpu_loaded; -struct vmx_host_state { -int loaded; -u16 fs_sel, gs_sel, ldt_sel; -int fs_gs_ldt_reload_needed; - } vmx_host_state;int mmio_needed;int mmio_read_completed;
@@ -579,8 +554,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);void fx_init (struct kvm_vcpu *vcpu); -void load_msrs (struct vmx_msr_entry *e,int n); -void save_msrs (struct vmx_msr_entry *e,int n);void kvm_resched (struct kvm_vcpu *vcpu);void kvm_load_guest_fpu (struct kvm_vcpu *vcpu);void kvm_put_guest_fpu (struct kvm_vcpu *vcpu);
drivers/kvm/kvm_main.c +5 -21
@@ -367,7 +367,7 @@ static void free_pio_guest_pages(struct kvm_vcpu *vcpu)static void kvm_unload_vcpu_mmu (struct kvm_vcpu *vcpu) { -if (!vcpu->vmcs) +if (!vcpu->valid)return ;vcpu_load (vcpu);
@@ -377,7 +377,7 @@ static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)static void kvm_free_vcpu (struct kvm_vcpu *vcpu) { -if (!vcpu->vmcs) +if (!vcpu->valid)return ;vcpu_load (vcpu);
@@ -1645,24 +1645,6 @@ void kvm_resched(struct kvm_vcpu *vcpu) }EXPORT_SYMBOL_GPL (kvm_resched); -void load_msrs (struct vmx_msr_entry *e,int n) -{ -int i; - -for (i =0 ; i < n; ++i) -wrmsrl (e[i].index, e[i].data); -} -EXPORT_SYMBOL_GPL (load_msrs); - -void save_msrs (struct vmx_msr_entry *e,int n) -{ -int i; - -for (i =0 ; i < n; ++i) -rdmsrl (e[i].index, e[i].data); -} -EXPORT_SYMBOL_GPL (save_msrs); -void kvm_emulate_cpuid (struct kvm_vcpu *vcpu) {int i;
@@ -2401,7 +2383,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)mutex_lock (&vcpu->mutex); -if (vcpu->vmcs) { +if (vcpu->valid) {mutex_unlock (&vcpu->mutex);return -EEXIST ; }
@@ -2449,6 +2431,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n) kvm->nvcpus = n +1 ;spin_unlock (&kvm_lock); + vcpu->valid =1 ; +return r; out_free_vcpus:
drivers/kvm/kvm_svm.h +3 -0
@@ -20,7 +20,10 @@ static const u32 host_save_user_msrs[] = {#define NR_HOST_SAVE_USER_MSRS ARRAY_SIZE(host_save_user_msrs)#define NUM_DB_REGS 4 +struct kvm_vcpu ; +struct vcpu_svm { +struct kvm_vcpu *vcpu;struct vmcb *vmcb;unsigned long vmcb_pa;struct svm_cpu_data *svm_data;
drivers/kvm/svm.c +229 -165
951 lines not on this page · raw message
drivers/kvm/vmx.c +158 -91
487 lines not on this page · raw message
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 25/104 KVM: Dynamically allocate vcpus
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
This patch converts the vcpus array in "struct kvm" to a pointer array, and changes the "vcpu_create" and "vcpu_setup" hooks into one "vcpu_create" call which does the allocation and initialization of the vcpu (calling back into the kvm_vcpu_init core helper).
--- drivers/kvm/kvm.h | 12 ++-- drivers/kvm/kvm_main.c | 198 +++++++++++++++++++++++++----------------------- drivers/kvm/kvm_svm.h | 2 +- drivers/kvm/svm.c | 177 +++++++++++++++++++++---------------------- drivers/kvm/vmx.c | 65 ++++++++++------ 5 files changed, 236 insertions(+), 218 deletions(-)
drivers/kvm/kvm.h +6 -6
@@ -300,10 +300,8 @@ void kvm_io_bus_register_dev(struct kvm_io_bus *bus, struct kvm_io_device *dev);struct kvm_vcpu { -int valid;struct kvm *kvm;int vcpu_id; -void *_priv;struct mutex mutex;int cpu;u64 host_tsc;
@@ -404,8 +402,7 @@ struct kvm {struct list_head active_mmu_pages;int n_free_mmu_pages;struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES ]; -int nvcpus; -struct kvm_vcpu vcpus[KVM_MAX_VCPUS ]; +struct kvm_vcpu *vcpus[KVM_MAX_VCPUS ];int memory_config_version;int busy;unsigned long rmap_overflow;
@@ -428,7 +425,8 @@ struct kvm_arch_ops {int (*hardware_setup)(void );/* __init */ void (*hardware_unsetup)(void );/* __exit */ -int (*vcpu_create)(struct kvm_vcpu *vcpu); +/* Create, but do not attach this VCPU */ +struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm,unsigned id);void (*vcpu_free)(struct kvm_vcpu *vcpu);void (*vcpu_load)(struct kvm_vcpu *vcpu);
@@ -470,7 +468,6 @@ struct kvm_arch_ops {void (*inject_gp)(struct kvm_vcpu *vcpu,unsigned err_code);int (*run)(struct kvm_vcpu *vcpu,struct kvm_run *run); -int (*vcpu_setup)(struct kvm_vcpu *vcpu);void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);void (*patch_hypercall)(struct kvm_vcpu *vcpu,unsigned char *hypercall_addr);
@@ -481,6 +478,9 @@ extern struct kvm_arch_ops *kvm_arch_ops; #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) #define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt) +int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id); +void kvm_vcpu_uninit (struct kvm_vcpu *vcpu); +int kvm_init_arch (struct kvm_arch_ops *ops,struct module *module);void kvm_exit_arch (void );
drivers/kvm/kvm_main.c +103 -95
274 lines not on this page · raw message
drivers/kvm/kvm_svm.h +1 -1
@@ -23,7 +23,7 @@ static const u32 host_save_user_msrs[] = {struct kvm_vcpu ;struct vcpu_svm { -struct kvm_vcpu *vcpu; +struct kvm_vcpu vcpu;struct vmcb *vmcb;unsigned long vmcb_pa;struct svm_cpu_data *svm_data;
drivers/kvm/svm.c +86 -91
260 lines not on this page · raw message
drivers/kvm/vmx.c +40 -25
107 lines not on this page · raw message
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 26/104 KVM: VMX: Improve the method of writing vmcs control
In reply to Avi KivityFrom: Yang, Sheng <[email protected]>
Put cpu feature detecting part in hardware_setup, and stored the vmcs condition in global variable for further check.
[glommer: fix for some i386-only machines not supporting CR8 load/store
exiting]
--- drivers/kvm/vmx.c | 147 ++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 102 insertions(+), 45 deletions(-)
drivers/kvm/vmx.c +102 -45
@@ -71,18 +71,17 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);static struct page *vmx_io_bitmap_a;static struct page *vmx_io_bitmap_b; -#ifdef CONFIG_X86_64 -#define HOST_IS_64 1 -#else -#define HOST_IS_64 0 -#endif #define EFER_SAVE_RESTORE_BITS ((u64)EFER_SCE) -static struct vmcs_descriptor { +static struct vmcs_config {int size;int order;u32 revision_id; -} vmcs_descriptor; +u32 pin_based_exec_ctrl; +u32 cpu_based_exec_ctrl; +u32 vmexit_ctrl; +u32 vmentry_ctrl; +} vmcs_config;#define VMX_SEGMENT_FIELD (seg) \ [VCPU_SREG_##seg] = { \
@@ -839,14 +838,93 @@ static void hardware_disable(void *garbage) asm volatile (ASM_VMX_VMXOFF : : : "cc"); } -static __init void setup_vmcs_descriptor (void ) +static __init int adjust_vmx_controls (u32 ctl_min,u32 ctl_opt, +u32 msr,u32 * result) +{ +u32 vmx_msr_low, vmx_msr_high; +u32 ctl = ctl_min | ctl_opt; + +rdmsr (msr, vmx_msr_low, vmx_msr_high); + + ctl &= vmx_msr_high;/* bit == 0 in high word ==> must be zero */ + ctl |= vmx_msr_low;/* bit == 1 in low word ==> must be one */ + +/* Ensure minimum (required) set of control bits are supported. */ +if (ctl_min & ~ctl) +return -1 ; + + *result = ctl; +return 0 ; +} + +static __init int setup_vmcs_config (void ) {u32 vmx_msr_low, vmx_msr_high; +u32 min, opt; +u32 _pin_based_exec_control =0 ; +u32 _cpu_based_exec_control =0 ; +u32 _vmexit_control =0 ; +u32 _vmentry_control =0 ; + + min =PIN_BASED_EXT_INTR_MASK |PIN_BASED_NMI_EXITING ; + opt =0 ; +if (adjust_vmx_controls (min, opt,MSR_IA32_VMX_PINBASED_CTLS , + &_pin_based_exec_control) <0 ) +return -1 ; + + min = CPU_BASED_HLT_EXITING | +#ifdef CONFIG_X86_64 +CPU_BASED_CR8_LOAD_EXITING | +CPU_BASED_CR8_STORE_EXITING | +#endif +CPU_BASED_USE_IO_BITMAPS | +CPU_BASED_MOV_DR_EXITING | +CPU_BASED_USE_TSC_OFFSETING ; + opt =0 ; +if (adjust_vmx_controls (min, opt,MSR_IA32_VMX_PROCBASED_CTLS , + &_cpu_based_exec_control) <0 ) +return -1 ; + + min =0 ; +#ifdef CONFIG_X86_64 + min |=VM_EXIT_HOST_ADDR_SPACE_SIZE ; +#endif + opt =0 ; +if (adjust_vmx_controls (min, opt,MSR_IA32_VMX_EXIT_CTLS , + &_vmexit_control) <0 ) +return -1 ; + + min = opt =0 ; +if (adjust_vmx_controls (min, opt,MSR_IA32_VMX_ENTRY_CTLS , + &_vmentry_control) <0 ) +return -1 ;rdmsr (MSR_IA32_VMX_BASIC , vmx_msr_low, vmx_msr_high); - vmcs_descriptor.size = vmx_msr_high &0x1fff ; - vmcs_descriptor.order =get_order (vmcs_descriptor.size); - vmcs_descriptor.revision_id = vmx_msr_low; + +/* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ +if ((vmx_msr_high &0x1fff ) >PAGE_SIZE ) +return -1 ; + +#ifdef CONFIG_X86_64 +/* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */ +if (vmx_msr_high & (1u <<16 )) +return -1 ; +#endif + +/* Require Write-Back (WB) memory type for VMCS accesses. */ +if (((vmx_msr_high >>18 ) &15 ) !=6 ) +return -1 ; + + vmcs_config.size = vmx_msr_high &0x1fff ; + vmcs_config.order =get_order (vmcs_config.size); + vmcs_config.revision_id = vmx_msr_low; + + vmcs_config.pin_based_exec_ctrl = _pin_based_exec_control; + vmcs_config.cpu_based_exec_ctrl = _cpu_based_exec_control; + vmcs_config.vmexit_ctrl = _vmexit_control; + vmcs_config.vmentry_ctrl = _vmentry_control; + + return 0; }static struct vmcs *alloc_vmcs_cpu (int cpu)
@@ -855,12 +933,12 @@ static struct vmcs *alloc_vmcs_cpu(int cpu)struct page *pages;struct vmcs *vmcs; - pages =alloc_pages_node (node,GFP_KERNEL , vmcs_descriptor.order); + pages =alloc_pages_node (node,GFP_KERNEL , vmcs_config.order);if (!pages)return NULL ; vmcs =page_address (pages); -memset (vmcs,0 , vmcs_descriptor.size); - vmcs->revision_id = vmcs_descriptor.revision_id;/* vmcs revision id */ +memset (vmcs,0 , vmcs_config.size); + vmcs->revision_id = vmcs_config.revision_id;/* vmcs revision id */ return vmcs; }
@@ -871,7 +949,7 @@ static struct vmcs *alloc_vmcs(void)static void free_vmcs (struct vmcs *vmcs) { -free_pages ((unsigned long )vmcs, vmcs_descriptor.order); +free_pages ((unsigned long )vmcs, vmcs_config.order); }static void free_kvm_area (void )
@@ -904,7 +982,8 @@ static __init int alloc_kvm_area(void)static __init int hardware_setup (void ) { -setup_vmcs_descriptor (); +if (setup_vmcs_config () <0 ) +return -1 ;return alloc_kvm_area (); }
@@ -1275,17 +1354,6 @@ static int init_rmode_tss(struct kvm* kvm)return 1 ; } -static void vmcs_write32_fixedbits (u32 msr,u32 vmcs_field,u32 val) -{ -u32 msr_high, msr_low; - -rdmsr (msr, msr_low, msr_high); - - val &= msr_high; - val |= msr_low; -vmcs_write32 (vmcs_field, val); -} -static void seg_setup (int seg) {struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -1382,20 +1450,10 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)vmcs_write64 (GUEST_IA32_DEBUGCTL ,0 );/* Control */ -vmcs_write32_fixedbits (MSR_IA32_VMX_PINBASED_CTLS , -PIN_BASED_VM_EXEC_CONTROL , -PIN_BASED_EXT_INTR_MASK /* 20.6.1 */ - |PIN_BASED_NMI_EXITING /* 20.6.1 */ - ); -vmcs_write32_fixedbits (MSR_IA32_VMX_PROCBASED_CTLS , -CPU_BASED_VM_EXEC_CONTROL , -CPU_BASED_HLT_EXITING /* 20.6.2 */ - |CPU_BASED_CR8_LOAD_EXITING /* 20.6.2 */ - |CPU_BASED_CR8_STORE_EXITING /* 20.6.2 */ - |CPU_BASED_USE_IO_BITMAPS /* 20.6.2 */ - |CPU_BASED_MOV_DR_EXITING - |CPU_BASED_USE_TSC_OFFSETING /* 21.3 */ - ); +vmcs_write32 (PIN_BASED_VM_EXEC_CONTROL , + vmcs_config.pin_based_exec_ctrl); +vmcs_write32 (CPU_BASED_VM_EXEC_CONTROL , + vmcs_config.cpu_based_exec_ctrl);vmcs_write32 (PAGE_FAULT_ERROR_CODE_MASK ,0 );vmcs_write32 (PAGE_FAULT_ERROR_CODE_MATCH ,0 );
@@ -1459,12 +1517,11 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)setup_msrs (vcpu); -vmcs_write32_fixedbits (MSR_IA32_VMX_EXIT_CTLS ,VM_EXIT_CONTROLS , - (HOST_IS_64 <<9 ));/* 22.2,1, 20.7.1 */ +vmcs_write32 (VM_EXIT_CONTROLS , vmcs_config.vmexit_ctrl);/* 22.2.1, 20.8.1 */ -vmcs_write32_fixedbits (MSR_IA32_VMX_ENTRY_CTLS , -VM_ENTRY_CONTROLS ,0 ); +vmcs_write32 (VM_ENTRY_CONTROLS , vmcs_config.vmentry_ctrl); +vmcs_write32 (VM_ENTRY_INTR_INFO_FIELD ,0 );/* 22.2.1 */ #ifdef CONFIG_X86_64
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 27/104 KVM: add hypercall nr to kvm_run
In reply to Avi KivityFrom: Jeff Dike <[email protected]>
Add the hypercall number to kvm_run and initialize it. This changes the ABI, but as this particular ABI was unusable before this no users are affected.
--- drivers/kvm/kvm_main.c | 1 + include/linux/kvm.h | 1 + 2 files changed, 2 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +1 -0
@@ -1378,6 +1378,7 @@ int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run) }switch (nr) {default : + run->hypercall.nr = nr; run->hypercall.args[0 ] = a0; run->hypercall.args[1 ] = a1; run->hypercall.args[2 ] = a2;
include/linux/kvm.h +1 -0
@@ -99,6 +99,7 @@ struct kvm_run { } mmio;/* KVM_EXIT_HYPERCALL */ struct { +__u64 nr;__u64 args[6 ];__u64 ret;__u32 longmode;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 28/104 KVM: Use the scheduler preemption notifiers to make kvm preemptible
In reply to Avi KivityCurrent kvm disables preemption while the new virtualization registers are in use. This of course is not very good for latency sensitive workloads (one use of virtualization is to offload user interface and other latency insensitive stuff to a container, so that it is easier to analyze the remaining workload). This patch re-enables preemption for kvm; preemption is now only disabled when switching the registers in and out, and during the switch to guest mode and back.
Contains fixes from Shaohua Li <[email protected]>.
--- drivers/kvm/Kconfig | 1 + drivers/kvm/kvm.h | 4 +++- drivers/kvm/kvm_main.c | 43 +++++++++++++++++++++++++++++++++++++------ drivers/kvm/mmu.c | 2 -- drivers/kvm/svm.c | 6 ++---- drivers/kvm/vmx.c | 22 +++++++++++++--------- 6 files changed, 56 insertions(+), 22 deletions(-)
drivers/kvm/Kconfig +1 -0
@@ -16,6 +16,7 @@ if VIRTUALIZATION config KVM tristate "Kernel-based Virtual Machine (KVM) support" depends on X86 && EXPERIMENTAL + select PREEMPT_NOTIFIERS select ANON_INODES ---help--- Support hosting fully virtualized guest machines using hardware
drivers/kvm/kvm.h +3 -1
@@ -13,6 +13,7 @@#include <linux/signal.h> #include <linux/sched.h> #include <linux/mm.h> +#include <linux/preempt.h> #include <asm/signal.h> #include <linux/kvm.h>
@@ -301,6 +302,7 @@ void kvm_io_bus_register_dev(struct kvm_io_bus *bus,struct kvm_vcpu {struct kvm *kvm; +struct preempt_notifier preempt_notifier;int vcpu_id;struct mutex mutex;int cpu;
@@ -429,7 +431,7 @@ struct kvm_arch_ops {struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm,unsigned id);void (*vcpu_free)(struct kvm_vcpu *vcpu); -void (*vcpu_load)(struct kvm_vcpu *vcpu); +void (*vcpu_load)(struct kvm_vcpu *vcpu,int cpu);void (*vcpu_put)(struct kvm_vcpu *vcpu);void (*vcpu_decache)(struct kvm_vcpu *vcpu);
drivers/kvm/kvm_main.c +37 -6
101 lines not on this page · raw message
drivers/kvm/mmu.c +0 -2
@@ -276,9 +276,7 @@ static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu)kvm_mmu_free_some_pages (vcpu);if (r <0 ) {spin_unlock (&vcpu->kvm->lock); - kvm_arch_ops->vcpu_put (vcpu); r =__mmu_topup_memory_caches (vcpu,GFP_KERNEL ); - kvm_arch_ops->vcpu_load (vcpu);spin_lock (&vcpu->kvm->lock);kvm_mmu_free_some_pages (vcpu); }
drivers/kvm/svm.c +2 -4
@@ -625,12 +625,11 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)kfree (svm); } -static void svm_vcpu_load (struct kvm_vcpu *vcpu) +static void svm_vcpu_load (struct kvm_vcpu *vcpu,int cpu) {struct vcpu_svm *svm =to_svm (vcpu); -int cpu, i; +int i; - cpu =get_cpu ();if (unlikely (cpu != vcpu->cpu)) {u64 tsc_this, delta;
@@ -657,7 +656,6 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu)wrmsrl (host_save_user_msrs[i], svm->host_user_msrs[i]);rdtscll (vcpu->host_tsc); -put_cpu (); }static void svm_vcpu_decache (struct kvm_vcpu *vcpu)
drivers/kvm/vmx.c +13 -9
@@ -396,6 +396,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)static void vmx_load_host_state (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu); +unsigned long flags;if (!vmx->host_state.loaded)return ;
@@ -408,12 +409,12 @@ static void vmx_load_host_state(struct kvm_vcpu *vcpu)* If we have to reload gs, we must take care to * preserve our gs base. */ -local_irq_disable (); +local_irq_save (flags);load_gs (vmx->host_state.gs_sel);#ifdef CONFIG_X86_64 wrmsrl (MSR_GS_BASE ,vmcs_readl (HOST_GS_BASE ));#endif -local_irq_enable (); +local_irq_restore (flags);reload_tss (); }
@@ -427,15 +428,12 @@ static void vmx_load_host_state(struct kvm_vcpu *vcpu)* Switches to specified vcpu, until a matching vcpu_put(), but assumes * vcpu mutex is already taken. */ -static void vmx_vcpu_load (struct kvm_vcpu *vcpu) +static void vmx_vcpu_load (struct kvm_vcpu *vcpu,int cpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);u64 phys_addr =__pa (vmx->vmcs); -int cpu;u64 tsc_this, delta; - cpu =get_cpu (); -if (vcpu->cpu != cpu)vcpu_clear (vcpu);
@@ -480,7 +478,6 @@ static void vmx_vcpu_put(struct kvm_vcpu *vcpu) {vmx_load_host_state (vcpu);kvm_put_guest_fpu (vcpu); -put_cpu (); }static void vmx_fpu_activate (struct kvm_vcpu *vcpu)
@@ -2127,6 +2124,8 @@ again:if (unlikely (r)) goto out; +preempt_disable (); +if (!vcpu->mmio_read_completed)do_interrupt_requests (vcpu, kvm_run);
@@ -2269,6 +2268,9 @@ again: vcpu->interrupt_window_open = (vmcs_read32 (GUEST_INTERRUPTIBILITY_INFO ) &3 ) ==0 ; asm ("mov %0, %%ds; mov %0, %%es" : :"r" (__USER_DS)); + vmx->launched =1 ; + +preempt_enable ();if (unlikely (fail)) { kvm_run->exit_reason =KVM_EXIT_FAIL_ENTRY ;
@@ -2283,7 +2285,6 @@ again:if (unlikely (prof_on ==KVM_PROFILING ))profile_hit (KVM_PROFILING , (void *)vmcs_readl (GUEST_RIP )); - vmx->launched =1 ; r =kvm_handle_exit (kvm_run, vcpu);if (r >0 ) {/* Give scheduler a change to reschedule. */
@@ -2372,6 +2373,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) {int err;struct vcpu_vmx *vmx =kzalloc (sizeof (*vmx),GFP_KERNEL ); +int cpu;if (!vmx)return ERR_PTR (-ENOMEM );
@@ -2396,9 +2398,11 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)vmcs_clear (vmx->vmcs); -vmx_vcpu_load (&vmx->vcpu); + cpu =get_cpu (); +vmx_vcpu_load (&vmx->vcpu, cpu); err =vmx_vcpu_setup (&vmx->vcpu);vmx_vcpu_put (&vmx->vcpu); +put_cpu ();if (err) goto free_vmcs;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 29/104 KVM: Convert vm lock to a mutex
In reply to Avi KivityFrom: Shaohua Li <[email protected]>
This allows the kvm mmu to perform sleepy operations, such as memory allocation.
--- drivers/kvm/kvm.h | 2 +- drivers/kvm/kvm_main.c | 69 +++++++++++++++++++++++------------------------- drivers/kvm/mmu.c | 9 +++--- drivers/kvm/svm.c | 8 +++--- drivers/kvm/vmx.c | 8 +++--- 5 files changed, 46 insertions(+), 50 deletions(-)
drivers/kvm/kvm.h +1 -1
@@ -393,7 +393,7 @@ struct kvm_memory_slot { };struct kvm { -spinlock_t lock;/* protects everything except vcpus */ +struct mutex lock;/* protects everything except vcpus */ int naliases;struct kvm_mem_alias aliases[KVM_ALIAS_SLOTS ];int nmemslots;
drivers/kvm/kvm_main.c +33 -36
233 lines not on this page · raw message
drivers/kvm/mmu.c +4 -5
@@ -275,10 +275,9 @@ static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu) r =__mmu_topup_memory_caches (vcpu,GFP_NOWAIT );kvm_mmu_free_some_pages (vcpu);if (r <0 ) { -spin_unlock (&vcpu->kvm->lock); +mutex_unlock (&vcpu->kvm->lock); r =__mmu_topup_memory_caches (vcpu,GFP_KERNEL ); -spin_lock (&vcpu->kvm->lock); -kvm_mmu_free_some_pages (vcpu); +mutex_lock (&vcpu->kvm->lock); }return r; }
@@ -1069,7 +1068,7 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu) {int r; -spin_lock (&vcpu->kvm->lock); +mutex_lock (&vcpu->kvm->lock); r =mmu_topup_memory_caches (vcpu);if (r) goto out;
@@ -1077,7 +1076,7 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu) kvm_arch_ops->set_cr3 (vcpu, vcpu->mmu.root_hpa);kvm_mmu_flush_tlb (vcpu); out: -spin_unlock (&vcpu->kvm->lock); +mutex_unlock (&vcpu->kvm->lock);return r; }EXPORT_SYMBOL_GPL (kvm_mmu_load);
drivers/kvm/svm.c +4 -4
@@ -941,21 +941,21 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)if (is_external_interrupt (exit_int_info))push_irq (vcpu, exit_int_info &SVM_EVTINJ_VEC_MASK ); -spin_lock (&vcpu->kvm->lock); +mutex_lock (&vcpu->kvm->lock); fault_address = svm->vmcb->control.exit_info_2; error_code = svm->vmcb->control.exit_info_1; r =kvm_mmu_page_fault (vcpu, fault_address, error_code);if (r <0 ) { -spin_unlock (&vcpu->kvm->lock); +mutex_unlock (&vcpu->kvm->lock);return r; }if (!r) { -spin_unlock (&vcpu->kvm->lock); +mutex_unlock (&vcpu->kvm->lock);return 1 ; } er =emulate_instruction (vcpu, kvm_run, fault_address, error_code); -spin_unlock (&vcpu->kvm->lock); +mutex_unlock (&vcpu->kvm->lock);switch (er) {case EMULATE_DONE :
drivers/kvm/vmx.c +4 -4
@@ -1711,19 +1711,19 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)if (is_page_fault (intr_info)) { cr2 =vmcs_readl (EXIT_QUALIFICATION ); -spin_lock (&vcpu->kvm->lock); +mutex_lock (&vcpu->kvm->lock); r =kvm_mmu_page_fault (vcpu, cr2, error_code);if (r <0 ) { -spin_unlock (&vcpu->kvm->lock); +mutex_unlock (&vcpu->kvm->lock);return r; }if (!r) { -spin_unlock (&vcpu->kvm->lock); +mutex_unlock (&vcpu->kvm->lock);return 1 ; } er =emulate_instruction (vcpu, kvm_run, cr2, error_code); -spin_unlock (&vcpu->kvm->lock); +mutex_unlock (&vcpu->kvm->lock);switch (er) {case EMULATE_DONE :
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 30/104 KVM: fx_init() needs preemption disabled while it plays with the FPU state
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Now that kvm generally runs with preemption enabled, we need to protect the fpu intialization sequence.
--- drivers/kvm/kvm_main.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +3 -0
@@ -693,10 +693,13 @@ void fx_init(struct kvm_vcpu *vcpu) } *fx_image; +/* Initialize guest FPU by resetting ours and saving into guest's */ +preempt_disable ();fx_save (vcpu->host_fx_image);fpu_init ();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 ;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 31/104 KVM: VMX: pass vcpu_vmx internally
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
container_of is wonderful, but not casting at all is better. This patch changes vmx.c's internal functions to pass "struct vcpu_vmx" instead of "struct kvm_vcpu" and using container_of.
--- drivers/kvm/vmx.c | 140 ++++++++++++++++++++++++---------------------------- 1 files changed, 65 insertions(+), 75 deletions(-)
drivers/kvm/vmx.c +65 -75
@@ -140,9 +140,8 @@ static inline u64 msr_efer_save_restore_bits(struct kvm_msr_entry msr)return (u64 )msr.data &EFER_SAVE_RESTORE_BITS ; } -static inline int msr_efer_need_save_restore (struct kvm_vcpu *vcpu) +static inline int msr_efer_need_save_restore (struct vcpu_vmx *vmx) { -struct vcpu_vmx *vmx =to_vmx (vcpu);int efer_offset = vmx->msr_offset_efer;return msr_efer_save_restore_bits (vmx->host_msrs[efer_offset]) !=msr_efer_save_restore_bits (vmx->guest_msrs[efer_offset]);
@@ -168,9 +167,8 @@ static inline int is_external_interrupt(u32 intr_info) == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); } -static int __find_msr_index (struct kvm_vcpu *vcpu,u32 msr) +static int __find_msr_index (struct vcpu_vmx *vmx,u32 msr) { -struct vcpu_vmx *vmx =to_vmx (vcpu);int i;for (i =0 ; i < vmx->nmsrs; ++i)
@@ -179,12 +177,11 @@ static int __find_msr_index(struct kvm_vcpu *vcpu, u32 msr)return -1 ; } -static struct kvm_msr_entry *find_msr_entry (struct kvm_vcpu *vcpu,u32 msr) +static struct kvm_msr_entry *find_msr_entry (struct vcpu_vmx *vmx,u32 msr) { -struct vcpu_vmx *vmx =to_vmx (vcpu);int i; - i =__find_msr_index (vcpu, msr); + i =__find_msr_index (vmx, msr);if (i >=0 )return &vmx->guest_msrs[i];return NULL ;
@@ -205,24 +202,24 @@ static void vmcs_clear(struct vmcs *vmcs)static void __vcpu_clear (void *arg) { -struct kvm_vcpu *vcpu = arg; -struct vcpu_vmx *vmx =to_vmx (vcpu); +struct vcpu_vmx *vmx = arg;int cpu =raw_smp_processor_id (); -if (vcpu->cpu == cpu) +if (vmx->vcpu.cpu == cpu)vmcs_clear (vmx->vmcs);if (per_cpu (current_vmcs, cpu) == vmx->vmcs)per_cpu (current_vmcs, cpu) =NULL ; -rdtscll (vcpu->host_tsc); +rdtscll (vmx->vcpu.host_tsc); } -static void vcpu_clear (struct kvm_vcpu *vcpu) +static void vcpu_clear (struct vcpu_vmx *vmx) { -if (vcpu->cpu !=raw_smp_processor_id () && vcpu->cpu !=-1 ) -smp_call_function_single (vcpu->cpu, __vcpu_clear, vcpu,0 ,1 ); +if (vmx->vcpu.cpu !=raw_smp_processor_id () && vmx->vcpu.cpu !=-1 ) +smp_call_function_single (vmx->vcpu.cpu, __vcpu_clear, + vmx,0 ,1 );else -__vcpu_clear (vcpu); -to_vmx (vcpu)->launched =0 ; +__vcpu_clear (vmx); + vmx->launched =0 ; }static unsigned long vmcs_readl (unsigned long field)
@@ -332,23 +329,20 @@ static void reload_tss(void)#endif } -static void load_transition_efer (struct kvm_vcpu *vcpu) +static void load_transition_efer (struct vcpu_vmx *vmx) {u64 trans_efer; -struct vcpu_vmx *vmx =to_vmx (vcpu);int efer_offset = vmx->msr_offset_efer; trans_efer = vmx->host_msrs[efer_offset].data; trans_efer &= ~EFER_SAVE_RESTORE_BITS ; trans_efer |=msr_efer_save_restore_bits (vmx->guest_msrs[efer_offset]);wrmsrl (MSR_EFER , trans_efer); - vcpu->stat.efer_reload++; + vmx->vcpu.stat.efer_reload++; } -static void vmx_save_host_state (struct kvm_vcpu *vcpu) +static void vmx_save_host_state (struct vcpu_vmx *vmx) { -struct vcpu_vmx *vmx =to_vmx (vcpu); -if (vmx->host_state.loaded)return ;
@@ -383,19 +377,18 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)#endif #ifdef CONFIG_X86_64 -if (is_long_mode (vcpu)) { +if (is_long_mode (&vmx->vcpu)) {save_msrs (vmx->host_msrs + vmx->msr_offset_kernel_gs_base,1 ); }#endif load_msrs (vmx->guest_msrs, vmx->save_nmsrs); -if (msr_efer_need_save_restore (vcpu)) -load_transition_efer (vcpu); +if (msr_efer_need_save_restore (vmx)) +load_transition_efer (vmx); } -static void vmx_load_host_state (struct kvm_vcpu *vcpu) +static void vmx_load_host_state (struct vcpu_vmx *vmx) { -struct vcpu_vmx *vmx =to_vmx (vcpu);unsigned long flags;if (!vmx->host_state.loaded)
@@ -420,7 +413,7 @@ static void vmx_load_host_state(struct kvm_vcpu *vcpu) }save_msrs (vmx->guest_msrs, vmx->save_nmsrs);load_msrs (vmx->host_msrs, vmx->save_nmsrs); -if (msr_efer_need_save_restore (vcpu)) +if (msr_efer_need_save_restore (vmx))load_msrs (vmx->host_msrs + vmx->msr_offset_efer,1 ); }
@@ -435,7 +428,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)u64 tsc_this, delta;if (vcpu->cpu != cpu) -vcpu_clear (vcpu); +vcpu_clear (vmx);if (per_cpu (current_vmcs, cpu) != vmx->vmcs) {u8 error;
@@ -476,7 +469,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)static void vmx_vcpu_put (struct kvm_vcpu *vcpu) { -vmx_load_host_state (vcpu); +vmx_load_host_state (to_vmx (vcpu));kvm_put_guest_fpu (vcpu); }
@@ -502,7 +495,7 @@ static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)static void vmx_vcpu_decache (struct kvm_vcpu *vcpu) { -vcpu_clear (vcpu); +vcpu_clear (to_vmx (vcpu)); }static unsigned long vmx_get_rflags (struct kvm_vcpu *vcpu)
@@ -550,9 +543,8 @@ static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)/* * Swap MSR entry in host/guest MSR entry array. */ -void move_msr_up (struct kvm_vcpu *vcpu,int from,int to) +static void move_msr_up (struct vcpu_vmx *vmx,int from,int to) { -struct vcpu_vmx *vmx =to_vmx (vcpu);struct kvm_msr_entry tmp; tmp = vmx->guest_msrs[to];
@@ -568,44 +560,43 @@ void move_msr_up(struct kvm_vcpu *vcpu, int from, int to)* msrs. Don't touch the 64-bit msrs if the guest is in legacy * mode, as fiddling with msrs is very expensive. */ -static void setup_msrs (struct kvm_vcpu *vcpu) +static void setup_msrs (struct vcpu_vmx *vmx) { -struct vcpu_vmx *vmx =to_vmx (vcpu);int save_nmsrs; save_nmsrs =0 ;#ifdef CONFIG_X86_64 -if (is_long_mode (vcpu)) { +if (is_long_mode (&vmx->vcpu)) {int index; - index =__find_msr_index (vcpu,MSR_SYSCALL_MASK ); + index =__find_msr_index (vmx,MSR_SYSCALL_MASK );if (index >=0 ) -move_msr_up (vcpu, index, save_nmsrs++); - index =__find_msr_index (vcpu,MSR_LSTAR ); +move_msr_up (vmx, index, save_nmsrs++); + index =__find_msr_index (vmx,MSR_LSTAR );if (index >=0 ) -move_msr_up (vcpu, index, save_nmsrs++); - index =__find_msr_index (vcpu,MSR_CSTAR ); +move_msr_up (vmx, index, save_nmsrs++); + index =__find_msr_index (vmx,MSR_CSTAR );if (index >=0 ) -move_msr_up (vcpu, index, save_nmsrs++); - index =__find_msr_index (vcpu,MSR_KERNEL_GS_BASE ); +move_msr_up (vmx, index, save_nmsrs++); + index =__find_msr_index (vmx,MSR_KERNEL_GS_BASE );if (index >=0 ) -move_msr_up (vcpu, index, save_nmsrs++); +move_msr_up (vmx, index, save_nmsrs++);/* * MSR_K6_STAR is only needed on long mode guests, and only * if efer.sce is enabled. */ - index =__find_msr_index (vcpu,MSR_K6_STAR ); -if ((index >=0 ) && (vcpu->shadow_efer &EFER_SCE )) -move_msr_up (vcpu, index, save_nmsrs++); + index =__find_msr_index (vmx,MSR_K6_STAR ); +if ((index >=0 ) && (vmx->vcpu.shadow_efer &EFER_SCE )) +move_msr_up (vmx, index, save_nmsrs++); }#endif vmx->save_nmsrs = save_nmsrs;#ifdef CONFIG_X86_64 vmx->msr_offset_kernel_gs_base = -__find_msr_index (vcpu,MSR_KERNEL_GS_BASE ); +__find_msr_index (vmx,MSR_KERNEL_GS_BASE );#endif - vmx->msr_offset_efer =__find_msr_index (vcpu,MSR_EFER ); + vmx->msr_offset_efer =__find_msr_index (vmx,MSR_EFER ); }/*
@@ -672,7 +663,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) data =vmcs_readl (GUEST_SYSENTER_ESP );break ;default : - msr =find_msr_entry (vcpu, msr_index); + msr =find_msr_entry (to_vmx (vcpu), msr_index);if (msr) { data = msr->data;break ;
@@ -700,7 +691,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)case MSR_EFER : ret =kvm_set_msr_common (vcpu, msr_index, data);if (vmx->host_state.loaded) -load_transition_efer (vcpu); +load_transition_efer (vmx);break ;case MSR_FS_BASE :vmcs_writel (GUEST_FS_BASE , data);
@@ -722,7 +713,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)guest_write_tsc (data);break ;default : - msr =find_msr_entry (vcpu, msr_index); + msr =find_msr_entry (vmx, msr_index);if (msr) { msr->data = data;if (vmx->host_state.loaded)
@@ -1116,7 +1107,7 @@ static void enter_lmode(struct kvm_vcpu *vcpu) vcpu->shadow_efer |=EFER_LMA ; -find_msr_entry (vcpu,MSR_EFER )->data |=EFER_LMA |EFER_LME ; +find_msr_entry (to_vmx (vcpu),MSR_EFER )->data |=EFER_LMA |EFER_LME ;vmcs_write32 (VM_ENTRY_CONTROLS ,vmcs_read32 (VM_ENTRY_CONTROLS ) |VM_ENTRY_CONTROLS_IA32E_MASK );
@@ -1186,7 +1177,8 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)static void vmx_set_efer (struct kvm_vcpu *vcpu,u64 efer) { -struct kvm_msr_entry *msr =find_msr_entry (vcpu,MSR_EFER ); +struct vcpu_vmx *vmx =to_vmx (vcpu); +struct kvm_msr_entry *msr =find_msr_entry (vmx,MSR_EFER ); vcpu->shadow_efer = efer;if (efer &EFER_LMA ) {
@@ -1202,7 +1194,7 @@ static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer) msr->data = efer & ~EFER_LME; } -setup_msrs (vcpu); +setup_msrs (vmx); }#endif
@@ -1364,9 +1356,8 @@ static void seg_setup(int seg)/* * Sets up the vmcs for emulated real mode. */ -static int vmx_vcpu_setup (struct kvm_vcpu *vcpu) +static int vmx_vcpu_setup (struct vcpu_vmx *vmx) { -struct vcpu_vmx *vmx =to_vmx (vcpu);u32 host_sysenter_cs;u32 junk;unsigned long a;
@@ -1375,19 +1366,18 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)int ret =0 ;unsigned long kvm_vmx_return; -if (!init_rmode_tss (vcpu->kvm)) { +if (!init_rmode_tss (vmx->vcpu.kvm)) { ret = -ENOMEM ; goto out; } -memset (vcpu->regs,0 ,sizeof (vcpu->regs)); - vcpu->regs[VCPU_REGS_RDX ] =get_rdx_init_val (); - vcpu->cr8 =0 ; - vcpu->apic_base =0xfee00000 |MSR_IA32_APICBASE_ENABLE ; -if (vcpu->vcpu_id ==0 ) - vcpu->apic_base |=MSR_IA32_APICBASE_BSP ; + vmx->vcpu.regs[VCPU_REGS_RDX ] =get_rdx_init_val (); + vmx->vcpu.cr8 =0 ; + vmx->vcpu.apic_base =0xfee00000 |MSR_IA32_APICBASE_ENABLE ; +if (vmx->vcpu.vcpu_id ==0 ) + vmx->vcpu.apic_base |=MSR_IA32_APICBASE_BSP ; -fx_init (vcpu); +fx_init (&vmx->vcpu);/* * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode
@@ -1512,7 +1502,7 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu) ++vmx->nmsrs; } -setup_msrs (vcpu); +setup_msrs (vmx);vmcs_write32 (VM_EXIT_CONTROLS , vmcs_config.vmexit_ctrl);
@@ -1529,14 +1519,14 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)vmcs_writel (CR0_GUEST_HOST_MASK , ~0UL );vmcs_writel (CR4_GUEST_HOST_MASK ,KVM_GUEST_CR4_MASK ); - vcpu->cr0 =0x60000010 ; -vmx_set_cr0 (vcpu, vcpu->cr0);// enter rmode -vmx_set_cr4 (vcpu,0 ); + vmx->vcpu.cr0 =0x60000010 ; +vmx_set_cr0 (&vmx->vcpu, vmx->vcpu.cr0);// enter rmode +vmx_set_cr4 (&vmx->vcpu,0 );#ifdef CONFIG_X86_64 -vmx_set_efer (vcpu,0 ); +vmx_set_efer (&vmx->vcpu,0 );#endif -vmx_fpu_activate (vcpu); -update_exception_bitmap (vcpu); +vmx_fpu_activate (&vmx->vcpu); +update_exception_bitmap (&vmx->vcpu);return 0 ;
@@ -2129,7 +2119,7 @@ again:if (!vcpu->mmio_read_completed)do_interrupt_requests (vcpu, kvm_run); -vmx_save_host_state (vcpu); +vmx_save_host_state (vmx);kvm_load_guest_fpu (vcpu);/*
@@ -2352,7 +2342,7 @@ static void vmx_free_vmcs(struct kvm_vcpu *vcpu)struct vcpu_vmx *vmx =to_vmx (vcpu);if (vmx->vmcs) { -on_each_cpu (__vcpu_clear, vcpu,0 ,1 ); +on_each_cpu (__vcpu_clear, vmx,0 ,1 );free_vmcs (vmx->vmcs); vmx->vmcs =NULL ; }
@@ -2400,7 +2390,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) cpu =get_cpu ();vmx_vcpu_load (&vmx->vcpu, cpu); - err =vmx_vcpu_setup (&vmx->vcpu); + err =vmx_vcpu_setup (vmx);vmx_vcpu_put (&vmx->vcpu);put_cpu ();if (err)
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 32/104 KVM: Remove three magic numbers
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
There are several places where hardcoded numbers are used in place of the easily-available constant, which is poor form.
--- drivers/kvm/kvm_main.c | 2 +- drivers/kvm/svm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/kvm/kvm_main.c +1 -1
@@ -413,7 +413,7 @@ static void free_pio_guest_pages(struct kvm_vcpu *vcpu) {int i; -for (i =0 ; i <2 ; ++i) +for (i =0 ; i <ARRAY_SIZE (vcpu->pio.guest_pages); ++i)if (vcpu->pio.guest_pages[i]) {__free_page (vcpu->pio.guest_pages[i]); vcpu->pio.guest_pages[i] =NULL ;
drivers/kvm/svm.c +1 -1
@@ -241,7 +241,7 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)printk (KERN_DEBUG "%s: NOP\n" , __FUNCTION__);return ; } -if (svm->next_rip - svm->vmcb->save.rip >15 ) { +if (svm->next_rip - svm->vmcb->save.rip >MAX_INST_SIZE ) { printk(KERN_ERR "%s: ip 0x%llx next 0x%llx\n", __FUNCTION__, svm->vmcb->save.rip,
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 33/104 KVM: SVM: de-containization
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
container_of is wonderful, but not casting at all is better. This patch changes svm.c's internal functions to pass "struct vcpu_svm" instead of "struct kvm_vcpu" and using container_of.
--- drivers/kvm/svm.c | 232 +++++++++++++++++++++++++---------------------------- 1 files changed, 108 insertions(+), 124 deletions(-)
drivers/kvm/svm.c +108 -124
@@ -98,9 +98,9 @@ static inline u32 svm_has(u32 feat)return svm_features & feat; } -static unsigned get_addr_size (struct kvm_vcpu *vcpu) +static unsigned get_addr_size (struct vcpu_svm *svm) { -struct vmcb_save_area *sa = &to_svm (vcpu)->vmcb->save; +struct vmcb_save_area *sa = &svm->vmcb->save;u16 cs_attrib;if (!(sa->cr0 &X86_CR0_PE ) || (sa->rflags &X86_EFLAGS_VM ))
@@ -865,17 +865,15 @@ static void save_host_msrs(struct kvm_vcpu *vcpu)#endif } -static void new_asid (struct kvm_vcpu *vcpu,struct svm_cpu_data *svm_data) +static void new_asid (struct vcpu_svm *svm,struct svm_cpu_data *svm_data) { -struct vcpu_svm *svm =to_svm (vcpu); -if (svm_data->next_asid > svm_data->max_asid) { ++svm_data->asid_generation; svm_data->next_asid =1 ; svm->vmcb->control.tlb_ctl =TLB_CONTROL_FLUSH_ALL_ASID ; } - vcpu->cpu = svm_data->cpu; + svm->vcpu.cpu = svm_data->cpu; svm->asid_generation = svm_data->asid_generation; svm->vmcb->control.asid = svm_data->next_asid++; }
@@ -929,42 +927,43 @@ static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value, } } -static int pf_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int pf_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu);u32 exit_int_info = svm->vmcb->control.exit_int_info; +struct kvm *kvm = svm->vcpu.kvm;u64 fault_address;u32 error_code;enum emulation_result er;int r;if (is_external_interrupt (exit_int_info)) -push_irq (vcpu, exit_int_info &SVM_EVTINJ_VEC_MASK ); +push_irq (&svm->vcpu, exit_int_info &SVM_EVTINJ_VEC_MASK ); -mutex_lock (&vcpu->kvm->lock); +mutex_lock (&kvm->lock); fault_address = svm->vmcb->control.exit_info_2; error_code = svm->vmcb->control.exit_info_1; - r =kvm_mmu_page_fault (vcpu, fault_address, error_code); + r =kvm_mmu_page_fault (&svm->vcpu, fault_address, error_code);if (r <0 ) { -mutex_unlock (&vcpu->kvm->lock); +mutex_unlock (&kvm->lock);return r; }if (!r) { -mutex_unlock (&vcpu->kvm->lock); +mutex_unlock (&kvm->lock);return 1 ; } - er =emulate_instruction (vcpu, kvm_run, fault_address, error_code); -mutex_unlock (&vcpu->kvm->lock); + er =emulate_instruction (&svm->vcpu, kvm_run, fault_address, + error_code); +mutex_unlock (&kvm->lock);switch (er) {case EMULATE_DONE :return 1 ;case EMULATE_DO_MMIO : - ++vcpu->stat.mmio_exits; + ++svm->vcpu.stat.mmio_exits;return 0 ;case EMULATE_FAIL : -vcpu_printf (vcpu,"%s: emulate fail\n" , __FUNCTION__); +vcpu_printf (&svm->vcpu,"%s: emulate fail\n" , __FUNCTION__);break ;default :BUG ();
@@ -974,21 +973,18 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)return 0 ; } -static int nm_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int nm_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu); - svm->vmcb->control.intercept_exceptions &= ~(1 <<NM_VECTOR ); -if (!(vcpu->cr0 &X86_CR0_TS )) +if (!(svm->vcpu.cr0 &X86_CR0_TS )) svm->vmcb->save.cr0 &= ~X86_CR0_TS ; - vcpu->fpu_active =1 ; + svm->vcpu.fpu_active =1 ;return 1 ; } -static int shutdown_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int shutdown_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu);/* * VMCB is undefined after a SHUTDOWN intercept * so reinitialize it.
@@ -1000,11 +996,10 @@ static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)return 0 ; } -static int io_get_override (struct kvm_vcpu *vcpu, +static int io_get_override (struct vcpu_svm *svm,struct vmcb_seg **seg,int *addr_override) { -struct vcpu_svm *svm =to_svm (vcpu);u8 inst[MAX_INST_SIZE ];unsigned ins_length;gva_t rip;
@@ -1024,7 +1019,7 @@ static int io_get_override(struct kvm_vcpu *vcpu, svm->vmcb->control.exit_info_2, ins_length); -if (kvm_read_guest (vcpu, rip, ins_length, inst) != ins_length) +if (kvm_read_guest (&svm->vcpu, rip, ins_length, inst) != ins_length)/* #PF */ return 0 ;
@@ -1065,28 +1060,27 @@ static int io_get_override(struct kvm_vcpu *vcpu,return 0 ; } -static unsigned long io_adress (struct kvm_vcpu *vcpu,int ins,gva_t *address) +static unsigned long io_adress (struct vcpu_svm *svm,int ins,gva_t *address) {unsigned long addr_mask;unsigned long *reg;struct vmcb_seg *seg;int addr_override; -struct vcpu_svm *svm =to_svm (vcpu);struct vmcb_save_area *save_area = &svm->vmcb->save;u16 cs_attrib = save_area->cs.attrib; -unsigned addr_size =get_addr_size (vcpu); +unsigned addr_size =get_addr_size (svm); -if (!io_get_override (vcpu, &seg, &addr_override)) +if (!io_get_override (svm, &seg, &addr_override))return 0 ;if (addr_override) addr_size = (addr_size ==2 ) ?4 : (addr_size >>1 );if (ins) { - reg = &vcpu->regs[VCPU_REGS_RDI ]; + reg = &svm->vcpu.regs[VCPU_REGS_RDI ]; seg = &svm->vmcb->save.es; }else { - reg = &vcpu->regs[VCPU_REGS_RSI ]; + reg = &svm->vcpu.regs[VCPU_REGS_RSI ]; seg = (seg) ? seg : &svm->vmcb->save.ds; }
@@ -1099,7 +1093,7 @@ static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, gva_t *address) }if (!(seg->attrib &SVM_SELECTOR_P_SHIFT )) { -svm_inject_gp (vcpu,0 ); +svm_inject_gp (&svm->vcpu,0 );return 0 ; }
@@ -1107,16 +1101,15 @@ static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, gva_t *address)return addr_mask; } -static int io_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int io_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu);u32 io_info = svm->vmcb->control.exit_info_1;//address size bug? int size, down, in, string, rep;unsigned port;unsigned long count;gva_t address =0 ; - ++vcpu->stat.io_exits; + ++svm->vcpu.stat.io_exits; svm->next_rip = svm->vmcb->control.exit_info_2;
@@ -1131,7 +1124,7 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)if (string) {unsigned addr_mask; - addr_mask =io_adress (vcpu, in, &address); + addr_mask =io_adress (svm, in, &address);if (!addr_mask) {printk (KERN_DEBUG "%s: get io address failed\n" , __FUNCTION__);
@@ -1139,60 +1132,57 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) }if (rep) - count = vcpu->regs[VCPU_REGS_RCX ] & addr_mask; + count = svm->vcpu.regs[VCPU_REGS_RCX ] & addr_mask; } -return kvm_setup_pio (vcpu, kvm_run, in, size, count, string, down, - address, rep, port); +return kvm_setup_pio (&svm->vcpu, kvm_run, in, size, count, string, + down, address, rep, port); } -static int nop_on_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int nop_on_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) {return 1 ; } -static int halt_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int halt_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu); - svm->next_rip = svm->vmcb->save.rip +1 ; -skip_emulated_instruction (vcpu); -return kvm_emulate_halt (vcpu); +skip_emulated_instruction (&svm->vcpu); +return kvm_emulate_halt (&svm->vcpu); } -static int vmmcall_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int vmmcall_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu); - svm->next_rip = svm->vmcb->save.rip +3 ; -skip_emulated_instruction (vcpu); -return kvm_hypercall (vcpu, kvm_run); +skip_emulated_instruction (&svm->vcpu); +return kvm_hypercall (&svm->vcpu, kvm_run); } -static int invalid_op_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int invalid_op_interception (struct vcpu_svm *svm, +struct kvm_run *kvm_run) { -inject_ud (vcpu); +inject_ud (&svm->vcpu);return 1 ; } -static int task_switch_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int task_switch_interception (struct vcpu_svm *svm, +struct kvm_run *kvm_run) {printk (KERN_DEBUG "%s: task swiche is unsupported\n" , __FUNCTION__); kvm_run->exit_reason =KVM_EXIT_UNKNOWN ;return 0 ; } -static int cpuid_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int cpuid_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu); - svm->next_rip = svm->vmcb->save.rip +2 ; -kvm_emulate_cpuid (vcpu); +kvm_emulate_cpuid (&svm->vcpu);return 1 ; } -static int emulate_on_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int emulate_on_interception (struct vcpu_svm *svm, +struct kvm_run *kvm_run) { -if (emulate_instruction (vcpu,NULL ,0 ,0 ) !=EMULATE_DONE ) +if (emulate_instruction (&svm->vcpu,NULL ,0 ,0 ) !=EMULATE_DONE )printk (KERN_ERR "%s: failed\n" , __FUNCTION__);return 1 ; }
@@ -1241,19 +1231,18 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)return 0 ; } -static int rdmsr_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int rdmsr_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu); -u32 ecx = vcpu->regs[VCPU_REGS_RCX ]; +u32 ecx = svm->vcpu.regs[VCPU_REGS_RCX ];u64 data; -if (svm_get_msr (vcpu, ecx, &data)) -svm_inject_gp (vcpu,0 ); +if (svm_get_msr (&svm->vcpu, ecx, &data)) +svm_inject_gp (&svm->vcpu,0 );else { svm->vmcb->save.rax = data &0xffffffff ; - vcpu->regs[VCPU_REGS_RDX ] = data >>32 ; + svm->vcpu.regs[VCPU_REGS_RDX ] = data >>32 ; svm->next_rip = svm->vmcb->save.rip +2 ; -skip_emulated_instruction (vcpu); +skip_emulated_instruction (&svm->vcpu); }return 1 ; }
@@ -1302,29 +1291,28 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)return 0 ; } -static int wrmsr_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int wrmsr_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu); -u32 ecx = vcpu->regs[VCPU_REGS_RCX ]; +u32 ecx = svm->vcpu.regs[VCPU_REGS_RCX ];u64 data = (svm->vmcb->save.rax &-1u ) - | ((u64)(vcpu->regs[VCPU_REGS_RDX ] &-1u ) <<32 ); + | ((u64)(svm->vcpu.regs[VCPU_REGS_RDX ] &-1u ) <<32 ); svm->next_rip = svm->vmcb->save.rip +2 ; -if (svm_set_msr (vcpu, ecx, data)) -svm_inject_gp (vcpu,0 ); +if (svm_set_msr (&svm->vcpu, ecx, data)) +svm_inject_gp (&svm->vcpu,0 );else -skip_emulated_instruction (vcpu); +skip_emulated_instruction (&svm->vcpu);return 1 ; } -static int msr_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int msr_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -if (to_svm (vcpu)->vmcb->control.exit_info_1) -return wrmsr_interception (vcpu, kvm_run); +if (svm->vmcb->control.exit_info_1) +return wrmsr_interception (svm, kvm_run);else -return rdmsr_interception (vcpu, kvm_run); +return rdmsr_interception (svm, kvm_run); } -static int interrupt_window_interception (struct kvm_vcpu *vcpu, +static int interrupt_window_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) {/*
@@ -1332,8 +1320,8 @@ static int interrupt_window_interception(struct kvm_vcpu *vcpu,* possible */ if (kvm_run->request_interrupt_window && - !vcpu->irq_summary) { - ++vcpu->stat.irq_window_exits; + !svm->vcpu.irq_summary) { + ++svm->vcpu.stat.irq_window_exits; kvm_run->exit_reason =KVM_EXIT_IRQ_WINDOW_OPEN ;return 0 ; }
@@ -1341,7 +1329,7 @@ static int interrupt_window_interception(struct kvm_vcpu *vcpu,return 1 ; } -static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, +static int (*svm_exit_handlers[])(struct vcpu_svm *svm,struct kvm_run *kvm_run) = { [SVM_EXIT_READ_CR0 ] = emulate_on_interception, [SVM_EXIT_READ_CR3 ] = emulate_on_interception,
@@ -1388,9 +1376,8 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, }; -static int handle_exit (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) +static int handle_exit (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu);u32 exit_code = svm->vmcb->control.exit_code; if (is_external_interrupt(svm->vmcb->control.exit_int_info) &&
@@ -1407,7 +1394,7 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)return 0 ; } -return svm_exit_handlers[exit_code](vcpu, kvm_run); +return svm_exit_handlers[exit_code](svm, kvm_run); }static void reload_tss (struct kvm_vcpu *vcpu)
@@ -1419,80 +1406,77 @@ static void reload_tss(struct kvm_vcpu *vcpu)load_TR_desc (); } -static void pre_svm_run (struct kvm_vcpu *vcpu) +static void pre_svm_run (struct vcpu_svm *svm) { -struct vcpu_svm *svm =to_svm (vcpu);int cpu =raw_smp_processor_id ();struct svm_cpu_data *svm_data =per_cpu (svm_data, cpu); svm->vmcb->control.tlb_ctl =TLB_CONTROL_DO_NOTHING ; -if (vcpu->cpu != cpu || +if (svm->vcpu.cpu != cpu || svm->asid_generation != svm_data->asid_generation) -new_asid (vcpu, svm_data); +new_asid (svm, svm_data); } -static inline void kvm_do_inject_irq (struct kvm_vcpu *vcpu) +static inline void kvm_do_inject_irq (struct vcpu_svm *svm) {struct vmcb_control_area *control; - control = &to_svm (vcpu)->vmcb->control; - control->int_vector =pop_irq (vcpu); + control = &svm->vmcb->control; + control->int_vector =pop_irq (&svm->vcpu); control->int_ctl &= ~V_INTR_PRIO_MASK ; control->int_ctl |=V_IRQ_MASK | ((/*control->int_vector >> 4*/ 0xf ) <<V_INTR_PRIO_SHIFT ); } -static void kvm_reput_irq (struct kvm_vcpu *vcpu) +static void kvm_reput_irq (struct vcpu_svm *svm) { -struct vmcb_control_area *control = &to_svm (vcpu)->vmcb->control; +struct vmcb_control_area *control = &svm->vmcb->control;if (control->int_ctl &V_IRQ_MASK ) { control->int_ctl &= ~V_IRQ_MASK ; -push_irq (vcpu, control->int_vector); +push_irq (&svm->vcpu, control->int_vector); } - vcpu->interrupt_window_open = + svm->vcpu.interrupt_window_open = !(control->int_state &SVM_INTERRUPT_SHADOW_MASK ); } -static void do_interrupt_requests (struct kvm_vcpu *vcpu, +static void do_interrupt_requests (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu);struct vmcb_control_area *control = &svm->vmcb->control; - vcpu->interrupt_window_open = + svm->vcpu.interrupt_window_open = (!(control->int_state &SVM_INTERRUPT_SHADOW_MASK ) && (svm->vmcb->save.rflags &X86_EFLAGS_IF )); -if (vcpu->interrupt_window_open && vcpu->irq_summary) +if (svm->vcpu.interrupt_window_open && svm->vcpu.irq_summary)/* * If interrupts enabled, and not blocked by sti or mov ss. Good. */ -kvm_do_inject_irq (vcpu); +kvm_do_inject_irq (svm);/* * Interrupts blocked. Wait for unblock. */ -if (!vcpu->interrupt_window_open && - (vcpu->irq_summary || kvm_run->request_interrupt_window)) { +if (!svm->vcpu.interrupt_window_open && + (svm->vcpu.irq_summary || kvm_run->request_interrupt_window)) { control->intercept |=1ULL <<INTERCEPT_VINTR ; }else control->intercept &= ~(1ULL <<INTERCEPT_VINTR ); } -static void post_kvm_run_save (struct kvm_vcpu *vcpu, +static void post_kvm_run_save (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -struct vcpu_svm *svm =to_svm (vcpu); - - kvm_run->ready_for_interrupt_injection = (vcpu->interrupt_window_open && - vcpu->irq_summary ==0 ); + kvm_run->ready_for_interrupt_injection + = (svm->vcpu.interrupt_window_open && + svm->vcpu.irq_summary ==0 ); kvm_run->if_flag = (svm->vmcb->save.rflags &X86_EFLAGS_IF ) !=0 ; - kvm_run->cr8 = vcpu->cr8; - kvm_run->apic_base = vcpu->apic_base; + kvm_run->cr8 = svm->vcpu.cr8; + kvm_run->apic_base = svm->vcpu.apic_base; }/*
@@ -1501,13 +1485,13 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu,* * No need to exit to userspace if we already have an interrupt queued. */ -static int dm_request_for_irq_injection (struct kvm_vcpu *vcpu, +static int dm_request_for_irq_injection (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -return (!vcpu->irq_summary && +return (!svm->vcpu.irq_summary && kvm_run->request_interrupt_window && - vcpu->interrupt_window_open && - (to_svm (vcpu)->vmcb->save.rflags &X86_EFLAGS_IF )); + svm->vcpu.interrupt_window_open && + (svm->vmcb->save.rflags &X86_EFLAGS_IF )); }static void save_db_regs (unsigned long *db_regs)
@@ -1545,7 +1529,7 @@ again:return r;if (!vcpu->mmio_read_completed) -do_interrupt_requests (vcpu, kvm_run); +do_interrupt_requests (svm, kvm_run);clgi ();
@@ -1554,7 +1538,7 @@ again:if (test_and_clear_bit (KVM_TLB_FLUSH , &vcpu->requests))svm_flush_tlb (vcpu); -pre_svm_run (vcpu); +pre_svm_run (svm);save_host_msrs (vcpu); fs_selector =read_fs ();
@@ -1714,7 +1698,7 @@ again:stgi (); -kvm_reput_irq (vcpu); +kvm_reput_irq (svm); svm->next_rip =0 ;
@@ -1722,29 +1706,29 @@ again: kvm_run->exit_reason =KVM_EXIT_FAIL_ENTRY ; kvm_run->fail_entry.hardware_entry_failure_reason = svm->vmcb->control.exit_code; -post_kvm_run_save (vcpu, kvm_run); +post_kvm_run_save (svm, kvm_run);return 0 ; } - r =handle_exit (vcpu, kvm_run); + r =handle_exit (svm, kvm_run);if (r >0 ) {if (signal_pending (current)) { ++vcpu->stat.signal_exits; -post_kvm_run_save (vcpu, kvm_run); +post_kvm_run_save (svm, kvm_run); kvm_run->exit_reason =KVM_EXIT_INTR ;return -EINTR ; } -if (dm_request_for_irq_injection (vcpu, kvm_run)) { +if (dm_request_for_irq_injection (svm, kvm_run)) { ++vcpu->stat.request_irq_exits; -post_kvm_run_save (vcpu, kvm_run); +post_kvm_run_save (svm, kvm_run); kvm_run->exit_reason =KVM_EXIT_INTR ;return -EINTR ; }kvm_resched (vcpu); goto again; } -post_kvm_run_save (vcpu, kvm_run); +post_kvm_run_save (svm, kvm_run);return r; }
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 34/104 KVM: SVM: internal function name cleanup
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Changes some svm.c internal function names:
1) io_adress -> io_address (de-germanify the spelling)
2) kvm_reput_irq -> reput_irq (it's not a generic kvm function)
3) kvm_do_inject_irq -> (it's not a generic kvm function)
--- drivers/kvm/svm.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
drivers/kvm/svm.c +6 -6
@@ -1060,7 +1060,7 @@ static int io_get_override(struct vcpu_svm *svm,return 0 ; } -static unsigned long io_adress (struct vcpu_svm *svm,int ins,gva_t *address) +static unsigned long io_address (struct vcpu_svm *svm,int ins,gva_t *address) {unsigned long addr_mask;unsigned long *reg;
@@ -1124,7 +1124,7 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)if (string) {unsigned addr_mask; - addr_mask =io_adress (svm, in, &address); + addr_mask =io_address (svm, in, &address);if (!addr_mask) {printk (KERN_DEBUG "%s: get io address failed\n" , __FUNCTION__);
@@ -1419,7 +1419,7 @@ static void pre_svm_run(struct vcpu_svm *svm) } -static inline void kvm_do_inject_irq (struct vcpu_svm *svm) +static inline void inject_irq (struct vcpu_svm *svm) {struct vmcb_control_area *control;
@@ -1430,7 +1430,7 @@ static inline void kvm_do_inject_irq(struct vcpu_svm *svm) ((/*control->int_vector >> 4*/ 0xf ) <<V_INTR_PRIO_SHIFT ); } -static void kvm_reput_irq (struct vcpu_svm *svm) +static void reput_irq (struct vcpu_svm *svm) {struct vmcb_control_area *control = &svm->vmcb->control;
@@ -1456,7 +1456,7 @@ static void do_interrupt_requests(struct vcpu_svm *svm,/* * If interrupts enabled, and not blocked by sti or mov ss. Good. */ -kvm_do_inject_irq (svm); +inject_irq (svm);/* * Interrupts blocked. Wait for unblock.
@@ -1698,7 +1698,7 @@ again:stgi (); -kvm_reput_irq (svm); +reput_irq (svm); svm->next_rip =0 ;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 35/104 KVM: Change the emulator_{read,write,cmpxchg}_* functions to take a vcpu
In reply to Avi KivityFrom: Laurent Vivier <Laurent.Vivier-6ktuUTfB/[email protected]>
... instead of a x86_emulate_ctxt, so that other callers can use it easily.
--- drivers/kvm/kvm_main.c | 25 +++++++++++-------------- drivers/kvm/x86_emulate.c | 35 ++++++++++++++++++++--------------- drivers/kvm/x86_emulate.h | 10 +++++----- 3 files changed, 36 insertions(+), 34 deletions(-)
drivers/kvm/kvm_main.c +11 -14
@@ -1020,9 +1020,8 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn)static int emulator_read_std (unsigned long addr,void *val,unsigned int bytes, -struct x86_emulate_ctxt *ctxt) +struct kvm_vcpu *vcpu) { -struct kvm_vcpu *vcpu = ctxt->vcpu;void *data = val;while (bytes) {
@@ -1056,7 +1055,7 @@ static int emulator_read_std(unsigned long addr,static int emulator_write_std (unsigned long addr,const void *val,unsigned int bytes, -struct x86_emulate_ctxt *ctxt) +struct kvm_vcpu *vcpu) {printk (KERN_ERR "emulator_write_std: addr %lx n %d\n" , addr, bytes);
@@ -1083,9 +1082,8 @@ static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu,static int emulator_read_emulated (unsigned long addr,void *val,unsigned int bytes, -struct x86_emulate_ctxt *ctxt) +struct kvm_vcpu *vcpu) { -struct kvm_vcpu *vcpu = ctxt->vcpu;struct kvm_io_device *mmio_dev;gpa_t gpa;
@@ -1093,7 +1091,7 @@ static int emulator_read_emulated(unsigned long addr,memcpy (val, vcpu->mmio_data, bytes); vcpu->mmio_read_completed =0 ;return X86EMUL_CONTINUE ; - }else if (emulator_read_std (addr, val, bytes, ctxt) + }else if (emulator_read_std (addr, val, bytes, vcpu) ==X86EMUL_CONTINUE )return X86EMUL_CONTINUE ;
@@ -1140,9 +1138,8 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,static int emulator_write_emulated_onepage (unsigned long addr,const void *val,unsigned int bytes, -struct x86_emulate_ctxt *ctxt) +struct kvm_vcpu *vcpu) { -struct kvm_vcpu *vcpu = ctxt->vcpu;struct kvm_io_device *mmio_dev;gpa_t gpa = vcpu->mmu.gva_to_gpa (vcpu, addr);
@@ -1175,28 +1172,28 @@ static int emulator_write_emulated_onepage(unsigned long addr,static int emulator_write_emulated (unsigned long addr,const void *val,unsigned int bytes, -struct x86_emulate_ctxt *ctxt) +struct kvm_vcpu *vcpu) {/* Crossing a page boundary? */ if (((addr + bytes -1 ) ^ addr) &PAGE_MASK ) {int rc, now; now = -addr & ~PAGE_MASK ; - rc =emulator_write_emulated_onepage (addr, val, now, ctxt); + rc =emulator_write_emulated_onepage (addr, val, now, vcpu);if (rc !=X86EMUL_CONTINUE )return rc; addr += now; val += now; bytes -= now; } -return emulator_write_emulated_onepage (addr, val, bytes, ctxt); +return emulator_write_emulated_onepage (addr, val, bytes, vcpu); }static int emulator_cmpxchg_emulated (unsigned long addr,const void *old,const void *new,unsigned int bytes, -struct x86_emulate_ctxt *ctxt) +struct kvm_vcpu *vcpu) {static int reported;
@@ -1204,7 +1201,7 @@ static int emulator_cmpxchg_emulated(unsigned long addr, reported =1 ;printk (KERN_WARNING "kvm: emulating exchange as write\n" ); } -return emulator_write_emulated (addr, new, bytes, ctxt); +return emulator_write_emulated (addr, new, bytes, vcpu); }static unsigned long get_segment_base (struct kvm_vcpu *vcpu,int seg)
@@ -1266,7 +1263,7 @@ static void report_emulation_failure(struct x86_emulate_ctxt *ctxt)if (reported)return ; -emulator_read_std (rip_linear, (void *)opcodes,4 , ctxt); +emulator_read_std (rip_linear, (void *)opcodes,4 , ctxt->vcpu); printk(KERN_ERR "emulation failed but !mmio_needed?" " rip %lx %02x %02x %02x %02x\n",
drivers/kvm/x86_emulate.c +20 -15
@@ -420,7 +420,7 @@ struct operand {#define insn_fetch (_type, _size, _eip) \ ({ unsigned long _x; \ rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x, \ - (_size), ctxt); \ + (_size), ctxt->vcpu); \ if ( rc != 0 ) \ goto done; \ (_eip) += (_size); \
@@ -469,10 +469,12 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt,if (op_bytes ==2 ) op_bytes =3 ; *address =0 ; - rc = ops->read_std ((unsigned long )ptr, (unsigned long *)size,2 , ctxt); + rc = ops->read_std ((unsigned long )ptr, (unsigned long *)size,2 , + ctxt->vcpu);if (rc)return rc; - rc = ops->read_std ((unsigned long )ptr +2 , address, op_bytes, ctxt); + rc = ops->read_std ((unsigned long )ptr +2 , address, op_bytes, + ctxt->vcpu);return rc; }
@@ -780,7 +782,7 @@ done_prefixes: src.type =OP_MEM ; src.ptr = (unsigned long *)cr2;if ((rc = ops->read_emulated ((unsigned long )src.ptr, - &src.val, src.bytes, ctxt)) !=0 ) + &src.val, src.bytes, ctxt->vcpu)) !=0 ) goto done; src.orig_val = src.val;break ;
@@ -850,7 +852,7 @@ done_prefixes: }if (!(d & Mov) &&/* optimisation - avoid slow emulated read */ ((rc = ops->read_emulated ((unsigned long )dst.ptr, - &dst.val, dst.bytes, ctxt)) !=0 )) + &dst.val, dst.bytes, ctxt->vcpu)) !=0 )) goto done;break ; }
@@ -963,7 +965,7 @@ done_prefixes: dst.bytes =8 ;if ((rc = ops->read_std (register_address (ctxt->ss_base, _regs[VCPU_REGS_RSP ]), - &dst.val, dst.bytes, ctxt)) !=0 ) + &dst.val, dst.bytes, ctxt->vcpu)) !=0 ) goto done;register_address_increment (_regs[VCPU_REGS_RSP ], dst.bytes);break ;
@@ -1048,7 +1050,7 @@ done_prefixes: dst.bytes =8 ;if ((rc = ops->read_std ((unsigned long )dst.ptr, &dst.val,8 , - ctxt)) !=0 ) + ctxt->vcpu)) !=0 ) goto done; } register_address_increment(_regs[VCPU_REGS_RSP],
@@ -1056,7 +1058,7 @@ done_prefixes:if ((rc = ops->write_std (register_address (ctxt->ss_base, _regs[VCPU_REGS_RSP ]), - &dst.val, dst.bytes, ctxt)) !=0 ) + &dst.val, dst.bytes, ctxt->vcpu)) !=0 ) goto done; no_wb =1 ;break ;
@@ -1091,11 +1093,11 @@ writeback: rc = ops->cmpxchg_emulated ((unsigned long )dst. ptr, &dst.orig_val, &dst.val, dst.bytes, - ctxt); + ctxt->vcpu); else rc = ops->write_emulated ((unsigned long )dst.ptr, &dst.val, dst.bytes, - ctxt); + ctxt->vcpu);if (rc !=0 ) goto done;default :
@@ -1130,7 +1132,7 @@ special_insn: _regs[VCPU_REGS_RDI]);if ((rc = ops->read_emulated (register_address ( override_base ? *override_base : ctxt->ds_base, - _regs[VCPU_REGS_RSI ]), &dst.val, dst.bytes, ctxt)) !=0 ) + _regs[VCPU_REGS_RSI ]), &dst.val, dst.bytes, ctxt->vcpu)) !=0 ) goto done;register_address_increment (_regs[VCPU_REGS_RSI ], (_eflags &EFLG_DF ) ? -dst.bytes : dst.bytes);
@@ -1152,7 +1154,8 @@ special_insn: dst.type =OP_REG ; dst.bytes = (d & ByteOp) ?1 : op_bytes; dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX ]; -if ((rc = ops->read_emulated (cr2, &dst.val, dst.bytes, ctxt)) !=0 ) +if ((rc = ops->read_emulated (cr2, &dst.val, dst.bytes, + ctxt->vcpu)) !=0 ) goto done;register_address_increment (_regs[VCPU_REGS_RSI ], (_eflags &EFLG_DF ) ? -dst.bytes : dst.bytes);
@@ -1171,7 +1174,8 @@ special_insn: pop_instruction:if ((rc = ops->read_std (register_address (ctxt->ss_base, - _regs[VCPU_REGS_RSP ]), dst.ptr, op_bytes, ctxt)) !=0 ) + _regs[VCPU_REGS_RSP ]), dst.ptr, op_bytes, ctxt->vcpu)) + !=0 ) goto done;register_address_increment (_regs[VCPU_REGS_RSP ], op_bytes);
@@ -1378,7 +1382,8 @@ twobyte_special_insn:case 0xc7 :/* Grp9 (cmpxchg8b) */ {u64 old, new; -if ((rc = ops->read_emulated (cr2, &old,8 , ctxt)) !=0 ) +if ((rc = ops->read_emulated (cr2, &old,8 , ctxt->vcpu)) + !=0 ) goto done;if (((u32) (old >>0 ) != (u32 ) _regs[VCPU_REGS_RAX ]) || ((u32) (old >>32 ) != (u32 ) _regs[VCPU_REGS_RDX ])) {
@@ -1389,7 +1394,7 @@ twobyte_special_insn: new = ((u64 )_regs[VCPU_REGS_RCX ] <<32 ) | (u32 ) _regs[VCPU_REGS_RBX ];if ((rc = ops->cmpxchg_emulated (cr2, &old, - &new,8 , ctxt)) !=0 ) + &new,8 , ctxt->vcpu)) !=0 ) goto done; _eflags |=EFLG_ZF ; }
drivers/kvm/x86_emulate.h +5 -5
@@ -60,7 +60,7 @@ struct x86_emulate_ops {* @bytes: [IN ] Number of bytes to read from memory. */ int (*read_std)(unsigned long addr,void *val, -unsigned int bytes,struct x86_emulate_ctxt * ctxt); +unsigned int bytes,struct kvm_vcpu *vcpu);/* * write_std: Write bytes of standard (non-emulated/special) memory.
@@ -71,7 +71,7 @@ struct x86_emulate_ops {* @bytes: [IN ] Number of bytes to write to memory. */ int (*write_std)(unsigned long addr,const void *val, -unsigned int bytes,struct x86_emulate_ctxt * ctxt); +unsigned int bytes,struct kvm_vcpu *vcpu);/* * read_emulated: Read bytes from emulated/special memory area.
@@ -82,7 +82,7 @@ struct x86_emulate_ops {int (*read_emulated) (unsigned long addr,void *val,unsigned int bytes, -struct x86_emulate_ctxt * ctxt); +struct kvm_vcpu *vcpu);/* * write_emulated: Read bytes from emulated/special memory area.
@@ -94,7 +94,7 @@ struct x86_emulate_ops {int (*write_emulated) (unsigned long addr,const void *val,unsigned int bytes, -struct x86_emulate_ctxt * ctxt); +struct kvm_vcpu *vcpu);/* * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG operation on an
@@ -108,7 +108,7 @@ struct x86_emulate_ops {const void *old, const void *new, unsigned int bytes, - struct x86_emulate_ctxt * ctxt); + struct kvm_vcpu *vcpu); };
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 36/104 KVM: Remove kvm_{read,write}_guest()
In reply to Avi KivityFrom: Laurent Vivier <Laurent.Vivier-6ktuUTfB/[email protected]>
... in favor of the more general emulator_{read,write}_*.
--- drivers/kvm/kvm.h | 17 +++++------ drivers/kvm/kvm_main.c | 74 ++--------------------------------------------- drivers/kvm/svm.c | 3 +- drivers/kvm/vmx.c | 19 +++++++----- 4 files changed, 25 insertions(+), 88 deletions(-)
drivers/kvm/kvm.h +8 -9
@@ -561,15 +561,14 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);void kvm_put_guest_fpu (struct kvm_vcpu *vcpu);void kvm_flush_remote_tlbs (struct kvm *kvm); -int kvm_read_guest (struct kvm_vcpu *vcpu, -gva_t addr, -unsigned long size, -void *dest); - -int kvm_write_guest (struct kvm_vcpu *vcpu, -gva_t addr, -unsigned long size, -void *data); +int emulator_read_std (unsigned long addr, +void *val, +unsigned int bytes, +struct kvm_vcpu *vcpu); +int emulator_write_emulated (unsigned long addr, +const void *val, +unsigned int bytes, +struct kvm_vcpu *vcpu);unsigned long segment_base (u16 selector);
drivers/kvm/kvm_main.c +4 -70
104 lines not on this page · raw message
drivers/kvm/svm.c +2 -1
@@ -1019,7 +1019,8 @@ static int io_get_override(struct vcpu_svm *svm, svm->vmcb->control.exit_info_2, ins_length); -if (kvm_read_guest (&svm->vcpu, rip, ins_length, inst) != ins_length) +if (emulator_read_std (rip, inst, ins_length, &svm->vcpu) + !=X86EMUL_CONTINUE )/* #PF */ return 0 ;
drivers/kvm/vmx.c +11 -8
@@ -16,6 +16,7 @@*/ #include "kvm.h" +#include "x86_emulate.h" #include "vmx.h" #include "segment_descriptor.h"
@@ -1553,8 +1554,8 @@ static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq)return ; } -if (kvm_read_guest (vcpu, irq *sizeof (ent),sizeof (ent), &ent) != -sizeof (ent)) { +if (emulator_read_std (irq *sizeof (ent), &ent,sizeof (ent), vcpu) != +X86EMUL_CONTINUE ) {vcpu_printf (vcpu,"%s: read guest err\n" , __FUNCTION__);return ; }
@@ -1564,9 +1565,9 @@ static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) ip =vmcs_readl (GUEST_RIP ); -if (kvm_write_guest (vcpu, ss_base + sp -2 ,2 , &flags) !=2 || -kvm_write_guest (vcpu, ss_base + sp -4 ,2 , &cs) !=2 || -kvm_write_guest (vcpu, ss_base + sp -6 ,2 , &ip) !=2 ) { +if (emulator_write_emulated (ss_base + sp -2 , &flags,2 , vcpu) !=X86EMUL_CONTINUE || +emulator_write_emulated (ss_base + sp -4 , &cs,2 , vcpu) !=X86EMUL_CONTINUE || +emulator_write_emulated (ss_base + sp -6 , &ip,2 , vcpu) !=X86EMUL_CONTINUE ) {vcpu_printf (vcpu,"%s: write guest err\n" , __FUNCTION__);return ; }
@@ -1767,7 +1768,7 @@ static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count)u64 inst;gva_t rip;int countr_size; -int i, n; +int i;if ((vmcs_readl (GUEST_RFLAGS ) &X86_EFLAGS_VM )) { countr_size =2 ;
@@ -1782,9 +1783,11 @@ static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count)if (countr_size !=8 ) rip +=vmcs_readl (GUEST_CS_BASE ); - n =kvm_read_guest (vcpu, rip,sizeof (inst), &inst); +if (emulator_read_std (rip, &inst,sizeof (inst), vcpu) != +X86EMUL_CONTINUE ) +return 0 ; -for (i =0 ; i < n; i++) { +for (i =0 ; i <sizeof (inst); i++) {switch (((u8 *)&inst)[i]) {case 0xf0 :case 0xf2 :
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 37/104 KVM: Use kmem cache for allocating vcpus
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Avi wants the allocations of vcpus centralized again. The easiest way is to add a "size" arg to kvm_init_arch, and expose the thus-prepared cache to the modules.
--- drivers/kvm/kvm.h | 4 +++- drivers/kvm/kvm_main.c | 16 +++++++++++++++- drivers/kvm/svm.c | 5 +++-- drivers/kvm/vmx.c | 4 ++-- 4 files changed, 23 insertions(+), 6 deletions(-)
drivers/kvm/kvm.h +3 -1
@@ -141,6 +141,7 @@ struct kvm_mmu_page { };struct kvm_vcpu ; +extern struct kmem_cache *kvm_vcpu_cache;/* * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level
@@ -483,7 +484,8 @@ extern struct kvm_arch_ops *kvm_arch_ops;int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id);void kvm_vcpu_uninit (struct kvm_vcpu *vcpu); -int kvm_init_arch (struct kvm_arch_ops *ops,struct module *module); +int kvm_init_arch (struct kvm_arch_ops *ops,unsigned int vcpu_size, +struct module *module);void kvm_exit_arch (void );int kvm_mmu_module_init (void );
drivers/kvm/kvm_main.c +15 -1
@@ -53,6 +53,8 @@ static LIST_HEAD(vm_list);static cpumask_t cpus_hardware_enabled;struct kvm_arch_ops *kvm_arch_ops; +struct kmem_cache *kvm_vcpu_cache; +EXPORT_SYMBOL_GPL (kvm_vcpu_cache);static __read_mostly struct preempt_ops kvm_preempt_ops;
@@ -3104,7 +3106,8 @@ static void kvm_sched_out(struct preempt_notifier *pn, kvm_arch_ops->vcpu_put (vcpu); } -int kvm_init_arch (struct kvm_arch_ops *ops,struct module *module) +int kvm_init_arch (struct kvm_arch_ops *ops,unsigned int vcpu_size, +struct module *module) {int r;
@@ -3142,6 +3145,14 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)if (r) goto out_free_3; +/* A kmem cache lets us meet the alignment requirements of fx_save. */ + kvm_vcpu_cache =kmem_cache_create ("kvm_vcpu" , vcpu_size, + __alignof__(struct kvm_vcpu ),0 ,0 ); +if (!kvm_vcpu_cache) { + r = -ENOMEM ; + goto out_free_4; + } + kvm_chardev_ops.owner = module; r =misc_register (&kvm_dev);
@@ -3156,6 +3167,8 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)return r; out_free: +kmem_cache_destroy (kvm_vcpu_cache); +out_free_4:sysdev_unregister (&kvm_sysdev); out_free_3:sysdev_class_unregister (&kvm_sysdev_class);
@@ -3173,6 +3186,7 @@ out:void kvm_exit_arch (void ) {misc_deregister (&kvm_dev); +kmem_cache_destroy (kvm_vcpu_cache);sysdev_unregister (&kvm_sysdev);sysdev_class_unregister (&kvm_sysdev_class);unregister_reboot_notifier (&kvm_reboot_notifier);
drivers/kvm/svm.c +3 -2
@@ -577,7 +577,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)struct page *page;int err; - svm =kzalloc (sizeof *svm,GFP_KERNEL ); + svm =kmem_cache_zalloc (kvm_vcpu_cache,GFP_KERNEL );if (!svm) { err = -ENOMEM ; goto out;
@@ -1849,7 +1849,8 @@ static struct kvm_arch_ops svm_arch_ops = {static int __init svm_init (void ) { -return kvm_init_arch (&svm_arch_ops,THIS_MODULE ); +return kvm_init_arch (&svm_arch_ops,sizeof (struct vcpu_svm ), +THIS_MODULE ); } static void __exit svm_exit(void)
drivers/kvm/vmx.c +2 -2
@@ -2365,7 +2365,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *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 (kvm_vcpu_cache,GFP_KERNEL );int cpu;if (!vmx)
@@ -2490,7 +2490,7 @@ static int __init vmx_init(void)memset (iova,0xff ,PAGE_SIZE );kunmap (vmx_io_bitmap_b); - r =kvm_init_arch (&vmx_arch_ops,THIS_MODULE ); + r =kvm_init_arch (&vmx_arch_ops,sizeof (struct vcpu_vmx ),THIS_MODULE );if (r) goto out1;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 38/104 KVM: Use alignment properties of vcpu to simplify FPU ops
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Now 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.
--- drivers/kvm/kvm.h | 13 ++++--------- drivers/kvm/kvm_main.c | 45 +++++++++++++++++---------------------------- drivers/kvm/svm.c | 8 ++++---- 3 files changed, 25 insertions(+), 41 deletions(-)
drivers/kvm/kvm.h +4 -9
@@ -45,10 +45,6 @@#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#define DF_VECTOR 8
@@ -342,9 +338,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;
@@ -704,12 +699,12 @@ static inline unsigned long read_msr(unsigned long msr) }#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)); }
drivers/kvm/kvm_main.c +17 -28
93 lines not on this page · raw message
drivers/kvm/svm.c +4 -4
@@ -1557,8 +1557,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 (
@@ -1670,8 +1670,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 ))
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 39/104 KVM: kvm_vm_ioctl_get_dirty_log restore "nothing dirty" optimization
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
kvm_vm_ioctl_get_dirty_log scans bitmap to see it it's all zero, but doesn't use that information.
Avi says:
Looks like it was used to guard kvm_mmu_slot_remove_write_access();
optimizing the case where the guest just leaves the screen alone (which it usually does, especially in benchmarks).
I'd rather reinstate that optimization. See 90cb0529dd230548a7f0d6b315997be854caea1b where the damage was done.
It's pretty simple: if the bitmap is all zero, we don't need to do anything to clean it.
--- drivers/kvm/kvm_main.c | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-)
drivers/kvm/kvm_main.c +8 -5
@@ -803,11 +803,14 @@ static int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,if (copy_to_user (log->dirty_bitmap, memslot->dirty_bitmap, n)) goto out; -mutex_lock (&kvm->lock); -kvm_mmu_slot_remove_write_access (kvm, log->slot); -kvm_flush_remote_tlbs (kvm); -memset (memslot->dirty_bitmap,0 , n); -mutex_unlock (&kvm->lock); +/* If nothing is dirty, don't bother messing with page tables. */ +if (any) { +mutex_lock (&kvm->lock); +kvm_mmu_slot_remove_write_access (kvm, log->slot); +kvm_flush_remote_tlbs (kvm); +memset (memslot->dirty_bitmap,0 , n); +mutex_unlock (&kvm->lock); + } r =0 ;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 40/104 KVM: VMX: Add cpu consistency check
In reply to Avi KivityFrom: Yang, Sheng <[email protected]>
All the physical CPUs on the board should support the same VMX feature set. Add check_processor_compatibility to kvm_arch_ops for the consistency check.
--- drivers/kvm/kvm.h | 1 + drivers/kvm/kvm_main.c | 10 +++++++++ drivers/kvm/svm.c | 6 +++++ drivers/kvm/vmx.c | 51 +++++++++++++++++++++++++++++++---------------- 4 files changed, 50 insertions(+), 18 deletions(-)
drivers/kvm/kvm.h +1 -0
@@ -420,6 +420,7 @@ struct kvm_arch_ops {int (*disabled_by_bios)(void );/* __init */ void (*hardware_enable)(void *dummy);/* __init */ void (*hardware_disable)(void *dummy); +void (*check_processor_compatibility)(void *rtn);int (*hardware_setup)(void );/* __init */ void (*hardware_unsetup)(void );/* __exit */
drivers/kvm/kvm_main.c +10 -0
@@ -3102,6 +3102,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, unsigned int vcpu_size, struct module *module) {int r; +int cpu;if (kvm_arch_ops) {printk (KERN_ERR "kvm: already loaded the other module\n" );
@@ -3123,6 +3124,14 @@ int kvm_init_arch(struct kvm_arch_ops *ops, unsigned int vcpu_size,if (r <0 ) goto out; +for_each_online_cpu (cpu) { +smp_call_function_single (cpu, + kvm_arch_ops->check_processor_compatibility, + &r,0 ,1 ); +if (r <0 ) + goto out_free_0; + } +on_each_cpu (hardware_enable,NULL ,0 ,1 ); r =register_cpu_notifier (&kvm_cpu_notifier);if (r)
@@ -3169,6 +3178,7 @@ out_free_2:unregister_cpu_notifier (&kvm_cpu_notifier); out_free_1:on_each_cpu (hardware_disable,NULL ,0 ,1 ); +out_free_0: kvm_arch_ops->hardware_unsetup (); out: kvm_arch_ops =NULL ;
drivers/kvm/svm.c +6 -0
@@ -1798,11 +1798,17 @@ svm_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall) hypercall[3 ] =0xc3 ; } +static void svm_check_processor_compat (void *rtn) +{ + *(int *)rtn =0 ; +} +static struct kvm_arch_ops svm_arch_ops = { .cpu_has_kvm_support = has_svm, .disabled_by_bios = is_disabled, .hardware_setup = svm_hardware_setup, .hardware_unsetup = svm_hardware_unsetup, + .check_processor_compatibility = svm_check_processor_compat, .hardware_enable = svm_hardware_enable, .hardware_disable = svm_hardware_disable,
drivers/kvm/vmx.c +33 -18
116 lines not on this page · raw message
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 41/104 KVM: Don't assign vcpu->cr3 if it's invalid: check first, set last
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
--- drivers/kvm/kvm_main.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/kvm/kvm_main.c +3 -2
@@ -579,7 +579,6 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) } } - vcpu->cr3 = cr3;mutex_lock (&vcpu->kvm->lock);/* * Does the new cr3 value map to physical memory? (Note, we
@@ -592,8 +591,10 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)*/ if (unlikely (!gfn_to_memslot (vcpu->kvm, cr3 >>PAGE_SHIFT )))inject_gp (vcpu); -else +else { + vcpu->cr3 = cr3; vcpu->mmu.new_cr3 (vcpu); + }mutex_unlock (&vcpu->kvm->lock); }EXPORT_SYMBOL_GPL (set_cr3);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 42/104 KVM: Cleanup mark_page_dirty
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
For some reason, mark_page_dirty open-codes __gfn_to_memslot().
--- drivers/kvm/kvm_main.c | 24 +++++++----------------- 1 files changed, 7 insertions(+), 17 deletions(-)
drivers/kvm/kvm_main.c +7 -17
@@ -916,28 +916,18 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) }EXPORT_SYMBOL_GPL (gfn_to_page); +/* WARNING: Does not work on aliased pages. */ void mark_page_dirty (struct kvm *kvm,gfn_t gfn) { -int i;struct kvm_memory_slot *memslot; -unsigned long rel_gfn; -for (i =0 ; i < kvm->nmemslots; ++i) { - memslot = &kvm->memslots[i]; + memslot =__gfn_to_memslot (kvm, gfn); +if (memslot && memslot->dirty_bitmap) { +unsigned long rel_gfn = gfn - memslot->base_gfn; -if (gfn >= memslot->base_gfn - && gfn < memslot->base_gfn + memslot->npages) { - -if (!memslot->dirty_bitmap) -return ; - - rel_gfn = gfn - memslot->base_gfn; - -/* avoid RMW */ -if (!test_bit (rel_gfn, memslot->dirty_bitmap)) -set_bit (rel_gfn, memslot->dirty_bitmap); -return ; - } +/* avoid RMW */ +if (!test_bit (rel_gfn, memslot->dirty_bitmap)) +set_bit (rel_gfn, memslot->dirty_bitmap); } }
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 43/104 KVM: SVM: Make set_msr_interception more reliable
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
set_msr_interception() is used by svm to set up which MSRs should be intercepted. It can only fail if someone has changed the code to try to intercept an MSR without updating the array of ranges.
The return value is ignored anyway: it should just BUG() if it doesn't work. (A build-time failure would be better, but that's tricky).
--- drivers/kvm/svm.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-)
drivers/kvm/svm.c +4 -5
@@ -359,8 +359,8 @@ err_1: } -static int set_msr_interception (u32 *msrpm,unsigned msr, -int read,int write) +static void set_msr_interception (u32 *msrpm,unsigned msr, +int read,int write) {int i;
@@ -375,11 +375,10 @@ static int set_msr_interception(u32 *msrpm, unsigned msr,u32 mask = ((write) ?0 :2 ) | ((read) ?0 :1 ); *base = (*base & ~(0x3 << msr_shift)) | (mask << msr_shift); -return 1 ; +return ; } } -printk (KERN_DEBUG "%s: not found 0x%x\n" , __FUNCTION__, msr); -return 0 ; +BUG (); }static __init int svm_hardware_setup (void )
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 44/104 KVM: Remove redundant alloc_vmcs_cpu declaration
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
alloc_vmcs_cpu is already declared (static) above, no need to redeclare.
--- drivers/kvm/vmx.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/kvm/vmx.c +0 -2
@@ -949,8 +949,6 @@ static void free_kvm_area(void)free_vmcs (per_cpu (vmxarea, cpu)); } -extern struct vmcs *alloc_vmcs_cpu (int cpu); -static __init int alloc_kvm_area (void ) {int cpu;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 45/104 KVM: Fix defined but not used warning in drivers/kvm/vmx.c
In reply to Avi KivityFrom: Gabriel C <nix.or.die-gM/[email protected]>
move_msr_up() is used only on X86_64 and generates a warning on !X86_64
--- drivers/kvm/vmx.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/kvm/vmx.c +2 -0
@@ -544,6 +544,7 @@ static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)/* * Swap MSR entry in host/guest MSR entry array. */ +#ifdef CONFIG_X86_64 static void move_msr_up (struct vcpu_vmx *vmx,int from,int to) {struct kvm_msr_entry tmp;
@@ -555,6 +556,7 @@ static void move_msr_up(struct vcpu_vmx *vmx, int from, int to) vmx->host_msrs[to] = vmx->host_msrs[from]; vmx->host_msrs[from] = tmp; } +#endif /* * Set up the vmcs to automatically save and restore system
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 045/104] KVM: Fix defined but not used warning in drivers/kvm/vmx.c
You've got to be kidding me.
104 patches is way over the top, post them in smaller chunks please instead of killing vger.kernel.org as it has to crunch out every single one of these 104 patches to several thousand recipients.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [kvm-devel] [PATCH 045/104] KVM: Fix defined but not used warning in drivers/kvm/vmx.c
Quoted 8 lines · David Miller
You've got to be kidding me.
104 patches is way over the top, post them in smaller chunks please instead of killing vger.kernel.org as it has to crunch out every single one of these 104 patches to several thousand recipients.
I can understand the load on the humans (and will split into several rounds in the future), but why is vger.kernel.org so badly affected? Shouldn't the mta throttle itself instead of dying?
Just curious.
Signature · 7 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 46/104 KVM: Remove stat_set from debugfs
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
We shouldn't define stat_set on the debug attributes, since that will cause silent failure on writing: without a set argument, userspace will get -EACCESS.
--- drivers/kvm/kvm_main.c | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-)
drivers/kvm/kvm_main.c +1 -5
@@ -3017,11 +3017,7 @@ static u64 stat_get(void *_offset)return total; } -static void stat_set (void *offset,u64 val) -{ -} - -DEFINE_SIMPLE_ATTRIBUTE (stat_fops, stat_get, stat_set,"%llu\n" ); +DEFINE_SIMPLE_ATTRIBUTE (stat_fops, stat_get,NULL ,"%llu\n" );static __init void kvm_init_debug (void ) {
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 47/104 KVM: Remove unneeded kvm_dev_open and kvm_dev_release functions.
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Devices don't need open or release functions.
--- drivers/kvm/kvm_main.c | 12 ------------ 1 files changed, 0 insertions(+), 12 deletions(-)
drivers/kvm/kvm_main.c +0 -12
@@ -302,11 +302,6 @@ static struct kvm *kvm_create_vm(void)return kvm; } -static int kvm_dev_open (struct inode *inode,struct file *filp) -{ -return 0 ; -} -/* * Free any memory in @free but not in @dont. */
@@ -376,11 +371,6 @@ static void kvm_free_vcpus(struct kvm *kvm) } -static int kvm_dev_release (struct inode *inode,struct file *filp) -{ -return 0 ; -} -static void kvm_destroy_vm (struct kvm *kvm) {spin_lock (&kvm_lock);
@@ -2841,8 +2831,6 @@ out: }static struct file_operations kvm_chardev_ops = { - .open = kvm_dev_open, - .release = kvm_dev_release, .unlocked_ioctl = kvm_dev_ioctl, .compat_ioctl = kvm_dev_ioctl, };
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 48/104 KVM: Add and use pr_unimpl for standard formatting of unimplemented features
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
All guest-invokable printks should be ratelimited to prevent malicious guests from flooding logs. This is a start.
--- drivers/kvm/kvm.h | 8 ++++++++ drivers/kvm/kvm_main.c | 18 ++++++++---------- drivers/kvm/svm.c | 4 ++-- drivers/kvm/vmx.c | 2 +- 4 files changed, 19 insertions(+), 13 deletions(-)
drivers/kvm/kvm.h +8 -0
@@ -474,6 +474,14 @@ struct kvm_arch_ops {extern struct kvm_arch_ops *kvm_arch_ops; +/* The guest did something we don't support. */ +#define pr_unimpl (vcpu, fmt, ...) \ + do { \ + if (printk_ratelimit()) \ + printk(KERN_ERR "kvm: %i: cpu%i " fmt, \ + current->tgid, (vcpu)->vcpu_id , ## __VA_ARGS__); \ + } while(0) + #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) #define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt)
drivers/kvm/kvm_main.c +8 -10
@@ -962,8 +962,7 @@ static int emulator_write_std(unsigned long addr, unsigned int bytes, struct kvm_vcpu *vcpu) { - printk(KERN_ERR "emulator_write_std: addr %lx n %d\n", - addr, bytes); + pr_unimpl(vcpu, "emulator_write_std: addr %lx n %d\n", addr, bytes);return X86EMUL_UNHANDLEABLE ; }
@@ -1138,8 +1137,7 @@ int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr, unsigned long *dest) *dest = kvm_arch_ops->get_dr (vcpu, dr);return X86EMUL_CONTINUE ;default : -printk (KERN_DEBUG "%s: unexpected dr %u\n" , - __FUNCTION__, dr); +pr_unimpl (vcpu,"%s: unexpected dr %u\n" , __FUNCTION__, dr);return X86EMUL_UNHANDLEABLE ; } }
@@ -1488,7 +1486,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)break ;#endif default : -printk (KERN_ERR "kvm: unhandled rdmsr: 0x%x\n" , msr); +pr_unimpl (vcpu,"unhandled rdmsr: 0x%x\n" , msr);return 1 ; } *pdata = data;
@@ -1543,11 +1541,11 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)break ;#endif case MSR_IA32_MC0_STATUS : -printk (KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n" , +pr_unimpl (vcpu,"%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n" , __FUNCTION__, data);break ;case MSR_IA32_MCG_STATUS : -printk (KERN_WARNING "%s: MSR_IA32_MCG_STATUS 0x%llx, nop\n" , +pr_unimpl (vcpu,"%s: MSR_IA32_MCG_STATUS 0x%llx, nop\n" , __FUNCTION__, data);break ;case MSR_IA32_UCODE_REV :
@@ -1567,7 +1565,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)return vcpu_register_para (vcpu, data);default : -printk (KERN_ERR "kvm: unhandled wrmsr: 0x%x\n" , msr); +pr_unimpl (vcpu,"unhandled wrmsr: 0x%x\n" , msr);return 1 ; }return 0 ;
@@ -1798,7 +1796,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,/* * String I/O in reverse. Yuck. Kill the guest, fix later. */ -printk (KERN_ERR "kvm: guest string pio down\n" ); +pr_unimpl (vcpu,"guest string pio down\n" );inject_gp (vcpu);return 1 ; }
@@ -1829,7 +1827,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, ret =1 ; } }else if (pio_dev) -printk (KERN_ERR "no string pio read support yet, " +pr_unimpl (vcpu,"no string pio read support yet, " "port %x size %d count %ld\n" , port, size, count);
drivers/kvm/svm.c +2 -2
@@ -1167,7 +1167,7 @@ static int invalid_op_interception(struct vcpu_svm *svm,static int task_switch_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run) { -printk (KERN_DEBUG "%s: task swiche is unsupported\n" , __FUNCTION__); +pr_unimpl (&svm->vcpu,"%s: task switch is unsupported\n" , __FUNCTION__); kvm_run->exit_reason =KVM_EXIT_UNKNOWN ;return 0 ; }
@@ -1183,7 +1183,7 @@ static int emulate_on_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) {if (emulate_instruction (&svm->vcpu,NULL ,0 ,0 ) !=EMULATE_DONE ) -printk (KERN_ERR "%s: failed\n" , __FUNCTION__); +pr_unimpl (&svm->vcpu,"%s: failed\n" , __FUNCTION__);return 1 ; }
drivers/kvm/vmx.c +1 -1
@@ -1920,7 +1920,7 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)break ; } kvm_run->exit_reason =0 ; -printk (KERN_ERR "kvm: unhandled control register: op %d cr %d\n" , +pr_unimpl (vcpu,"unhandled control register: op %d cr %d\n" , (int )(exit_qualification >>4 ) &3 , cr);return 0 ; }
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 048/104] KVM: Add and use pr_unimpl for standard formatting of unimplemented features
Quoted 9 lines · Avi Kivity
drivers/kvm/kvm.h +1
-0@@ -474,6 +474,14 @@ struct kvm_arch_ops {extern struct kvm_arch_ops *kvm_arch_ops; +/* The guest did something we don't support. */
drivers/kvm/kvm.h struct kvm_arch_ops { · line 487
Quoted 10 lines
drivers/kvm/kvm.h +7
-0+#define pr_unimpl (vcpu, fmt, ...) \ + do { \ + if (printk_ratelimit()) \ + printk(KERN_ERR "kvm: %i: cpu%i " fmt, \ + current->tgid, (vcpu)->vcpu_id , ## __VA_ARGS__); \ + } while(0) + #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) #define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt)
This converts all KERN_<level> uses to KERN_ERR. It seems better to add a <level> argument to kvm_printf. pr_unimpl is perhaps a poor name choice. perhaps vcpu_printk_ratelimit(vcpu, level, fmt, ...)
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Re: [PATCH 048/104] KVM: Add and use pr_unimpl for standard formatting of unimplemented features
Quoted 9 lines · Joe Perches
Quoted 8 lines · Avi Kivity
drivers/kvm/kvm.h +0
-0@@ -474,6 +474,14 @@ struct kvm_arch_ops {extern struct kvm_arch_ops *kvm_arch_ops;
Quoted 16 lines
drivers/kvm/kvm.h struct kvm_arch_ops { · line 487
Quoted 11 lines
drivers/kvm/kvm.h +8
-0+/* The guest did something we don't support. */ +#define pr_unimpl (vcpu, fmt, ...) \ + do { \ + if (printk_ratelimit()) \ + printk(KERN_ERR "kvm: %i: cpu%i " fmt, \ + current->tgid, (vcpu)->vcpu_id , ## __VA_ARGS__); \ + } while(0) + #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) #define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt)This converts all KERN_<level> uses to
KERN_ERR. It seems better to add a <level> argument tokvm_printf.pr_unimplis perhaps a poor name choice. perhapsvcpu_printk_ratelimit(vcpu, level, fmt, ...)
Possibly, but remember that printk() is an admission of failure. It's only useful to developers, and the only reason for printk over pr_debug() is for users to report to developers when guests crash.
pr_unimpl() means exactly what it says: the guest asked for something we don't support. If that turns out to be the last thing in the logs before a crash, it's a clue. The rest of the printks should probably move to pr_debug().
Hope that helps,
Rusty.
PATCH 49/104 KVM: Use kmem_cache_free for kmem_cache_zalloc'ed objects
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
We use kfree in svm.c and vmx.c, and this works, but it could break at any time. kfree() is supposed to match up with kmalloc().
--- drivers/kvm/svm.c | 4 ++-- drivers/kvm/vmx.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/kvm/svm.c +2 -2
@@ -610,7 +610,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) uninit:kvm_vcpu_uninit (&svm->vcpu); free_svm: -kfree (svm); +kmem_cache_free (kvm_vcpu_cache, svm); out:return ERR_PTR (err); }
@@ -621,7 +621,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)__free_page (pfn_to_page (svm->vmcb_pa >>PAGE_SHIFT ));kvm_vcpu_uninit (vcpu); -kfree (svm); +kmem_cache_free (kvm_vcpu_cache, svm); }static void svm_vcpu_load (struct kvm_vcpu *vcpu,int cpu)
drivers/kvm/vmx.c +2 -2
@@ -2359,7 +2359,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)kfree (vmx->host_msrs);kfree (vmx->guest_msrs);kvm_vcpu_uninit (vcpu); -kfree (vmx); +kmem_cache_free (kvm_vcpu_cache, vmx); }static struct kvm_vcpu *vmx_create_vcpu (struct kvm *kvm,unsigned int id)
@@ -2410,7 +2410,7 @@ free_guest_msrs: uninit_vcpu:kvm_vcpu_uninit (&vmx->vcpu); free_vcpu: -kfree (vmx); +kmem_cache_free (kvm_vcpu_cache, vmx);return ERR_PTR (err); }
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 50/104 KVM: VMX: Remove a duplicated ia32e mode vm entry control
In reply to Avi KivityFrom: Li, Xin B <[email protected]>
Remove a duplicated ia32e mode VM Entry control definition and use the proper one.
--- drivers/kvm/vmx.c | 8 ++++---- drivers/kvm/vmx.h | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-)
drivers/kvm/vmx.c +4 -4
@@ -1111,7 +1111,7 @@ static void enter_lmode(struct kvm_vcpu *vcpu)find_msr_entry (to_vmx (vcpu),MSR_EFER )->data |=EFER_LMA |EFER_LME ;vmcs_write32 (VM_ENTRY_CONTROLS ,vmcs_read32 (VM_ENTRY_CONTROLS ) - |VM_ENTRY_CONTROLS_IA32E_MASK ); + |VM_ENTRY_IA32E_MODE ); }static void exit_lmode (struct kvm_vcpu *vcpu)
@@ -1120,7 +1120,7 @@ static void exit_lmode(struct kvm_vcpu *vcpu)vmcs_write32 (VM_ENTRY_CONTROLS ,vmcs_read32 (VM_ENTRY_CONTROLS ) - & ~VM_ENTRY_CONTROLS_IA32E_MASK); + & ~VM_ENTRY_IA32E_MODE); }#endif
@@ -1185,13 +1185,13 @@ static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)if (efer &EFER_LMA ) {vmcs_write32 (VM_ENTRY_CONTROLS ,vmcs_read32 (VM_ENTRY_CONTROLS ) | -VM_ENTRY_CONTROLS_IA32E_MASK ); +VM_ENTRY_IA32E_MODE ); msr->data = efer; }else {vmcs_write32 (VM_ENTRY_CONTROLS ,vmcs_read32 (VM_ENTRY_CONTROLS ) & - ~VM_ENTRY_CONTROLS_IA32E_MASK ); + ~VM_ENTRY_IA32E_MODE ); msr->data = efer & ~EFER_LME ; }
drivers/kvm/vmx.h +0 -3
@@ -268,9 +268,6 @@ enum vmcs_field {/* segment AR */ #define SEGMENT_AR_L_MASK (1 << 13) -/* entry controls */ -#define VM_ENTRY_CONTROLS_IA32E_MASK (1 << 9) -#define AR_TYPE_ACCESSES_MASK 1#define AR_TYPE_READABLE_MASK (1 << 1)#define AR_TYPE_WRITEABLE_MASK (1 << 2)
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 51/104 KVM: Remove useless assignment
In reply to Avi KivityFrom: Laurent Vivier <Laurent.Vivier-6ktuUTfB/[email protected]>
Line 1809 of kvm_main.c is useless, value is overwritten in line 1815:
1809 now = min(count, PAGE_SIZE / size);
1810
1811 if (!down)
1812 in_page = PAGE_SIZE - offset_in_page(address);
1813 else
1814 in_page = offset_in_page(address) + size;
1815 now = min(count, (unsigned long)in_page / size);
1816 if (!now) {
--- drivers/kvm/kvm_main.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/kvm/kvm_main.c +0 -2
@@ -1776,8 +1776,6 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,return 1 ; } - now =min (count,PAGE_SIZE / size); -if (!down) in_page =PAGE_SIZE -offset_in_page (address);else
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 52/104 KVM: Cleanup string I/O instruction emulation
In reply to Avi KivityFrom: Laurent Vivier <Laurent.Vivier-6ktuUTfB/[email protected]>
Both vmx and svm decode the I/O instructions, and both botch the job, requiring the instruction prefixes to be fetched in order to completely decode the instruction.
So, if we see a string I/O instruction, use the x86 emulator to decode it, as it already has all the prefix decoding machinery.
This patch defines ins/outs opcodes in x86_emulate.c and calls emulate_instruction() from io_interception() (svm.c) and from handle_io() (vmx.c). It removes all vmx/svm prefix instruction decoders (get_addr_size(), io_get_override(), io_address(), get_io_count())
--- drivers/kvm/kvm_main.c | 3 + drivers/kvm/svm.c | 149 +++------------------------------------------ drivers/kvm/vmx.c | 76 ++++------------------- drivers/kvm/x86_emulate.c | 49 +++++++++++++-- 4 files changed, 69 insertions(+), 208 deletions(-)
drivers/kvm/kvm_main.c +3 -0
@@ -1221,7 +1221,10 @@ int emulate_instruction(struct kvm_vcpu *vcpu, emulate_ctxt.fs_base =get_segment_base (vcpu,VCPU_SREG_FS ); vcpu->mmio_is_write =0 ; + vcpu->pio.string =0 ; r =x86_emulate_memop (&emulate_ctxt, &emulate_ops); +if (vcpu->pio.string) +return EMULATE_DO_MMIO ;if ((r || vcpu->mmio_is_write) && run) { run->exit_reason =KVM_EXIT_MMIO ;
drivers/kvm/svm.c +10 -139
177 lines not on this page · raw message
drivers/kvm/vmx.c +12 -64
94 lines not on this page · raw message
drivers/kvm/x86_emulate.c +44 -5
69 lines not on this page · raw message
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 53/104 KVM: Clean up kvm_setup_pio()
In reply to Avi KivityFrom: Laurent Vivier <Laurent.Vivier-6ktuUTfB/[email protected]>
Split kvm_setup_pio() into two functions, one to setup in/out pio (kvm_emulate_pio()) and one to setup ins/outs pio (kvm_emulate_pio_string()).
--- drivers/kvm/kvm.h | 8 +++-- drivers/kvm/kvm_main.c | 63 +++++++++++++++++++++++++++----------------- drivers/kvm/svm.c | 3 +- drivers/kvm/vmx.c | 3 +- drivers/kvm/x86_emulate.c | 6 +--- 5 files changed, 48 insertions(+), 35 deletions(-)
drivers/kvm/kvm.h +5 -3
@@ -539,9 +539,11 @@ int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);struct x86_emulate_ctxt ; -int kvm_setup_pio (struct kvm_vcpu *vcpu,struct kvm_run *run,int in, -int size,unsigned long count,int string,int down, -gva_t address,int rep,unsigned port); +int kvm_emulate_pio (struct kvm_vcpu *vcpu,struct kvm_run *run,int in, +int size,unsigned port); +int kvm_emulate_pio_string (struct kvm_vcpu *vcpu,struct kvm_run *run,int in, +int size,unsigned long count,int down, +gva_t address,int rep,unsigned port);void kvm_emulate_cpuid (struct kvm_vcpu *vcpu);int kvm_emulate_halt (struct kvm_vcpu *vcpu);int emulate_invlpg (struct kvm_vcpu *vcpu,gva_t address);
drivers/kvm/kvm_main.c +39 -24
93 lines not on this page · raw message
drivers/kvm/svm.c +1 -2
@@ -1005,8 +1005,7 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) rep = (io_info &SVM_IOIO_REP_MASK ) !=0 ; down = (svm->vmcb->save.rflags &X86_EFLAGS_DF ) !=0 ; -return kvm_setup_pio (&svm->vcpu, kvm_run, in, size,1 ,0 , - down,0 , rep, port); +return kvm_emulate_pio (&svm->vcpu, kvm_run, in, size, port); }static int nop_on_interception (struct vcpu_svm *svm,struct kvm_run *kvm_run)
drivers/kvm/vmx.c +1 -2
@@ -1785,8 +1785,7 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) rep = (exit_qualification &32 ) !=0 ; port = exit_qualification >>16 ; -return kvm_setup_pio (vcpu, kvm_run, in, size,1 ,0 , down, -0 , rep, port); +return kvm_emulate_pio (vcpu, kvm_run, in, size, port); } static void
drivers/kvm/x86_emulate.c +2 -4
@@ -1123,12 +1123,11 @@ special_insn:switch (b) {case 0x6c :/* insb */ case 0x6d :/* insw/insd */ - if (kvm_setup_pio(ctxt->vcpu, NULL, + if (kvm_emulate_pio_string(ctxt->vcpu, NULL, 1, /* in */ (d & ByteOp) ? 1 : op_bytes, /* size */ rep_prefix ? address_mask(_regs[VCPU_REGS_RCX]) : 1, /* count */ - 1, /* strings */ (_eflags & EFLG_DF), /* down */ register_address(ctxt->es_base, _regs[VCPU_REGS_RDI]), /* address */
@@ -1139,12 +1138,11 @@ special_insn:return 0 ;case 0x6e :/* outsb */ case 0x6f :/* outsw/outsd */ - if (kvm_setup_pio(ctxt->vcpu, NULL, + if (kvm_emulate_pio_string(ctxt->vcpu, NULL, 0, /* in */ (d & ByteOp) ? 1 : op_bytes, /* size */ rep_prefix ? address_mask(_regs[VCPU_REGS_RCX]) : 1, /* count */ - 1, /* strings */ (_eflags & EFLG_DF), /* down */ register_address(override_base ? *override_base : ctxt->ds_base,
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 55/104 KVM: Communicate cr8 changes to userspace
In reply to Avi KivityFrom: Yang, Sheng <[email protected]>
This allows running 64-bit Windows.
--- drivers/kvm/vmx.c | 3 ++- include/linux/kvm.h | 1 + 2 files changed, 3 insertions(+), 1 deletions(-)
drivers/kvm/vmx.c +2 -1
@@ -1831,7 +1831,8 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)vcpu_load_rsp_rip (vcpu);set_cr8 (vcpu, vcpu->regs[reg]);skip_emulated_instruction (vcpu); -return 1 ; + kvm_run->exit_reason =KVM_EXIT_SET_TPR ; +return 0 ; };break ;case 2 :/* clts */
include/linux/kvm.h +1 -0
@@ -46,6 +46,7 @@ enum kvm_exit_reason {KVM_EXIT_SHUTDOWN =8 ,KVM_EXIT_FAIL_ENTRY =9 ,KVM_EXIT_INTR =10 , + KVM_EXIT_SET_TPR = 11 };/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 56/104 KVM: x86 emulator: implement 'and $imm, %{al|ax|eax}'
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement emulation of instruction
and al imm8 (opcode 0x24)
and ax/eax imm16/imm32 (opcode 0x25)--- drivers/kvm/x86_emulate.c | 21 +++++++++++++++++++-- 1 files changed, 19 insertions(+), 2 deletions(-)
drivers/kvm/x86_emulate.c +19 -2
@@ -83,7 +83,7 @@ static u8 opcode_table[256] = {/* 0x20 - 0x27 */ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, -0 ,0 ,0 ,0 , + SrcImmByte, SrcImm,0 ,0 ,/* 0x28 - 0x2F */ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
@@ -882,10 +882,27 @@ done_prefixes: sbb:/* sbb */ emulate_2op_SrcV ("sbb" , src, dst, _eflags);break ; - case 0x20 ... 0x25: + case 0x20 ... 0x23: and:/* and */ emulate_2op_SrcV ("and" , src, dst, _eflags);break ; +case 0x24 :/* and al imm8 */ + dst.type =OP_REG ; + dst.ptr = &_regs[VCPU_REGS_RAX ]; + dst.val = *(u8 *)dst.ptr; + dst.bytes =1 ; + dst.orig_val = dst.val; + goto and; +case 0x25 :/* and ax imm16, or eax imm32 */ + dst.type =OP_REG ; + dst.bytes = op_bytes; + dst.ptr = &_regs[VCPU_REGS_RAX ]; +if (op_bytes ==2 ) + dst.val = *(u16 *)dst.ptr; +else + dst.val = *(u32 *)dst.ptr; + dst.orig_val = dst.val; + goto and; case 0x28 ... 0x2d: sub:/* sub */ emulate_2op_SrcV ("sub" , src, dst, _eflags);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 57/104 KVM: x86 emulator: implement 'jmp rel' instruction (opcode 0xe9)
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
--- drivers/kvm/x86_emulate.c | 16 ++++++++++++++-- 1 files changed, 14 insertions(+), 2 deletions(-)
drivers/kvm/x86_emulate.c +14 -2
@@ -145,8 +145,10 @@ static u8 opcode_table[256] = {0 ,0 ,0 ,0 ,/* 0xD8 - 0xDF */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , -/* 0xE0 - 0xEF */ -0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , +/* 0xE0 - 0xE7 */ +0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , +/* 0xE8 - 0xEF */ +0 , SrcImm|ImplicitOps,0 ,0 ,0 ,0 ,0 ,0 ,/* 0xF0 - 0xF7 */ 0 ,0 ,0 ,0 , ImplicitOps, 0,
@@ -447,6 +449,12 @@ struct operand { (((reg) + _inc) & ((1UL << (ad_bytes <<3 )) -1 )); \ } while (0) +#define JMP_REL (rel) \ + do { \ + _eip += (int)(rel); \ + _eip = ((op_bytes == 2) ? (uint16_t)_eip : (uint32_t)_eip); \ + } while (0) +/* * Given the 'reg' portion of a ModRM byte, and a register block, return a * pointer into the block that addresses the relevant register.
@@ -1023,6 +1031,10 @@ done_prefixes: case 0xd2 ... 0xd3: /* Grp2 */ src.val = _regs[VCPU_REGS_RCX ]; goto grp2; +case 0xe9 :/* jmp rel */ +JMP_REL (src.val); + no_wb =1 ;/* Disable writeback. */ +break ; case 0xf6 ... 0xf7: /* Grp3 */switch (modrm_reg) { case 0 ... 1: /* test */
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 58/104 KVM: x86 emulator: Implement 'jmp rel short' instruction (opcode 0xeb)
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
--- drivers/kvm/x86_emulate.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +2 -1
@@ -148,7 +148,7 @@ static u8 opcode_table[256] = {/* 0xE0 - 0xE7 */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,/* 0xE8 - 0xEF */ -0 , SrcImm|ImplicitOps,0 ,0 ,0 ,0 ,0 ,0 , +0 , SrcImm|ImplicitOps,0 , SrcImmByte|ImplicitOps,0 ,0 ,0 ,0 ,/* 0xF0 - 0xF7 */ 0 ,0 ,0 ,0 , ImplicitOps, 0,
@@ -1032,6 +1032,7 @@ done_prefixes: src.val = _regs[VCPU_REGS_RCX ]; goto grp2;case 0xe9 :/* jmp rel */ +case 0xeb :/* jmp rel short */ JMP_REL (src.val); no_wb =1 ;/* Disable writeback. */ break ;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 59/104 KVM: x86 emulator: implement 'push reg' (opcodes 0x50-0x57)
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
--- drivers/kvm/x86_emulate.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +15 -1
@@ -99,7 +99,8 @@ static u8 opcode_table[256] = {/* 0x40 - 0x4F */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,/* 0x50 - 0x57 */ -0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,/* 0x58 - 0x5F */ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -1151,6 +1152,19 @@ special_insn:if (twobyte) goto twobyte_special_insn;switch (b) { + case 0x50 ... 0x57: /* push reg */ +if (op_bytes ==2 ) + src.val = (u16 ) _regs[b &0x7 ]; +else + src.val = (u32 ) _regs[b &0x7 ]; + dst.type =OP_MEM ; + dst.bytes = op_bytes; + dst.val = src.val; +register_address_increment (_regs[VCPU_REGS_RSP ], -op_bytes); + dst.ptr = (void *)register_address ( + ctxt->ss_base, _regs[VCPU_REGS_RSP ]); + no_wb =1 ;/* force writeback */ +break ;case 0x6c :/* insb */ case 0x6d :/* insw/insd */ if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 60/104 KVM: VMX: allow rmode_tss_base() to work with >2G of guest memory
In reply to Avi KivityFrom: Izik Eidus <izike-atKUWr5tajBWk0Htik3J/[email protected]>
--- drivers/kvm/vmx.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/kvm/vmx.c +1 -1
@@ -1030,7 +1030,7 @@ static void enter_pmode(struct kvm_vcpu *vcpu)vmcs_write32 (GUEST_CS_AR_BYTES ,0x9b ); } -static int rmode_tss_base (struct kvm * kvm) +static gva_t rmode_tss_base (struct kvm * kvm) {gfn_t base_gfn = kvm->memslots[0 ].base_gfn + kvm->memslots[0 ].npages -3 ;return base_gfn <<PAGE_SHIFT ;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 61/104 KVM: Support more memory slots
In reply to Avi KivityFrom: Izik Eidus <izike-atKUWr5tajBWk0Htik3J/[email protected]>
Needed for mapping memory at 4GB.
--- drivers/kvm/kvm.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/kvm/kvm.h +1 -1
@@ -39,7 +39,7 @@#define KVM_MAX_VCPUS 4#define KVM_ALIAS_SLOTS 4 -#define KVM_MEMORY_SLOTS 4 +#define KVM_MEMORY_SLOTS 8#define KVM_NUM_MMU_PAGES 1024#define KVM_MIN_FREE_MMU_PAGES 5#define KVM_REFILL_PAGES 25
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 62/104 KVM: X86 emulator: fix 'push reg' writeback
In reply to Avi KivityPointed out by Rusty Russell.
--- drivers/kvm/x86_emulate.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +0 -1
@@ -1163,7 +1163,6 @@ special_insn:register_address_increment (_regs[VCPU_REGS_RSP ], -op_bytes); dst.ptr = (void *)register_address ( ctxt->ss_base, _regs[VCPU_REGS_RSP ]); - no_wb =1 ;/* force writeback */ break ;case 0x6c :/* insb */ case 0x6d :/* insw/insd */
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 63/104 KVM: VMX: Split segments reload in vmx_load_host_state()
In reply to Avi KivityFrom: Laurent Vivier <Laurent.Vivier-6ktuUTfB/[email protected]>
vmx_load_host_state() bundles fs, gs, ldt, and tss reloading into one in the hope that it is infrequent. With smp guests, fs reloading is frequent due to fs being used by threads.
Unbundle the reloads so reduce expensive gs reloads.
--- drivers/kvm/vmx.c | 22 ++++++++++++---------- 1 files changed, 12 insertions(+), 10 deletions(-)
drivers/kvm/vmx.c +12 -10
@@ -54,7 +54,8 @@ struct vcpu_vmx {struct {int loaded;u16 fs_sel, gs_sel, ldt_sel; -int fs_gs_ldt_reload_needed; +int gs_ldt_reload_needed; +int fs_reload_needed; }host_state; };
@@ -353,20 +354,21 @@ static void vmx_save_host_state(struct vcpu_vmx *vmx)* allow segment selectors with cpl > 0 or ti == 1. */ vmx->host_state.ldt_sel =read_ldt (); - vmx->host_state.fs_gs_ldt_reload_needed = vmx->host_state.ldt_sel; + vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel; vmx->host_state.fs_sel =read_fs (); -if (!(vmx->host_state.fs_sel &7 )) +if (!(vmx->host_state.fs_sel &7 )) {vmcs_write16 (HOST_FS_SELECTOR , vmx->host_state.fs_sel); -else { + vmx->host_state.fs_reload_needed =0 ; + }else {vmcs_write16 (HOST_FS_SELECTOR ,0 ); - vmx->host_state.fs_gs_ldt_reload_needed =1 ; + vmx->host_state.fs_reload_needed =1 ; } vmx->host_state.gs_sel =read_gs ();if (!(vmx->host_state.gs_sel &7 ))vmcs_write16 (HOST_GS_SELECTOR , vmx->host_state.gs_sel);else {vmcs_write16 (HOST_GS_SELECTOR ,0 ); - vmx->host_state.fs_gs_ldt_reload_needed =1 ; + vmx->host_state.gs_ldt_reload_needed =1 ; }#ifdef CONFIG_X86_64
@@ -396,9 +398,10 @@ static void vmx_load_host_state(struct vcpu_vmx *vmx)return ; vmx->host_state.loaded =0 ; -if (vmx->host_state.fs_gs_ldt_reload_needed) { -load_ldt (vmx->host_state.ldt_sel); +if (vmx->host_state.fs_reload_needed)load_fs (vmx->host_state.fs_sel); +if (vmx->host_state.gs_ldt_reload_needed) { +load_ldt (vmx->host_state.ldt_sel);/* * If we have to reload gs, we must take care to * preserve our gs base.
@@ -409,9 +412,8 @@ static void vmx_load_host_state(struct vcpu_vmx *vmx)wrmsrl (MSR_GS_BASE ,vmcs_readl (HOST_GS_BASE ));#endif local_irq_restore (flags); - -reload_tss (); } +reload_tss ();save_msrs (vmx->guest_msrs, vmx->save_nmsrs);load_msrs (vmx->host_msrs, vmx->save_nmsrs);if (msr_efer_need_save_restore (vmx))
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 64/104 KVM: Add support for in-kernel PIC emulation
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
--- drivers/kvm/Makefile | 2 +- drivers/kvm/i8259.c | 442 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/kvm/irq.c | 61 +++++++ drivers/kvm/irq.h | 64 +++++++ drivers/kvm/kvm.h | 11 ++ drivers/kvm/kvm_main.c | 46 +++++- drivers/kvm/svm.c | 69 +++++++- drivers/kvm/vmx.c | 80 ++++++++- include/linux/kvm.h | 19 ++ 9 files changed, 770 insertions(+), 24 deletions(-) create mode 100644 drivers/kvm/i8259.c create mode 100644 drivers/kvm/irq.c create mode 100644 drivers/kvm/irq.h
drivers/kvm/Makefile +1 -1
@@ -2,7 +2,7 @@ # Makefile for Kernel-based Virtual Machine module # -kvm-objs := kvm_main.o mmu.o x86_emulate.o +kvm-objs := kvm_main.o mmu.o x86_emulate.o i8259.o irq.o obj-$(CONFIG_KVM) += kvm.o kvm-intel-objs = vmx.o obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
drivers/kvm/i8259.c new file +442 -0
442 lines not on this page · raw message
drivers/kvm/irq.c new file +61 -0
61 lines not on this page · raw message
drivers/kvm/irq.h new file +64 -0
64 lines not on this page · raw message
drivers/kvm/kvm.h +11 -0
@@ -408,8 +408,19 @@ struct kvm {struct file *filp;struct kvm_io_bus mmio_bus;struct kvm_io_bus pio_bus; +struct kvm_pic *vpic; }; +static inline struct kvm_pic *pic_irqchip (struct kvm *kvm) +{ +return kvm->vpic; +} + +static inline int irqchip_in_kernel (struct kvm *kvm) +{ +return pic_irqchip (kvm) !=0 ; +} +struct descriptor_table {u16 limit;unsigned long base;
drivers/kvm/kvm_main.c +40 -6
77 lines not on this page · raw message
drivers/kvm/svm.c +61 -8
129 lines not on this page · raw message
drivers/kvm/vmx.c +71 -9
122 lines not on this page · raw message
include/linux/kvm.h +19 -0
@@ -34,6 +34,17 @@ struct kvm_memory_alias {__u64 target_phys_addr; }; +/* for KVM_SET_IRQ_LEVEL */ +struct kvm_irq_level { +/* +* ACPI gsi notion of irq. +* For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47.. +* For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23.. +*/ +__u32 irq; +__u32 level; +}; +enum kvm_exit_reason {KVM_EXIT_UNKNOWN =0 ,KVM_EXIT_EXCEPTION =1 ,
@@ -269,6 +280,11 @@ struct kvm_signal_mask {#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04)/* in bytes */ /* +* Extension capability list. +*/ +#define KVM_CAP_IRQCHIP 0 + +/* * ioctls for VM fds */ #define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)
@@ -279,6 +295,9 @@ struct kvm_signal_mask {#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias) +/* Device model IOC */ +#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) +#define KVM_IRQ_LINE _IO(KVMIO, 0x61)/* * ioctls for vcpu fds
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 65/104 KVM: Define and use cr8 access functions
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
This patch is to wrap APIC base register and CR8 operation which can provide a unique API for user level irqchip and kernel irqchip. This is a preparation of merging lapic/ioapic patch.
--- drivers/kvm/kvm.h | 3 +++ drivers/kvm/kvm_main.c | 32 +++++++++++++++++++++++++------- drivers/kvm/svm.c | 8 ++++---- drivers/kvm/vmx.c | 14 ++++++++------ 4 files changed, 40 insertions(+), 17 deletions(-)
drivers/kvm/kvm.h +3 -0
@@ -568,6 +568,9 @@ void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);void set_cr3 (struct kvm_vcpu *vcpu,unsigned long cr0);void set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr0);void set_cr8 (struct kvm_vcpu *vcpu,unsigned long cr0); +unsigned long get_cr8 (struct kvm_vcpu *vcpu); +u64 kvm_get_apic_base (struct kvm_vcpu *vcpu); +void kvm_set_apic_base (struct kvm_vcpu *vcpu,u64 data);void lmsw (struct kvm_vcpu *vcpu,unsigned long msw);int kvm_get_msr_common (struct kvm_vcpu *vcpu,u32 msr,u64 *pdata);
drivers/kvm/kvm_main.c +25 -7
@@ -602,6 +602,24 @@ void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) }EXPORT_SYMBOL_GPL (set_cr8); +unsigned long get_cr8 (struct kvm_vcpu *vcpu) +{ +return vcpu->cr8; +} +EXPORT_SYMBOL_GPL (get_cr8); + +u64 kvm_get_apic_base (struct kvm_vcpu *vcpu) +{ +return vcpu->apic_base; +} +EXPORT_SYMBOL_GPL (kvm_get_apic_base); + +void kvm_set_apic_base (struct kvm_vcpu *vcpu,u64 data) +{ + vcpu->apic_base = data; +} +EXPORT_SYMBOL_GPL (kvm_set_apic_base); +void fx_init (struct kvm_vcpu *vcpu) {unsigned after_mxcsr_mask;
@@ -1481,7 +1499,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) data =3 ;break ;case MSR_IA32_APICBASE : - data = vcpu->apic_base; + data =kvm_get_apic_base (vcpu);break ;case MSR_IA32_MISC_ENABLE : data = vcpu->ia32_misc_enable_msr;
@@ -1559,7 +1577,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) case 0x200 ... 0x2ff: /* MTRRs */break ;case MSR_IA32_APICBASE : - vcpu->apic_base = data; +kvm_set_apic_base (vcpu, data);break ;case MSR_IA32_MISC_ENABLE : vcpu->ia32_misc_enable_msr = data;
@@ -1865,7 +1883,7 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)sigprocmask (SIG_SETMASK , &vcpu->sigset, &sigsaved);/* re-sync apic's tpr */ - vcpu->cr8 = kvm_run->cr8; +set_cr8 (vcpu, kvm_run->cr8);if (vcpu->pio.cur_count) { r =complete_pio (vcpu);
@@ -2013,9 +2031,9 @@ static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, sregs->cr2 = vcpu->cr2; sregs->cr3 = vcpu->cr3; sregs->cr4 = vcpu->cr4; - sregs->cr8 = vcpu->cr8; + sregs->cr8 =get_cr8 (vcpu); sregs->efer = vcpu->shadow_efer; - sregs->apic_base = vcpu->apic_base; + sregs->apic_base =kvm_get_apic_base (vcpu);memcpy (sregs->interrupt_bitmap, vcpu->irq_pending,sizeof sregs->interrupt_bitmap);
@@ -2051,13 +2069,13 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, mmu_reset_needed |= vcpu->cr3 != sregs->cr3; vcpu->cr3 = sregs->cr3; - vcpu->cr8 = sregs->cr8; +set_cr8 (vcpu, sregs->cr8); mmu_reset_needed |= vcpu->shadow_efer != sregs->efer;#ifdef CONFIG_X86_64 kvm_arch_ops->set_efer (vcpu, sregs->efer);#endif - vcpu->apic_base = sregs->apic_base; +kvm_set_apic_base (vcpu, sregs->apic_base); kvm_arch_ops->decache_cr4_guest_bits (vcpu);
drivers/kvm/svm.c +4 -4
@@ -1339,10 +1339,10 @@ static void svm_intr_assist(struct vcpu_svm *svm)static void kvm_reput_irq (struct vcpu_svm *svm) { -struct kvm_vcpu *vcpu = &svm->vcpu;struct vmcb_control_area *control = &svm->vmcb->control; -if ((control->int_ctl &V_IRQ_MASK ) && !irqchip_in_kernel (vcpu->kvm)) { +if ((control->int_ctl &V_IRQ_MASK ) + && !irqchip_in_kernel (svm->vcpu.kvm)) { control->int_ctl &= ~V_IRQ_MASK ;push_irq (&svm->vcpu, control->int_vector); }
@@ -1396,8 +1396,8 @@ static void post_kvm_run_save(struct vcpu_svm *svm, = (svm->vcpu.interrupt_window_open && svm->vcpu.irq_summary ==0 ); kvm_run->if_flag = (svm->vmcb->save.rflags &X86_EFLAGS_IF ) !=0 ; - kvm_run->cr8 = svm->vcpu.cr8; - kvm_run->apic_base = svm->vcpu.apic_base; + kvm_run->cr8 =get_cr8 (&svm->vcpu); + kvm_run->apic_base =kvm_get_apic_base (&svm->vcpu); }/*
drivers/kvm/vmx.c +8 -6
@@ -1369,6 +1369,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)int i;int ret =0 ;unsigned long kvm_vmx_return; +u64 msr;if (!init_rmode_tss (vmx->vcpu.kvm)) { ret = -ENOMEM ;
@@ -1376,10 +1377,11 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) } vmx->vcpu.regs[VCPU_REGS_RDX ] =get_rdx_init_val (); - vmx->vcpu.cr8 =0 ; - vmx->vcpu.apic_base =0xfee00000 |MSR_IA32_APICBASE_ENABLE ; +set_cr8 (&vmx->vcpu,0 ); + msr =0xfee00000 |MSR_IA32_APICBASE_ENABLE ;if (vmx->vcpu.vcpu_id ==0 ) - vmx->vcpu.apic_base |=MSR_IA32_APICBASE_BSP ; + msr |=MSR_IA32_APICBASE_BSP ; +kvm_set_apic_base (&vmx->vcpu, msr);fx_init (&vmx->vcpu);
@@ -1860,7 +1862,7 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)return 1 ;case 8 :vcpu_load_rsp_rip (vcpu); - vcpu->regs[reg] = vcpu->cr8; + vcpu->regs[reg] =get_cr8 (vcpu);vcpu_put_rsp_rip (vcpu);skip_emulated_instruction (vcpu);return 1 ;
@@ -1957,8 +1959,8 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { kvm_run->if_flag = (vmcs_readl (GUEST_RFLAGS ) &X86_EFLAGS_IF ) !=0 ; - kvm_run->cr8 = vcpu->cr8; - kvm_run->apic_base = vcpu->apic_base; + kvm_run->cr8 =get_cr8 (vcpu); + kvm_run->apic_base =kvm_get_apic_base (vcpu); kvm_run->ready_for_interrupt_injection = (vcpu->interrupt_window_open && vcpu->irq_summary ==0 ); }
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 66/104 KVM: Emulate local APIC in kernel
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
Because lightweight exits (exits which don't involve userspace) are many times faster than heavyweight exits, it makes sense to emulate high usage devices in the kernel. The local APIC is one such device, especially for Windows and for SMP, so we add an APIC model to kvm.
It also allows in-kernel host-side drivers to inject interrupts without going through userspace.
[compile fix on i386 from Jindrich Makovicka]
--- drivers/kvm/Makefile | 2 +- drivers/kvm/irq.c | 53 ++- drivers/kvm/irq.h | 41 ++- drivers/kvm/kvm.h | 3 +- drivers/kvm/kvm_main.c | 52 +++- drivers/kvm/lapic.c | 933 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/kvm/svm.c | 6 + drivers/kvm/vmx.c | 6 + include/linux/kvm.h | 4 +- 9 files changed, 1067 insertions(+), 33 deletions(-) create mode 100644 drivers/kvm/lapic.c
drivers/kvm/Makefile +1 -1
@@ -2,7 +2,7 @@ # Makefile for Kernel-based Virtual Machine module # -kvm-objs := kvm_main.o mmu.o x86_emulate.o i8259.o irq.o +kvm-objs := kvm_main.o mmu.o x86_emulate.o i8259.o irq.o lapic.o obj-$(CONFIG_KVM) += kvm.o kvm-intel-objs = vmx.o obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
drivers/kvm/irq.c +36 -17
66 lines not on this page · raw message
drivers/kvm/irq.h +40 -1
51 lines not on this page · raw message
drivers/kvm/kvm.h +1 -2
@@ -324,6 +324,7 @@ struct kvm_vcpu {u64 pdptrs[4 ];/* pae */ u64 shadow_efer;u64 apic_base; +struct kvm_lapic *apic;/* kernel irqchip context */ u64 ia32_misc_enable_msr;struct kvm_mmu mmu;
@@ -569,8 +570,6 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr0);void set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr0);void set_cr8 (struct kvm_vcpu *vcpu,unsigned long cr0);unsigned long get_cr8 (struct kvm_vcpu *vcpu); -u64 kvm_get_apic_base (struct kvm_vcpu *vcpu); -void kvm_set_apic_base (struct kvm_vcpu *vcpu,u64 data);void lmsw (struct kvm_vcpu *vcpu,unsigned long msw);int kvm_get_msr_common (struct kvm_vcpu *vcpu,u32 msr,u64 *pdata);
drivers/kvm/kvm_main.c +42 -10
94 lines not on this page · raw message
drivers/kvm/lapic.c new file +933 -0
933 lines not on this page · raw message
drivers/kvm/svm.c +6 -0
@@ -573,6 +573,12 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)if (err) goto free_svm; +if (irqchip_in_kernel (kvm)) { + err =kvm_create_lapic (&svm->vcpu); +if (err <0 ) + goto free_svm; + } + page =alloc_page (GFP_KERNEL );if (!page) { err = -ENOMEM ;
drivers/kvm/vmx.c +6 -0
@@ -2390,6 +2390,12 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)if (err) goto free_vcpu; +if (irqchip_in_kernel (kvm)) { + err =kvm_create_lapic (&vmx->vcpu); +if (err <0 ) + goto free_vcpu; + } + vmx->guest_msrs =kmalloc (PAGE_SIZE ,GFP_KERNEL );if (!vmx->guest_msrs) { err = -ENOMEM ;
include/linux/kvm.h +2 -2
@@ -34,7 +34,7 @@ struct kvm_memory_alias {__u64 target_phys_addr; }; -/* for KVM_SET_IRQ_LEVEL */ +/* for KVM_IRQ_LINE */ struct kvm_irq_level {/* * ACPI gsi notion of irq.
@@ -297,7 +297,7 @@ struct kvm_signal_mask {#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)/* Device model IOC */ #define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) -#define KVM_IRQ_LINE _IO(KVMIO, 0x61) +#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)/* * ioctls for vcpu fds
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 67/104 KVM: In-kernel I/O APIC model
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
This allows in-kernel host-side device drivers to raise guest interrupts without going to userspace.
--- drivers/kvm/Makefile | 2 +- drivers/kvm/ioapic.c | 397 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/kvm/irq.c | 4 - drivers/kvm/irq.h | 50 ++++++ drivers/kvm/kvm.h | 1 + drivers/kvm/kvm_main.c | 15 ++- 6 files changed, 461 insertions(+), 8 deletions(-) create mode 100644 drivers/kvm/ioapic.c
drivers/kvm/Makefile +1 -1
@@ -2,7 +2,7 @@ # Makefile for Kernel-based Virtual Machine module # -kvm-objs := kvm_main.o mmu.o x86_emulate.o i8259.o irq.o lapic.o +kvm-objs := kvm_main.o mmu.o x86_emulate.o i8259.o irq.o lapic.o ioapic.o obj-$(CONFIG_KVM) += kvm.o kvm-intel-objs = vmx.o obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
drivers/kvm/ioapic.c new file +397 -0
397 lines not on this page · raw message
drivers/kvm/irq.c +0 -4
@@ -74,7 +74,3 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)smp_call_function_single (ipi_pcpu, vcpu_kick_intr, vcpu,0 ,0 ); } -void kvm_ioapic_update_eoi (struct kvm *kvm,int vector) -{ -/* TODO: for kernel IOAPIC */ -}
drivers/kvm/irq.h +50 -0
64 lines not on this page · raw message
drivers/kvm/kvm.h +1 -0
@@ -410,6 +410,7 @@ struct kvm {struct kvm_io_bus mmio_bus;struct kvm_io_bus pio_bus;struct kvm_pic *vpic; +struct kvm_ioapic *vioapic; };static inline struct kvm_pic *pic_irqchip (struct kvm *kvm)
drivers/kvm/kvm_main.c +12 -3
@@ -381,6 +381,7 @@ static void kvm_destroy_vm(struct kvm *kvm)kvm_io_bus_destroy (&kvm->pio_bus);kvm_io_bus_destroy (&kvm->mmio_bus);kfree (kvm->vpic); +kfree (kvm->vioapic);kvm_free_vcpus (kvm);kvm_free_physmem (kvm);kfree (kvm);
@@ -2771,8 +2772,14 @@ static long kvm_vm_ioctl(struct file *filp,case KVM_CREATE_IRQCHIP : r = -ENOMEM ; kvm->vpic =kvm_create_pic (kvm); -if (kvm->vpic) - r =0 ; +if (kvm->vpic) { + r =kvm_ioapic_init (kvm); +if (r) { +kfree (kvm->vpic); + kvm->vpic =NULL ; + goto out; + } + }else goto out;break ;
@@ -2787,7 +2794,9 @@ static long kvm_vm_ioctl(struct file *filp,kvm_pic_set_irq (pic_irqchip (kvm), irq_event.irq, irq_event.level); -/* TODO: IOAPIC */ +kvm_ioapic_set_irq (kvm->vioapic, + irq_event.irq, + irq_event.level); r =0 ; }break ;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 68/104 KVM: Emulate hlt in the kernel
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
By sleeping in the kernel when hlt is executed, we simplify the in-kernel guest interrupt path considerably.
--- drivers/kvm/i8259.c | 3 +++ drivers/kvm/irq.c | 4 ++++ drivers/kvm/kvm.h | 2 ++ drivers/kvm/kvm_main.c | 41 +++++++++++++++++++++++++++++++++++------ drivers/kvm/svm.c | 9 ++++++--- drivers/kvm/vmx.c | 8 ++++++-- include/linux/kvm.h | 1 + 7 files changed, 57 insertions(+), 11 deletions(-)
drivers/kvm/i8259.c +3 -0
@@ -413,8 +413,11 @@ static void picdev_read(struct kvm_io_device *this,static void pic_irq_request (void *opaque,int level) {struct kvm *kvm = opaque; +struct kvm_vcpu *vcpu = kvm->vcpus[0 ];pic_irqchip (kvm)->output = level; +if (vcpu) +kvm_vcpu_kick (vcpu); }struct kvm_pic *kvm_create_pic (struct kvm *kvm)
drivers/kvm/irq.c +4 -0
@@ -70,6 +70,10 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu) {int ipi_pcpu = vcpu->cpu; +if (waitqueue_active (&vcpu->wq)) { +wake_up_interruptible (&vcpu->wq); + ++vcpu->stat.halt_wakeup; + }if (vcpu->guest_mode)smp_call_function_single (ipi_pcpu, vcpu_kick_intr, vcpu,0 ,0 ); }
drivers/kvm/kvm.h +2 -0
@@ -231,6 +231,7 @@ struct kvm_stat {u32 signal_exits;u32 irq_window_exits;u32 halt_exits; +u32 halt_wakeup;u32 request_irq_exits;u32 irq_exits;u32 light_exits;
@@ -353,6 +354,7 @@ struct kvm_vcpu {gva_t mmio_fault_cr2;struct kvm_pio_request pio;void *pio_data; +wait_queue_head_t wq;int sigset_active;sigset_t sigset;
drivers/kvm/kvm_main.c +35 -6
68 lines not on this page · raw message
drivers/kvm/svm.c +6 -3
@@ -1398,9 +1398,12 @@ static void do_interrupt_requests(struct vcpu_svm *svm,static void post_kvm_run_save (struct vcpu_svm *svm,struct kvm_run *kvm_run) { - kvm_run->ready_for_interrupt_injection - = (svm->vcpu.interrupt_window_open && - svm->vcpu.irq_summary ==0 ); +if (irqchip_in_kernel (svm->vcpu.kvm)) + kvm_run->ready_for_interrupt_injection =1 ; +else + kvm_run->ready_for_interrupt_injection = + (svm->vcpu.interrupt_window_open && + svm->vcpu.irq_summary ==0 ); kvm_run->if_flag = (svm->vmcb->save.rflags &X86_EFLAGS_IF ) !=0 ; kvm_run->cr8 =get_cr8 (&svm->vcpu); kvm_run->apic_base =kvm_get_apic_base (&svm->vcpu);
drivers/kvm/vmx.c +6 -2
@@ -1961,8 +1961,12 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu, kvm_run->if_flag = (vmcs_readl (GUEST_RFLAGS ) &X86_EFLAGS_IF ) !=0 ; kvm_run->cr8 =get_cr8 (vcpu); kvm_run->apic_base =kvm_get_apic_base (vcpu); - kvm_run->ready_for_interrupt_injection = (vcpu->interrupt_window_open && - vcpu->irq_summary ==0 ); +if (irqchip_in_kernel (vcpu->kvm)) + kvm_run->ready_for_interrupt_injection =1 ; +else + kvm_run->ready_for_interrupt_injection = + (vcpu->interrupt_window_open && + vcpu->irq_summary ==0 ); } static int handle_interrupt_window(struct kvm_vcpu *vcpu,
include/linux/kvm.h +1 -0
@@ -283,6 +283,7 @@ struct kvm_signal_mask {* Extension capability list. */ #define KVM_CAP_IRQCHIP 0 +#define KVM_CAP_HLT 1/* * ioctls for VM fds
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 69/104 KVM: Protect in-kernel pio using kvm->lock
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
pio operation and IRQ_LINE kvm_vm_ioctl is not kvm->lock protected. Add lock to same with IOAPIC MMIO operations.
--- drivers/kvm/kvm_main.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +6 -0
@@ -1790,6 +1790,7 @@ static void kernel_pio(struct kvm_io_device *pio_dev, {/* TODO: String I/O for in kernel device */ +mutex_lock (&vcpu->kvm->lock);if (vcpu->pio.in) kvm_iodevice_read(pio_dev, vcpu->pio.port, vcpu->pio.size,
@@ -1798,6 +1799,7 @@ static void kernel_pio(struct kvm_io_device *pio_dev,kvm_iodevice_write (pio_dev, vcpu->pio.port, vcpu->pio.size, pd); +mutex_unlock (&vcpu->kvm->lock); } static void pio_string_write(struct kvm_io_device *pio_dev,
@@ -1807,12 +1809,14 @@ static void pio_string_write(struct kvm_io_device *pio_dev,void *pd = vcpu->pio_data;int i; +mutex_lock (&vcpu->kvm->lock);for (i =0 ; i < io->cur_count; i++) {kvm_iodevice_write (pio_dev, io->port, io->size, pd); pd += io->size; } +mutex_unlock (&vcpu->kvm->lock); } int kvm_emulate_pio (struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
@@ -2818,6 +2822,7 @@ static long kvm_vm_ioctl(struct file *filp,if (copy_from_user (&irq_event, argp,sizeof irq_event)) goto out;if (irqchip_in_kernel (kvm)) { +mutex_lock (&kvm->lock);if (irq_event.irq <16 ) kvm_pic_set_irq(pic_irqchip(kvm), irq_event.irq,
@@ -2825,6 +2830,7 @@ static long kvm_vm_ioctl(struct file *filp,kvm_ioapic_set_irq (kvm->vioapic, irq_event.irq, irq_event.level); +mutex_unlock (&kvm->lock); r =0 ; }break ;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 70/104 KVM: Add get/set irqchip ioctls for in-kernel PIC live migration support
In reply to Avi KivityFrom: He, Qing <[email protected]>
This patch adds two new ioctls to dump and write kernel irqchips for save/restore and live migration. PIC s/r and l/m is implemented in this patch.
--- drivers/kvm/i8259.c | 5 +++ drivers/kvm/irq.h | 1 + drivers/kvm/kvm_main.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/kvm.h | 36 +++++++++++++++++++++ 4 files changed, 124 insertions(+), 0 deletions(-)
drivers/kvm/i8259.c +5 -0
@@ -119,6 +119,11 @@ static void pic_update_irq(struct kvm_pic *s) s->irq_request (s->irq_request_opaque,0 ); } +void kvm_pic_update_irq (struct kvm_pic *s) +{ +pic_update_irq (s); +} +void kvm_pic_set_irq (void *opaque,int irq,int level) {struct kvm_pic *s = opaque;
drivers/kvm/irq.h +1 -0
@@ -59,6 +59,7 @@ void kvm_pic_set_irq(void *opaque, int irq, int level);int kvm_pic_read_irq (struct kvm_pic *s);int kvm_cpu_get_interrupt (struct kvm_vcpu *v);int kvm_cpu_has_interrupt (struct kvm_vcpu *v); +void kvm_pic_update_irq (struct kvm_pic *s);#define IOAPIC_NUM_PINS 24#define IOAPIC_VERSION_ID 0x11/* IOAPIC version */
drivers/kvm/kvm_main.c +82 -0
94 lines not on this page · raw message
include/linux/kvm.h +36 -0
@@ -45,6 +45,40 @@ struct kvm_irq_level {__u32 level; }; +/* for KVM_GET_IRQCHIP / KVM_SET_IRQCHIP */ +struct kvm_pic_state { +__u8 last_irr;/* edge detection */ +__u8 irr;/* interrupt request register */ +__u8 imr;/* interrupt mask register */ +__u8 isr;/* interrupt service register */ +__u8 priority_add;/* highest irq priority */ +__u8 irq_base; +__u8 read_reg_select; +__u8 poll; +__u8 special_mask; +__u8 init_state; +__u8 auto_eoi; +__u8 rotate_on_auto_eoi; +__u8 special_fully_nested_mode; +__u8 init4;/* true if 4 byte init */ +__u8 elcr;/* PIIX edge/trigger selection */ +__u8 elcr_mask; +}; + +enum kvm_irqchip_id { +KVM_IRQCHIP_PIC_MASTER =0 , +KVM_IRQCHIP_PIC_SLAVE =1 , +}; + +struct kvm_irqchip { +__u32 chip_id; +__u32 pad; +union { +char dummy[512 ];/* reserving space */ +struct kvm_pic_state pic; + } chip; +}; +enum kvm_exit_reason {KVM_EXIT_UNKNOWN =0 ,KVM_EXIT_EXCEPTION =1 ,
@@ -299,6 +333,8 @@ struct kvm_signal_mask {/* Device model IOC */ #define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level) +#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip) +#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)/* * ioctls for vcpu fds
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 71/104 KVM: Bypass irq_pending get/set when using in kernel irqchip
In reply to Avi KivityFrom: He, Qing <[email protected]>
vcpu->irq_pending is saved in get/set_sreg IOCTL, but when in-kernel local APIC is used, doing this may occasionally overwrite vcpu->apic to an invalid value, as in the vm restore path.
--- drivers/kvm/kvm_main.c | 22 ++++++++++++++-------- 1 files changed, 14 insertions(+), 8 deletions(-)
drivers/kvm/kvm_main.c +14 -8
@@ -2145,8 +2145,12 @@ static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, sregs->efer = vcpu->shadow_efer; sregs->apic_base =kvm_get_apic_base (vcpu); -memcpy (sregs->interrupt_bitmap, vcpu->irq_pending, -sizeof sregs->interrupt_bitmap); +if (irqchip_in_kernel (vcpu->kvm)) +memset (sregs->interrupt_bitmap,0 , +sizeof sregs->interrupt_bitmap); +else +memcpy (sregs->interrupt_bitmap, vcpu->irq_pending, +sizeof sregs->interrupt_bitmap);vcpu_put (vcpu);
@@ -2200,12 +2204,14 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,if (mmu_reset_needed)kvm_mmu_reset_context (vcpu); -memcpy (vcpu->irq_pending, sregs->interrupt_bitmap, -sizeof vcpu->irq_pending); - vcpu->irq_summary =0 ; -for (i =0 ; i <ARRAY_SIZE (vcpu->irq_pending); ++i) -if (vcpu->irq_pending[i]) -__set_bit (i, &vcpu->irq_summary); +if (!irqchip_in_kernel (vcpu->kvm)) { +memcpy (vcpu->irq_pending, sregs->interrupt_bitmap, +sizeof vcpu->irq_pending); + vcpu->irq_summary =0 ; +for (i =0 ; i <ARRAY_SIZE (vcpu->irq_pending); ++i) +if (vcpu->irq_pending[i]) +__set_bit (i, &vcpu->irq_summary); + }set_segment (vcpu, &sregs->cs,VCPU_SREG_CS );set_segment (vcpu, &sregs->ds,VCPU_SREG_DS );
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 72/104 KVM: in-kernel IOAPIC save and restore support
In reply to Avi KivityFrom: He, Qing <[email protected]>
This patch adds support for in-kernel ioapic save and restore (to and from userspace). It uses the same get/set_irqchip ioctl as in-kernel PIC.
--- drivers/kvm/irq.h | 9 +++++---- drivers/kvm/kvm.h | 5 +++++ drivers/kvm/kvm_main.c | 10 ++++++++++ include/linux/kvm.h | 29 ++++++++++++++++++++++++++++- 4 files changed, 48 insertions(+), 5 deletions(-)
drivers/kvm/irq.h +5 -4
@@ -61,7 +61,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v);int kvm_cpu_has_interrupt (struct kvm_vcpu *v);void kvm_pic_update_irq (struct kvm_pic *s); -#define IOAPIC_NUM_PINS 24 +#define IOAPIC_NUM_PINS KVM_IOAPIC_NUM_PINS#define IOAPIC_VERSION_ID 0x11/* IOAPIC version */ #define IOAPIC_EDGE_TRIG 0#define IOAPIC_LEVEL_TRIG 1
@@ -80,12 +80,11 @@ void kvm_pic_update_irq(struct kvm_pic *s);#define IOAPIC_REG_ARB_ID 0x02/* x86 IOAPIC only */ struct kvm_ioapic { - struct kvm_io_device dev; - unsigned long base_address; - struct kvm *kvm; + u64 base_address; u32 ioregsel; u32 id; u32 irr; + u32 pad; union ioapic_redir_entry { u64 bits; struct {
@@ -102,6 +101,8 @@ struct kvm_ioapic {u8 dest_id; } fields; } redirtbl[IOAPIC_NUM_PINS ]; +struct kvm_io_device dev; +struct kvm *kvm; };struct kvm_lapic {
drivers/kvm/kvm.h +5 -0
@@ -420,6 +420,11 @@ static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)return kvm->vpic; } +static inline struct kvm_ioapic *ioapic_irqchip (struct kvm *kvm) +{ +return kvm->vioapic; +} +static inline int irqchip_in_kernel (struct kvm *kvm) {return pic_irqchip (kvm) !=0 ;
drivers/kvm/kvm_main.c +10 -0
@@ -913,6 +913,11 @@ static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, struct kvm_irqchip *chip) &pic_irqchip (kvm)->pics[1 ], sizeof(struct kvm_pic_state));break ; +case KVM_IRQCHIP_IOAPIC : +memcpy (&chip->chip.ioapic, +ioapic_irqchip (kvm), +sizeof (struct kvm_ioapic_state )); +break ;default : r = -EINVAL ;break ;
@@ -936,6 +941,11 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip) &chip->chip.pic, sizeof(struct kvm_pic_state));break ; +case KVM_IRQCHIP_IOAPIC : +memcpy (ioapic_irqchip (kvm), + &chip->chip.ioapic, +sizeof (struct kvm_ioapic_state )); +break ;default : r = -EINVAL ;break ;
include/linux/kvm.h +28 -1
@@ -45,7 +45,7 @@ struct kvm_irq_level {__u32 level; }; -/* for KVM_GET_IRQCHIP / KVM_SET_IRQCHIP */ +/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */ struct kvm_pic_state {__u8 last_irr;/* edge detection */ __u8 irr;/* interrupt request register */
@@ -65,9 +65,35 @@ struct kvm_pic_state {__u8 elcr_mask; }; +#define KVM_IOAPIC_NUM_PINS 24 +struct kvm_ioapic_state { +__u64 base_address; +__u32 ioregsel; +__u32 id; +__u32 irr; +__u32 pad; +union { +__u64 bits; +struct { +__u8 vector; +__u8 delivery_mode:3 ; +__u8 dest_mode:1 ; +__u8 delivery_status:1 ; +__u8 polarity:1 ; +__u8 remote_irr:1 ; +__u8 trig_mode:1 ; +__u8 mask:1 ; +__u8 reserve:7 ; +__u8 reserved[4 ]; +__u8 dest_id; + } fields; + } redirtbl[KVM_IOAPIC_NUM_PINS ]; +}; +enum kvm_irqchip_id {KVM_IRQCHIP_PIC_MASTER =0 ,KVM_IRQCHIP_PIC_SLAVE =1 , +KVM_IRQCHIP_IOAPIC =2 , };struct kvm_irqchip {
@@ -76,6 +102,7 @@ struct kvm_irqchip {union {char dummy[512 ];/* reserving space */ struct kvm_pic_state pic; +struct kvm_ioapic_state ioapic; } chip; };
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 73/104 KVM: in-kernel LAPIC save and restore support
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
This patch adds a new vcpu-based IOCTL to save and restore the local apic registers for a single vcpu. The kernel only copies the apic page as a whole, extraction of registers is left to userspace side. On restore, the APIC timer is restarted from the initial count, this introduces a little delay, but works fine.
--- drivers/kvm/irq.h | 1 + drivers/kvm/kvm_main.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/kvm/lapic.c | 13 +++++++++++++ include/linux/kvm.h | 8 ++++++++ 4 files changed, 68 insertions(+), 0 deletions(-)
drivers/kvm/irq.h +1 -0
@@ -149,6 +149,7 @@ int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);void kvm_ioapic_update_eoi (struct kvm *kvm,int vector);int kvm_apic_match_logical_addr (struct kvm_lapic *apic,u8 mda);int kvm_apic_set_irq (struct kvm_lapic *apic,u8 vec,u8 trig); +void kvm_apic_post_state_restore (struct kvm_vcpu *vcpu);int kvm_ioapic_init (struct kvm *kvm);void kvm_ioapic_set_irq (struct kvm_ioapic *ioapic,int irq,int level);
drivers/kvm/kvm_main.c +46 -0
58 lines not on this page · raw message
drivers/kvm/lapic.c +13 -0
@@ -931,3 +931,16 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)apic_clear_irr (vector, apic);return vector; } + +void kvm_apic_post_state_restore (struct kvm_vcpu *vcpu) +{ +struct kvm_lapic *apic = vcpu->apic; + + apic->base_address = vcpu->apic_base & +MSR_IA32_APICBASE_BASE ; +apic_set_reg (apic,APIC_LVR ,APIC_VERSION ); +apic_update_ppr (apic); +hrtimer_cancel (&apic->timer.dev); +update_divide_count (apic); +start_apic_timer (apic); +}
include/linux/kvm.h +8 -0
@@ -208,6 +208,12 @@ struct kvm_fpu {__u32 pad2; }; +/* for KVM_GET_LAPIC and KVM_SET_LAPIC */ +#define KVM_APIC_REG_SIZE 0x400 +struct kvm_lapic_state { +char regs[KVM_APIC_REG_SIZE ]; +}; +struct kvm_segment {__u64 base;__u32 limit;
@@ -380,5 +386,7 @@ struct kvm_signal_mask {#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask)#define KVM_GET_FPU _IOR(KVMIO, 0x8c, struct kvm_fpu)#define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu) +#define KVM_GET_LAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state) +#define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state)#endif
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 74/104 KVM: pending irq save/restore
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
Add in kernel irqchip save/restore support for pending vectors.
--- drivers/kvm/kvm.h | 2 ++ drivers/kvm/kvm_main.c | 22 +++++++++++++++++++--- drivers/kvm/svm.c | 19 +++++++++++++++++++ drivers/kvm/vmx.c | 16 ++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-)
drivers/kvm/kvm.h +2 -0
@@ -490,6 +490,8 @@ struct kvm_arch_ops {void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);void (*patch_hypercall)(struct kvm_vcpu *vcpu,unsigned char *hypercall_addr); +int (*get_irq)(struct kvm_vcpu *vcpu); +void (*set_irq)(struct kvm_vcpu *vcpu,int vec); };extern struct kvm_arch_ops *kvm_arch_ops;
drivers/kvm/kvm_main.c +19 -3
@@ -2126,6 +2126,7 @@ static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) {struct descriptor_table dt; +int pending_vec;vcpu_load (vcpu);
@@ -2155,10 +2156,15 @@ static int kvm_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, sregs->efer = vcpu->shadow_efer; sregs->apic_base =kvm_get_apic_base (vcpu); -if (irqchip_in_kernel (vcpu->kvm)) +if (irqchip_in_kernel (vcpu->kvm)) {memset (sregs->interrupt_bitmap,0 ,sizeof sregs->interrupt_bitmap); -else + pending_vec = kvm_arch_ops->get_irq (vcpu); +if (pending_vec >=0 ) { +set_bit (pending_vec, sregs->interrupt_bitmap); +printk ("pending irq in kernel %d\n" ,pending_vec); + } + }else memcpy (sregs->interrupt_bitmap, vcpu->irq_pending,sizeof sregs->interrupt_bitmap);
@@ -2177,7 +2183,7 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) {int mmu_reset_needed =0 ; -int i; +int i, pending_vec, max_bits;struct descriptor_table dt;vcpu_load (vcpu);
@@ -2221,6 +2227,16 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,for (i =0 ; i <ARRAY_SIZE (vcpu->irq_pending); ++i)if (vcpu->irq_pending[i])__set_bit (i, &vcpu->irq_summary); + }else { + max_bits = (sizeof sregs->interrupt_bitmap) <<3 ; + pending_vec =find_first_bit ( + (const unsigned long *)sregs->interrupt_bitmap, + max_bits); +/* Only pending external irq is handled here */ +if (pending_vec < max_bits) { + kvm_arch_ops->set_irq (vcpu, pending_vec); +printk ("Set back pending irq %d\n" , pending_vec); + } }set_segment (vcpu, &sregs->cs,VCPU_SREG_CS );
drivers/kvm/svm.c +19 -0
@@ -843,6 +843,16 @@ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)return -EOPNOTSUPP ; } +static int svm_get_irq (struct kvm_vcpu *vcpu) +{ +struct vcpu_svm *svm =to_svm (vcpu); +u32 exit_int_info = svm->vmcb->control.exit_int_info; + +if (is_external_interrupt (exit_int_info)) +return exit_int_info &SVM_EVTINJ_VEC_MASK ; +return -1 ; +} +static void load_host_msrs (struct kvm_vcpu *vcpu) {#ifdef CONFIG_X86_64
@@ -1310,6 +1320,13 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq) ((/*control->int_vector >> 4*/ 0xf ) <<V_INTR_PRIO_SHIFT ); } +static void svm_set_irq (struct kvm_vcpu *vcpu,int irq) +{ +struct vcpu_svm *svm =to_svm (vcpu); + +svm_inject_irq (svm, irq); +} +static void svm_intr_assist (struct vcpu_svm *svm) {struct vmcb *vmcb = svm->vmcb;
@@ -1783,6 +1800,8 @@ static struct kvm_arch_ops svm_arch_ops = { .run = svm_vcpu_run, .skip_emulated_instruction = skip_emulated_instruction, .patch_hypercall = svm_patch_hypercall, + .get_irq = svm_get_irq, + .set_irq = svm_set_irq, };static int __init svm_init (void )
drivers/kvm/vmx.c +16 -0
@@ -790,6 +790,20 @@ static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)return 0 ; } +static int vmx_get_irq (struct kvm_vcpu *vcpu) +{ +u32 idtv_info_field; + + idtv_info_field =vmcs_read32 (IDT_VECTORING_INFO_FIELD ); +if (idtv_info_field &INTR_INFO_VALID_MASK ) { +if (is_external_interrupt (idtv_info_field)) +return idtv_info_field &VECTORING_INFO_VECTOR_MASK ; +else +printk ("pending exception: not handled yet\n" ); + } +return -1 ; +} +static __init int cpu_has_kvm_support (void ) {unsigned long ecx =cpuid_ecx (1 );
@@ -2500,6 +2514,8 @@ static struct kvm_arch_ops vmx_arch_ops = { .run = vmx_vcpu_run, .skip_emulated_instruction = skip_emulated_instruction, .patch_hypercall = vmx_patch_hypercall, + .get_irq = vmx_get_irq, + .set_irq = vmx_inject_irq, };static int __init vmx_init (void )
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 75/104 KVM: VMX: Use shadow TPR/cr8 for 64-bits guests
In reply to Avi KivityFrom: Yang, Sheng <[email protected]>
This patch enables TPR shadow of VMX on CR8 access. 64bit Windows using CR8 access TPR frequently. The TPR shadow can improve the performance of access TPR by not causing vmexit.
--- drivers/kvm/irq.h | 2 + drivers/kvm/lapic.c | 17 +++++++++++++ drivers/kvm/vmx.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++--- drivers/kvm/vmx.h | 1 + 4 files changed, 81 insertions(+), 4 deletions(-)
drivers/kvm/irq.h +2 -0
@@ -152,5 +152,7 @@ int kvm_apic_set_irq(struct kvm_lapic *apic, u8 vec, u8 trig);void kvm_apic_post_state_restore (struct kvm_vcpu *vcpu);int kvm_ioapic_init (struct kvm *kvm);void kvm_ioapic_set_irq (struct kvm_ioapic *ioapic,int irq,int level); +int kvm_lapic_enabled (struct kvm_vcpu *vcpu); +int kvm_lapic_find_highest_irr (struct kvm_vcpu *vcpu);#endif
drivers/kvm/lapic.c +17 -0
@@ -170,6 +170,19 @@ static inline int apic_find_highest_irr(struct kvm_lapic *apic)return result; } +int kvm_lapic_find_highest_irr (struct kvm_vcpu *vcpu) +{ +struct kvm_lapic *apic = (struct kvm_lapic *)vcpu->apic; +int highest_irr; + +if (!apic) +return 0 ; + highest_irr =apic_find_highest_irr (apic); + +return highest_irr; +} +EXPORT_SYMBOL_GPL (kvm_lapic_find_highest_irr); +int kvm_apic_set_irq (struct kvm_lapic *apic,u8 vec,u8 trig) {if (!apic_test_and_set_irr (vec, apic)) {
@@ -483,6 +496,7 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)break ;default : +apic_update_ppr (apic); val =apic_get_reg (apic, offset);break ; }
@@ -723,6 +737,7 @@ u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)return (tpr &0xf0 ) >>4 ; } +EXPORT_SYMBOL_GPL (kvm_lapic_get_cr8);void kvm_lapic_set_base (struct kvm_vcpu *vcpu,u64 value) {
@@ -809,6 +824,7 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu)return ret; } +EXPORT_SYMBOL_GPL (kvm_lapic_enabled);/* *----------------------------------------------------------------------
@@ -911,6 +927,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)if (!apic || !apic_enabled (apic))return -1 ; +apic_update_ppr (apic); highest_irr =apic_find_highest_irr (apic);if ((highest_irr ==-1 ) || ((highest_irr &0xF0 ) <=apic_get_reg (apic,APIC_PROCPRI )))
drivers/kvm/vmx.c +61 -4
123 lines not on this page · raw message
drivers/kvm/vmx.h +1 -0
@@ -213,6 +213,7 @@ enum vmcs_field {#define EXIT_REASON_MSR_READ 31#define EXIT_REASON_MSR_WRITE 32#define EXIT_REASON_MWAIT_INSTRUCTION 36 +#define EXIT_REASON_TPR_BELOW_THRESHOLD 43/* * Interruption-information format
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 76/104 KVM: Keep track of missed timer irq injections
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
APIC timer IRQ is set every time when a certain period expires at host time, but the guest may be descheduled at that time and thus the irq be overwritten by later fire. This patch keep track of firing irq numbers and decrease only when the IRQ is injected to guest or buffered in APIC.
--- drivers/kvm/irq.c | 13 ++++++++++ drivers/kvm/irq.h | 4 +++ drivers/kvm/kvm_main.c | 2 + drivers/kvm/lapic.c | 58 +++++++++++++++++++++++++++++++---------------- drivers/kvm/svm.c | 7 ++++- drivers/kvm/vmx.c | 10 +++++-- 6 files changed, 69 insertions(+), 25 deletions(-)
drivers/kvm/irq.c +13 -0
@@ -78,3 +78,16 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)smp_call_function_single (ipi_pcpu, vcpu_kick_intr, vcpu,0 ,0 ); } +void kvm_inject_pending_timer_irqs (struct kvm_vcpu *vcpu) +{ +kvm_inject_apic_timer_irqs (vcpu); +/* TODO: PIT, RTC etc. */ +} +EXPORT_SYMBOL_GPL (kvm_inject_pending_timer_irqs); + +void kvm_timer_intr_post (struct kvm_vcpu *vcpu,int vec) +{ +kvm_apic_timer_intr_post (vcpu, vec); +/* TODO: PIT, RTC etc. */ +} +EXPORT_SYMBOL_GPL (kvm_timer_intr_post);
drivers/kvm/irq.h +4 -0
@@ -154,5 +154,9 @@ int kvm_ioapic_init(struct kvm *kvm);void kvm_ioapic_set_irq (struct kvm_ioapic *ioapic,int irq,int level);int kvm_lapic_enabled (struct kvm_vcpu *vcpu);int kvm_lapic_find_highest_irr (struct kvm_vcpu *vcpu); +void kvm_apic_timer_intr_post (struct kvm_vcpu *vcpu,int vec); +void kvm_timer_intr_post (struct kvm_vcpu *vcpu,int vec); +void kvm_inject_pending_timer_irqs (struct kvm_vcpu *vcpu); +void kvm_inject_apic_timer_irqs (struct kvm_vcpu *vcpu);#endif
drivers/kvm/kvm_main.c +2 -0
@@ -283,6 +283,8 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_init);void kvm_vcpu_uninit (struct kvm_vcpu *vcpu) {kvm_mmu_destroy (vcpu); +if (vcpu->apic) +hrtimer_cancel (&vcpu->apic->timer.dev);kvm_free_apic (vcpu->apic);free_page ((unsigned long )vcpu->pio_data);free_page ((unsigned long )vcpu->run);
drivers/kvm/lapic.c +38 -20
102 lines not on this page · raw message
drivers/kvm/svm.c +5 -2
@@ -1331,7 +1331,9 @@ static void svm_intr_assist(struct vcpu_svm *svm) {struct vmcb *vmcb = svm->vmcb;int intr_vector =-1 ; +struct kvm_vcpu *vcpu = &svm->vcpu; +kvm_inject_pending_timer_irqs (vcpu);if ((vmcb->control.exit_int_info &SVM_EVTINJ_VALID ) && ((vmcb->control.exit_int_info &SVM_EVTINJ_TYPE_MASK ) ==0 )) { intr_vector = vmcb->control.exit_int_info &
@@ -1344,7 +1346,7 @@ static void svm_intr_assist(struct vcpu_svm *svm)if (vmcb->control.int_ctl &V_IRQ_MASK )return ; -if (!kvm_cpu_has_interrupt (&svm->vcpu)) +if (!kvm_cpu_has_interrupt (vcpu))return ; if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
@@ -1356,8 +1358,9 @@ static void svm_intr_assist(struct vcpu_svm *svm)return ; }/* Okay, we can deliver the interrupt: grab it and update PIC state. */ - intr_vector =kvm_cpu_get_interrupt (&svm->vcpu); + intr_vector =kvm_cpu_get_interrupt (vcpu);svm_inject_irq (svm, intr_vector); +kvm_timer_intr_post (vcpu, intr_vector); }static void kvm_reput_irq (struct vcpu_svm *svm)
drivers/kvm/vmx.c +7 -3
@@ -2151,7 +2151,9 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) {u32 idtv_info_field, intr_info_field;int has_ext_irq, interrupt_window_open; +int vector; +kvm_inject_pending_timer_irqs (vcpu);update_tpr_threshold (vcpu); has_ext_irq =kvm_cpu_has_interrupt (vcpu);
@@ -2183,9 +2185,11 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) interrupt_window_open = ((vmcs_readl (GUEST_RFLAGS ) &X86_EFLAGS_IF ) && (vmcs_read32 (GUEST_INTERRUPTIBILITY_INFO ) &3 ) ==0 ); -if (interrupt_window_open) -vmx_inject_irq (vcpu,kvm_cpu_get_interrupt (vcpu)); -else +if (interrupt_window_open) { + vector =kvm_cpu_get_interrupt (vcpu); +vmx_inject_irq (vcpu, vector); +kvm_timer_intr_post (vcpu, vector); + }else enable_irq_window (vcpu); }
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 77/104 KVM: Migrate lapic hrtimer when vcpu moves to another cpu
In reply to Avi KivityFrom: Eddie Dong <[email protected]>
This reduces overhead by accessing cachelines from the wrong node, as well as simplifying locking.
[Qing: fix for inactive or expired one-shot timer]
--- drivers/kvm/irq.h | 1 + drivers/kvm/lapic.c | 14 ++++++++++++++ drivers/kvm/svm.c | 1 + drivers/kvm/vmx.c | 4 +++- 4 files changed, 19 insertions(+), 1 deletions(-)
drivers/kvm/irq.h +1 -0
@@ -158,5 +158,6 @@ void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec);void kvm_timer_intr_post (struct kvm_vcpu *vcpu,int vec);void kvm_inject_pending_timer_irqs (struct kvm_vcpu *vcpu);void kvm_inject_apic_timer_irqs (struct kvm_vcpu *vcpu); +void kvm_migrate_apic_timer (struct kvm_vcpu *vcpu);#endif
drivers/kvm/lapic.c +14 -0
@@ -979,3 +979,17 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)update_divide_count (apic);start_apic_timer (apic); } + +void kvm_migrate_apic_timer (struct kvm_vcpu *vcpu) +{ +struct kvm_lapic *apic = vcpu->apic; +struct hrtimer *timer; + +if (!apic) +return ; + + timer = &apic->timer.dev; +if (hrtimer_cancel (timer)) +hrtimer_start (timer, timer->expires,HRTIMER_MODE_ABS ); +} +EXPORT_SYMBOL_GPL (kvm_migrate_apic_timer);
drivers/kvm/svm.c +1 -0
@@ -633,6 +633,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) delta = vcpu->host_tsc - tsc_this; svm->vmcb->control.tsc_offset += delta; vcpu->cpu = cpu; +kvm_migrate_apic_timer (vcpu); }for (i =0 ; i <NR_HOST_SAVE_USER_MSRS ; i++)
drivers/kvm/vmx.c +3 -1
@@ -441,8 +441,10 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)u64 phys_addr =__pa (vmx->vmcs);u64 tsc_this, delta; -if (vcpu->cpu != cpu) +if (vcpu->cpu != cpu) {vcpu_clear (vmx); +kvm_migrate_apic_timer (vcpu); + }if (per_cpu (current_vmcs, cpu) != vmx->vmcs) {u8 error;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 78/104 KVM: disable tpr/cr8 sync when in-kernel APIC is used
In reply to Avi KivityFrom: He, Qing <[email protected]>
--- drivers/kvm/kvm_main.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/kvm/kvm_main.c +2 -1
@@ -2005,7 +2005,8 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)sigprocmask (SIG_SETMASK , &vcpu->sigset, &sigsaved);/* re-sync apic's tpr */ -set_cr8 (vcpu, kvm_run->cr8); +if (!irqchip_in_kernel (vcpu->kvm)) +set_cr8 (vcpu, kvm_run->cr8);if (vcpu->pio.cur_count) { r =complete_pio (vcpu);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 79/104 KVM: deliver PIC interrupt only to vcpu0
In reply to Avi KivityFrom: Qing He <[email protected]>
This patch changes the PIC interrupts delivery. Now it is only delivered to vcpu0 when either condition is met (on vcpu0):
1. local APIC is hardware disabled
2. LVT0 is unmasked and configured to delivery mode ExtInt
It fixes the 2x faster wall clock on x86_64 and SMP i386 Linux guests
--- drivers/kvm/irq.c | 15 ++++++++++----- drivers/kvm/irq.h | 1 + drivers/kvm/lapic.c | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-)
drivers/kvm/irq.c +10 -5
@@ -33,8 +33,11 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)struct kvm_pic *s;if (kvm_apic_has_interrupt (v) ==-1 ) {/* LAPIC */ - s =pic_irqchip (v->kvm);/* PIC */ -return s->output; +if (kvm_apic_accept_pic_intr (v)) { + s =pic_irqchip (v->kvm);/* PIC */ +return s->output; + }else +return 0 ; }return 1 ; }
@@ -50,9 +53,11 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) vector =kvm_get_apic_interrupt (v);/* APIC */ if (vector ==-1 ) { - s =pic_irqchip (v->kvm); - s->output =0 ;/* PIC */ - vector =kvm_pic_read_irq (s); +if (kvm_apic_accept_pic_intr (v)) { + s =pic_irqchip (v->kvm); + s->output =0 ;/* PIC */ + vector =kvm_pic_read_irq (s); + } }return vector; }
drivers/kvm/irq.h +1 -0
@@ -135,6 +135,7 @@ do { \void kvm_vcpu_kick (struct kvm_vcpu *vcpu);int kvm_apic_has_interrupt (struct kvm_vcpu *vcpu); +int kvm_apic_accept_pic_intr (struct kvm_vcpu *vcpu);int kvm_get_apic_interrupt (struct kvm_vcpu *vcpu);int kvm_create_lapic (struct kvm_vcpu *vcpu);void kvm_free_apic (struct kvm_lapic *apic);
drivers/kvm/lapic.c +17 -0
@@ -788,6 +788,8 @@ static void lapic_reset(struct kvm_vcpu *vcpu)for (i =0 ; i <APIC_LVT_NUM ; i++)apic_set_reg (apic,APIC_LVTT +0x10 * i,APIC_LVT_MASKED ); +apic_set_reg (apic,APIC_LVT0 , +SET_APIC_DELIVERY_MODE (0 ,APIC_MODE_EXTINT ));apic_set_reg (apic,APIC_DFR ,0xffffffffU );apic_set_reg (apic,APIC_SPIV ,0xff );
@@ -932,6 +934,21 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)return highest_irr; } +int kvm_apic_accept_pic_intr (struct kvm_vcpu *vcpu) +{ +u32 lvt0 =apic_get_reg (vcpu->apic,APIC_LVT0 ); +int r =0 ; + +if (vcpu->vcpu_id ==0 ) { +if (!apic_hw_enabled (vcpu->apic)) + r =1 ; +if ((lvt0 &APIC_LVT_MASKED ) ==0 && +GET_APIC_DELIVERY_MODE (lvt0) ==APIC_MODE_EXTINT ) + r =1 ; + } +return r; +} +void kvm_inject_apic_timer_irqs (struct kvm_vcpu *vcpu) {struct kvm_lapic *apic = vcpu->apic;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 80/104 KVM: round robin for APIC lowest priority delivery mode
In reply to Avi KivityFrom: He, Qing <[email protected]>
--- drivers/kvm/kvm.h | 1 + drivers/kvm/lapic.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-)
drivers/kvm/kvm.h +1 -0
@@ -413,6 +413,7 @@ struct kvm {struct kvm_io_bus pio_bus;struct kvm_pic *vpic;struct kvm_ioapic *vioapic; +int round_robin_prev_vcpu; };static inline struct kvm_pic *pic_irqchip (struct kvm *kvm)
drivers/kvm/lapic.c +28 -5
@@ -371,12 +371,35 @@ struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector, unsigned long bitmap) {int vcpu_id; +int last; +int next; +struct kvm_lapic *apic; + + last = kvm->round_robin_prev_vcpu; + next = last; + +do { +if (++next ==KVM_MAX_VCPUS ) + next =0 ; +if (kvm->vcpus[next] ==NULL || !test_bit (next, &bitmap)) +continue ; + apic = kvm->vcpus[next]->apic; +if (apic &&apic_enabled (apic)) +break ; + apic =NULL ; + }while (next != last); + kvm->round_robin_prev_vcpu = next; + +if (!apic) { + vcpu_id =ffs (bitmap) -1 ; +if (vcpu_id <0 ) { + vcpu_id =0 ; +printk (KERN_DEBUG "vcpu not ready for apic_round_robin\n" ); + } + apic = kvm->vcpus[vcpu_id]->apic; + } -/* TODO for real round robin */ - vcpu_id =fls (bitmap) -1 ; -if (vcpu_id <0 ) -printk (KERN_DEBUG "vcpu not ready for apic_round_robin\n" ); -return kvm->vcpus[vcpu_id]->apic; +return apic; }static void apic_set_eoi (struct kvm_lapic *apic)
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 81/104 KVM: enable in-kernel APIC INIT/SIPI handling
In reply to Avi KivityFrom: He, Qing <[email protected]>
This patch enables INIT/SIPI handling using in-kernel APIC by introducing a ->mp_state field to emulate the SMP state transition.
[avi: remove smp_processor_id() warning]
--- drivers/kvm/irq.h | 1 + drivers/kvm/kvm.h | 7 +++++++ drivers/kvm/kvm_main.c | 26 ++++++++++++++++++++------ drivers/kvm/lapic.c | 43 ++++++++++++++++++++++++++++++++++++------- drivers/kvm/vmx.c | 24 +++++++++++++++++++++--- 5 files changed, 85 insertions(+), 16 deletions(-)
drivers/kvm/irq.h +1 -0
@@ -138,6 +138,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu);int kvm_apic_accept_pic_intr (struct kvm_vcpu *vcpu);int kvm_get_apic_interrupt (struct kvm_vcpu *vcpu);int kvm_create_lapic (struct kvm_vcpu *vcpu); +void kvm_lapic_reset (struct kvm_vcpu *vcpu);void kvm_free_apic (struct kvm_lapic *apic);u64 kvm_lapic_get_cr8 (struct kvm_vcpu *vcpu);void kvm_lapic_set_tpr (struct kvm_vcpu *vcpu,unsigned long cr8);
drivers/kvm/kvm.h +7 -0
@@ -326,6 +326,13 @@ struct kvm_vcpu {u64 shadow_efer;u64 apic_base;struct kvm_lapic *apic;/* kernel irqchip context */ +#define VCPU_MP_STATE_RUNNABLE 0 +#define VCPU_MP_STATE_UNINITIALIZED 1 +#define VCPU_MP_STATE_INIT_RECEIVED 2 +#define VCPU_MP_STATE_SIPI_RECEIVED 3 +#define VCPU_MP_STATE_HALTED 4 +int mp_state; +int sipi_vector;u64 ia32_misc_enable_msr;struct kvm_mmu mmu;
drivers/kvm/kvm_main.c +20 -6
@@ -249,6 +249,10 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id) vcpu->mmu.root_hpa =INVALID_PAGE ; vcpu->kvm = kvm; vcpu->vcpu_id = id; +if (!irqchip_in_kernel (kvm) || id ==0 ) + vcpu->mp_state =VCPU_MP_STATE_RUNNABLE ; +else + vcpu->mp_state =VCPU_MP_STATE_UNINITIALIZED ;init_waitqueue_head (&vcpu->wq); page =alloc_page (GFP_KERNEL | __GFP_ZERO);
@@ -1371,7 +1375,7 @@ EXPORT_SYMBOL_GPL(emulate_instruction);/* * The vCPU has executed a HLT instruction with in-kernel mode enabled. */ -static void kvm_vcpu_kernel_halt (struct kvm_vcpu *vcpu) +static void kvm_vcpu_block (struct kvm_vcpu *vcpu) {DECLARE_WAITQUEUE (wait, current);
@@ -1380,24 +1384,28 @@ static void kvm_vcpu_kernel_halt(struct kvm_vcpu *vcpu)/* * We will block until either an interrupt or a signal wakes us up */ -while (!(irqchip_in_kernel (vcpu->kvm) &&kvm_cpu_has_interrupt (vcpu)) - && !vcpu->irq_summary - && !signal_pending (current)) { +while (!kvm_cpu_has_interrupt (vcpu) + && !signal_pending (current) + && vcpu->mp_state !=VCPU_MP_STATE_RUNNABLE + && vcpu->mp_state !=VCPU_MP_STATE_SIPI_RECEIVED ) {set_current_state (TASK_INTERRUPTIBLE );vcpu_put (vcpu);schedule ();vcpu_load (vcpu); } +__set_current_state (TASK_RUNNING );remove_wait_queue (&vcpu->wq, &wait); -set_current_state (TASK_RUNNING ); }int kvm_emulate_halt (struct kvm_vcpu *vcpu) { ++vcpu->stat.halt_exits;if (irqchip_in_kernel (vcpu->kvm)) { -kvm_vcpu_kernel_halt (vcpu); + vcpu->mp_state =VCPU_MP_STATE_HALTED ; +kvm_vcpu_block (vcpu); +if (vcpu->mp_state !=VCPU_MP_STATE_RUNNABLE ) +return -EINTR ;return 1 ; }else { vcpu->run->exit_reason =KVM_EXIT_HLT ;
@@ -2001,6 +2009,12 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)vcpu_load (vcpu); +if (unlikely (vcpu->mp_state ==VCPU_MP_STATE_UNINITIALIZED )) { +kvm_vcpu_block (vcpu); +vcpu_put (vcpu); +return -EAGAIN ; + } +if (vcpu->sigset_active)sigprocmask (SIG_SETMASK , &vcpu->sigset, &sigsaved);
drivers/kvm/lapic.c +36 -7
89 lines not on this page · raw message
drivers/kvm/vmx.c +21 -3
@@ -1412,6 +1412,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) goto out; } + vmx->vcpu.rmode.active =0 ; + vmx->vcpu.regs[VCPU_REGS_RDX ] =get_rdx_init_val ();set_cr8 (&vmx->vcpu,0 ); msr =0xfee00000 |MSR_IA32_APICBASE_ENABLE ;
@@ -1425,8 +1427,13 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)* GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4. Sigh. */ -vmcs_write16 (GUEST_CS_SELECTOR ,0xf000 ); -vmcs_writel (GUEST_CS_BASE ,0x000f0000 ); +if (vmx->vcpu.vcpu_id ==0 ) { +vmcs_write16 (GUEST_CS_SELECTOR ,0xf000 ); +vmcs_writel (GUEST_CS_BASE ,0x000f0000 ); + }else { +vmcs_write16 (GUEST_CS_SELECTOR , vmx->vcpu.sipi_vector <<8 ); +vmcs_writel (GUEST_CS_BASE , vmx->vcpu.sipi_vector <<12 ); + }vmcs_write32 (GUEST_CS_LIMIT ,0xffff );vmcs_write32 (GUEST_CS_AR_BYTES ,0x9b );
@@ -1451,7 +1458,10 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)vmcs_writel (GUEST_SYSENTER_EIP ,0 );vmcs_writel (GUEST_RFLAGS ,0x02 ); -vmcs_writel (GUEST_RIP ,0xfff0 ); +if (vmx->vcpu.vcpu_id ==0 ) +vmcs_writel (GUEST_RIP ,0xfff0 ); +else +vmcs_writel (GUEST_RIP ,0 );vmcs_writel (GUEST_RSP ,0 );//todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0
@@ -2201,6 +2211,14 @@ static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)u8 fail;int r; +if (unlikely (vcpu->mp_state ==VCPU_MP_STATE_SIPI_RECEIVED )) { +printk ("vcpu %d received sipi with vector # %x\n" , + vcpu->vcpu_id, vcpu->sipi_vector); +kvm_lapic_reset (vcpu); +vmx_vcpu_setup (vmx); + vcpu->mp_state =VCPU_MP_STATE_RUNNABLE ; + } + preempted:if (vcpu->guest_debug.enabled)kvm_guest_debug_pre (vcpu);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 82/104 KVM: Set the ET flag in CR0 after initializing FX
In reply to Avi KivityFrom: Amit Shah <amit.shah-atKUWr5tajBWk0Htik3J/[email protected]>
This was missed when moving stuff around in fbc4f2e
Fixes Solaris guests and bug #1773613
--- drivers/kvm/kvm_main.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +1 -0
@@ -655,6 +655,7 @@ void fx_init(struct kvm_vcpu *vcpu)fx_restore (&vcpu->host_fx_image);preempt_enable (); + vcpu->cr0 |=X86_CR0_ET ; 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,
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 83/104 KVM: Remove the unused invlpg member of struct kvm_arch_ops.
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
--- drivers/kvm/kvm.h | 1 - drivers/kvm/svm.c | 6 ------ 2 files changed, 0 insertions(+), 7 deletions(-)
drivers/kvm/kvm.h +0 -1
@@ -487,7 +487,6 @@ struct kvm_arch_ops {unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);void (*set_rflags)(struct kvm_vcpu *vcpu,unsigned long rflags); -void (*invlpg)(struct kvm_vcpu *vcpu,gva_t addr);void (*tlb_flush)(struct kvm_vcpu *vcpu);void (*inject_page_fault)(struct kvm_vcpu *vcpu,unsigned long addr,u32 err_code);
drivers/kvm/svm.c +0 -6
@@ -881,11 +881,6 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data) svm->vmcb->control.asid = svm_data->next_asid++; } -static void svm_invlpg (struct kvm_vcpu *vcpu,gva_t address) -{ -invlpga (address,to_svm (vcpu)->vmcb->control.asid);// is needed? -} -static unsigned long svm_get_dr (struct kvm_vcpu *vcpu,int dr) {return to_svm (vcpu)->db_regs[dr];
@@ -1795,7 +1790,6 @@ static struct kvm_arch_ops svm_arch_ops = { .get_rflags = svm_get_rflags, .set_rflags = svm_set_rflags, - .invlpg = svm_invlpg, .tlb_flush = svm_flush_tlb, .inject_page_fault = svm_inject_page_fault,
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 84/104 KVM: Clean up unloved invlpg emulation
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
invlpg shouldn't fetch the "src" address, since it may not be valid, however SVM's "solution" which neuters emulation of all group 7 instruction is horrible and breaks kvm-lite. The simplest fix is to put a special check in for invlpg.
--- drivers/kvm/kvm.h | 2 -- drivers/kvm/svm.c | 2 -- drivers/kvm/x86_emulate.c | 16 +++------------- 3 files changed, 3 insertions(+), 17 deletions(-)
drivers/kvm/kvm.h +0 -2
@@ -539,8 +539,6 @@ static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }hpa_t gva_to_hpa (struct kvm_vcpu *vcpu,gva_t gva);struct page *gva_to_page (struct kvm_vcpu *vcpu,gva_t gva); -void kvm_emulator_want_group7_invlpg (void ); -extern hpa_t bad_page_address;struct page *gfn_to_page (struct kvm *kvm,gfn_t gfn);
drivers/kvm/svm.c +0 -2
@@ -376,8 +376,6 @@ static __init int svm_hardware_setup(void)void *iopm_va, *msrpm_va;int r; -kvm_emulator_want_group7_invlpg (); - iopm_pages =alloc_pages (GFP_KERNEL ,IOPM_ALLOC_ORDER );if (!iopm_pages)
drivers/kvm/x86_emulate.c +3 -13
@@ -213,19 +213,6 @@ static u16 twobyte_table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -/* -* Tell the emulator that of the Group 7 instructions (sgdt, lidt, etc.) we -* are interested only in invlpg and not in any of the rest. -* -* invlpg is a special instruction in that the data it references may not -* be mapped. -*/ -void kvm_emulator_want_group7_invlpg (void ) -{ - twobyte_table[1 ] &= ~SrcMem; -} -EXPORT_SYMBOL_GPL (kvm_emulator_want_group7_invlpg); -/* Type, address-of, and value of an instruction's operand. */ struct operand {enum {OP_REG ,OP_MEM ,OP_IMM } type;
@@ -791,6 +778,9 @@ done_prefixes: goto srcmem_common;case SrcMem: src.bytes = (d & ByteOp) ?1 : op_bytes; +/* Don't fetch the address for invlpg: it could be unmapped. */ +if (twobyte && b ==0x01 && modrm_reg ==7 ) +break ; srcmem_common: src.type =OP_MEM ; src.ptr = (unsigned long *)cr2;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 85/104 KVM: Keep control regs in sync
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
We don't update the vcpu control registers in various places. We should do so.
--- drivers/kvm/kvm_main.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
drivers/kvm/kvm_main.c +4 -4
@@ -543,6 +543,7 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)return ; } kvm_arch_ops->set_cr4 (vcpu, cr4); + vcpu->cr4 = cr4;mutex_lock (&vcpu->kvm->lock);kvm_mmu_reset_context (vcpu);mutex_unlock (&vcpu->kvm->lock);
@@ -1238,10 +1239,8 @@ int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address)int emulate_clts (struct kvm_vcpu *vcpu) { -unsigned long cr0; - - cr0 = vcpu->cr0 & ~X86_CR0_TS ; - kvm_arch_ops->set_cr0 (vcpu, cr0); + vcpu->cr0 &= ~X86_CR0_TS ; + kvm_arch_ops->set_cr0 (vcpu, vcpu->cr0);return X86EMUL_CONTINUE ; }
@@ -2228,6 +2227,7 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, kvm_arch_ops->decache_cr4_guest_bits (vcpu); mmu_reset_needed |= vcpu->cr0 != sregs->cr0; + vcpu->cr0 = sregs->cr0; kvm_arch_ops->set_cr0 (vcpu, sregs->cr0); mmu_reset_needed |= vcpu->cr4 != sregs->cr4;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 86/104 KVM: Hoist SVM's get_cs_db_l_bits into core code.
In reply to Avi KivityFrom: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
SVM gets the DB and L bits for the cs by decoding the segment. This is in fact the completely generic code, so hoist it for kvm-lite to use.
--- drivers/kvm/kvm.h | 1 + drivers/kvm/kvm_main.c | 10 ++++++++++ drivers/kvm/svm.c | 10 +--------- 3 files changed, 12 insertions(+), 9 deletions(-)
drivers/kvm/kvm.h +1 -0
@@ -586,6 +586,7 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr0);void set_cr8 (struct kvm_vcpu *vcpu,unsigned long cr0);unsigned long get_cr8 (struct kvm_vcpu *vcpu);void lmsw (struct kvm_vcpu *vcpu,unsigned long msw); +void kvm_get_cs_db_l_bits (struct kvm_vcpu *vcpu,int *db,int *l);int kvm_get_msr_common (struct kvm_vcpu *vcpu,u32 msr,u64 *pdata);int kvm_set_msr_common (struct kvm_vcpu *vcpu,u32 msr,u64 data);
drivers/kvm/kvm_main.c +10 -0
@@ -2272,6 +2272,16 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,return 0 ; } +void kvm_get_cs_db_l_bits (struct kvm_vcpu *vcpu,int *db,int *l) +{ +struct kvm_segment cs; + +get_segment (vcpu, &cs,VCPU_SREG_CS ); + *db = cs.db; + *l = cs.l; +} +EXPORT_SYMBOL_GPL (kvm_get_cs_db_l_bits); +/* * List of msr numbers which we expose to userspace through KVM_GET_MSRS * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST.
drivers/kvm/svm.c +1 -9
@@ -724,14 +724,6 @@ static void svm_get_segment(struct kvm_vcpu *vcpu, var->unusable = !var->present; } -static void svm_get_cs_db_l_bits (struct kvm_vcpu *vcpu,int *db,int *l) -{ -struct vmcb_seg *s =svm_seg (vcpu,VCPU_SREG_CS ); - - *db = (s->attrib >>SVM_SELECTOR_DB_SHIFT ) &1 ; - *l = (s->attrib >>SVM_SELECTOR_L_SHIFT ) &1 ; -} -static void svm_get_idt (struct kvm_vcpu *vcpu,struct descriptor_table *dt) {struct vcpu_svm *svm =to_svm (vcpu);
@@ -1771,7 +1763,7 @@ static struct kvm_arch_ops svm_arch_ops = { .get_segment_base = svm_get_segment_base, .get_segment = svm_get_segment, .set_segment = svm_set_segment, - .get_cs_db_l_bits = svm_get_cs_db_l_bits, + .get_cs_db_l_bits = kvm_get_cs_db_l_bits, .decache_cr4_guest_bits = svm_decache_cr4_guest_bits, .set_cr0 = svm_set_cr0, .set_cr3 = svm_set_cr3,
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 87/104 KVM: Simplify memory allocation
In reply to Avi KivityFrom: Laurent Vivier <[email protected]>
The mutex->splinlock convertion alllows us to make some code simplifications. As we can keep the lock longer, we don't have to release it and then have to check if the environment has not been modified before re-taking it. We can remove kvm->busy and kvm->memory_config_version.
--- drivers/kvm/kvm.h | 2 -- drivers/kvm/kvm_main.c | 38 +++----------------------------------- 2 files changed, 3 insertions(+), 37 deletions(-)
drivers/kvm/kvm.h +0 -2
@@ -411,8 +411,6 @@ struct kvm {int n_free_mmu_pages;struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES ];struct kvm_vcpu *vcpus[KVM_MAX_VCPUS ]; -int memory_config_version; -int busy;unsigned long rmap_overflow;struct list_head vm_list;struct file *filp;
drivers/kvm/kvm_main.c +3 -35
@@ -679,7 +679,6 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,unsigned long i;struct kvm_memory_slot *memslot;struct kvm_memory_slot old, new; -int memory_config_version; r = -EINVAL ;/* General sanity checks */
@@ -699,10 +698,8 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,if (!npages) mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES ; -raced:mutex_lock (&kvm->lock); - memory_config_version = kvm->memory_config_version; new = old = *memslot; new.base_gfn = base_gfn;
@@ -725,11 +722,6 @@ raced: (base_gfn >= s->base_gfn + s->npages))) goto out_unlock; } -/* -* Do memory allocations outside lock. memory_config_version will -* detect any races. -*/ -mutex_unlock (&kvm->lock);/* Deallocate if slot is being removed */ if (!npages)
@@ -746,14 +738,14 @@ raced: new.phys_mem =vmalloc (npages *sizeof (struct page *));if (!new.phys_mem) - goto out_free; + goto out_unlock;memset (new.phys_mem,0 , npages *sizeof (struct page *));for (i =0 ; i < npages; ++i) { new.phys_mem[i] =alloc_page (GFP_HIGHUSER | __GFP_ZERO);if (!new.phys_mem[i]) - goto out_free; + goto out_unlock;set_page_private (new.phys_mem[i],0 ); } }
@@ -764,27 +756,14 @@ raced: new.dirty_bitmap =vmalloc (dirty_bytes);if (!new.dirty_bitmap) - goto out_free; + goto out_unlock;memset (new.dirty_bitmap,0 , dirty_bytes); } -mutex_lock (&kvm->lock); - -if (memory_config_version != kvm->memory_config_version) { -mutex_unlock (&kvm->lock); -kvm_free_physmem_slot (&new, &old); - goto raced; - } - - r = -EAGAIN ; -if (kvm->busy) - goto out_unlock; -if (mem->slot >= kvm->nmemslots) kvm->nmemslots = mem->slot +1 ; *memslot = new; - ++kvm->memory_config_version;kvm_mmu_slot_remove_write_access (kvm, mem->slot);kvm_flush_remote_tlbs (kvm);
@@ -796,7 +775,6 @@ raced: out_unlock:mutex_unlock (&kvm->lock); -out_free:kvm_free_physmem_slot (&new, &old); out:return r;
@@ -815,12 +793,6 @@ static int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,mutex_lock (&kvm->lock); -/* -* Prevent changes to guest memory configuration even while the lock -* is not taken. -*/ - ++kvm->busy; -mutex_unlock (&kvm->lock); r = -EINVAL ;if (log->slot >=KVM_MEMORY_SLOTS ) goto out;
@@ -841,18 +813,14 @@ static int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,/* If nothing is dirty, don't bother messing with page tables. */ if (any) { -mutex_lock (&kvm->lock);kvm_mmu_slot_remove_write_access (kvm, log->slot);kvm_flush_remote_tlbs (kvm);memset (memslot->dirty_bitmap,0 , n); -mutex_unlock (&kvm->lock); } r =0 ; out: -mutex_lock (&kvm->lock); - --kvm->busy;mutex_unlock (&kvm->lock);return r; }
Signature · 1 line
1.5.3
PATCH 88/104 KVM: Rename kvm_arch_ops to kvm_x86_ops
In reply to Avi KivityFrom: Christian Ehrhardt <[email protected]>
This patch just renames the current (misnamed) _arch namings to _x86 to ensure better readability when a real arch layer takes place.
--- drivers/kvm/kvm.h | 8 +- drivers/kvm/kvm_main.c | 160 ++++++++++++++++++++++---------------------- drivers/kvm/mmu.c | 6 +- drivers/kvm/paging_tmpl.h | 2 +- drivers/kvm/svm.c | 6 +- drivers/kvm/vmx.c | 6 +- drivers/kvm/x86_emulate.c | 4 +- 7 files changed, 96 insertions(+), 96 deletions(-)
drivers/kvm/kvm.h +4 -4
@@ -441,7 +441,7 @@ struct descriptor_table {unsigned long base; } __attribute__((packed)); -struct kvm_arch_ops { +struct kvm_x86_ops {int (*cpu_has_kvm_support)(void );/* __init */ int (*disabled_by_bios)(void );/* __init */ void (*hardware_enable)(void *dummy);/* __init */
@@ -499,7 +499,7 @@ struct kvm_arch_ops {void (*set_irq)(struct kvm_vcpu *vcpu,int vec); }; -extern struct kvm_arch_ops *kvm_arch_ops; +extern struct kvm_x86_ops *kvm_x86_ops;/* The guest did something we don't support. */ #define pr_unimpl (vcpu, fmt, ...) \
@@ -515,9 +515,9 @@ extern struct kvm_arch_ops *kvm_arch_ops;int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id);void kvm_vcpu_uninit (struct kvm_vcpu *vcpu); -int kvm_init_arch (struct kvm_arch_ops *ops,unsigned int vcpu_size, +int kvm_init_x86 (struct kvm_x86_ops *ops,unsigned int vcpu_size,struct module *module); -void kvm_exit_arch (void ); +void kvm_exit_x86 (void );int kvm_mmu_module_init (void );void kvm_mmu_module_exit (void );
drivers/kvm/kvm_main.c +80 -80
539 lines not on this page · raw message
drivers/kvm/mmu.c +3 -3
@@ -966,7 +966,7 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu)static void kvm_mmu_flush_tlb (struct kvm_vcpu *vcpu) { ++vcpu->stat.tlb_flush; - kvm_arch_ops->tlb_flush (vcpu); + kvm_x86_ops->tlb_flush (vcpu); }static void paging_new_cr3 (struct kvm_vcpu *vcpu)
@@ -979,7 +979,7 @@ static void inject_page_fault(struct kvm_vcpu *vcpu, u64 addr, u32 err_code) { - kvm_arch_ops->inject_page_fault (vcpu, addr, err_code); + kvm_x86_ops->inject_page_fault (vcpu, addr, err_code); }static void paging_free (struct kvm_vcpu *vcpu)
@@ -1073,7 +1073,7 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu)if (r) goto out;mmu_alloc_roots (vcpu); - kvm_arch_ops->set_cr3 (vcpu, vcpu->mmu.root_hpa); + kvm_x86_ops->set_cr3 (vcpu, vcpu->mmu.root_hpa);kvm_mmu_flush_tlb (vcpu); out:mutex_unlock (&vcpu->kvm->lock);
drivers/kvm/paging_tmpl.h +1 -1
@@ -274,7 +274,7 @@ static void FNAME(set_pte_common)(struct kvm_vcpu *vcpu, access_bits &= ~PT_WRITABLE_MASK ;if (is_writeble_pte (spte)) { spte &= ~PT_WRITABLE_MASK ; - kvm_arch_ops->tlb_flush (vcpu); + kvm_x86_ops->tlb_flush (vcpu); }if (write_fault) *ptwrite =1 ;
drivers/kvm/svm.c +3 -3
@@ -1741,7 +1741,7 @@ static void svm_check_processor_compat(void *rtn) *(int *)rtn =0 ; } -static struct kvm_arch_ops svm_arch_ops = { +static struct kvm_x86_ops svm_x86_ops = { .cpu_has_kvm_support = has_svm, .disabled_by_bios = is_disabled, .hardware_setup = svm_hardware_setup,
@@ -1794,13 +1794,13 @@ static struct kvm_arch_ops svm_arch_ops = {static int __init svm_init (void ) { -return kvm_init_arch (&svm_arch_ops,sizeof (struct vcpu_svm ), +return kvm_init_x86 (&svm_x86_ops,sizeof (struct vcpu_svm ),THIS_MODULE ); } static void __exit svm_exit(void) { -kvm_exit_arch (); +kvm_exit_x86 (); }module_init (svm_init)
drivers/kvm/vmx.c +3 -3
@@ -2548,7 +2548,7 @@ static void __init vmx_check_processor_compat(void *rtn) } } -static struct kvm_arch_ops vmx_arch_ops = { +static struct kvm_x86_ops vmx_x86_ops = { .cpu_has_kvm_support = cpu_has_kvm_support, .disabled_by_bios = vmx_disabled_by_bios, .hardware_setup = hardware_setup,
@@ -2627,7 +2627,7 @@ static int __init vmx_init(void)memset (iova,0xff ,PAGE_SIZE );kunmap (vmx_io_bitmap_b); - r =kvm_init_arch (&vmx_arch_ops,sizeof (struct vcpu_vmx ),THIS_MODULE ); + r =kvm_init_x86 (&vmx_x86_ops,sizeof (struct vcpu_vmx ),THIS_MODULE );if (r) goto out1;
@@ -2645,7 +2645,7 @@ static void __exit vmx_exit(void)__free_page (vmx_io_bitmap_b);__free_page (vmx_io_bitmap_a); -kvm_exit_arch (); +kvm_exit_x86 (); }module_init (vmx_init)
drivers/kvm/x86_emulate.c +2 -2
@@ -1432,7 +1432,7 @@ twobyte_special_insn: | ((u64)_regs[VCPU_REGS_RDX] << 32); rc =kvm_set_msr (ctxt->vcpu, _regs[VCPU_REGS_RCX ], msr_data);if (rc) { - kvm_arch_ops->inject_gp (ctxt->vcpu,0 ); + kvm_x86_ops->inject_gp (ctxt->vcpu,0 ); _eip = ctxt->vcpu->rip; } rc =X86EMUL_CONTINUE ;
@@ -1441,7 +1441,7 @@ twobyte_special_insn:/* rdmsr */ rc =kvm_get_msr (ctxt->vcpu, _regs[VCPU_REGS_RCX ], &msr_data);if (rc) { - kvm_arch_ops->inject_gp (ctxt->vcpu,0 ); + kvm_x86_ops->inject_gp (ctxt->vcpu,0 ); _eip = ctxt->vcpu->rip; }else { _regs[VCPU_REGS_RAX ] = (u32 )msr_data;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 89/104 KVM: MMU: Don't do GFP_NOWAIT allocations
In reply to Avi KivityBefore preempt notifiers, kvm needed to allocate memory with GFP_NOWAIT so as not to have to enable preemption and take a heavyweight exit. On oom, we'd fall back to a GFP_KERNEL allocation.
With preemption notifiers, we can do a GFP_KERNEL allocation, and perform the heavyweight exit only if the kernel decides to put us to sleep.
--- drivers/kvm/mmu.c | 34 ++++++++++------------------------ 1 files changed, 10 insertions(+), 24 deletions(-)
drivers/kvm/mmu.c +10 -24
@@ -202,15 +202,14 @@ static void set_shadow_pte(u64 *sptep, u64 spte) }static int mmu_topup_memory_cache (struct kvm_mmu_memory_cache *cache, -struct kmem_cache *base_cache,int min, -gfp_t gfp_flags) +struct kmem_cache *base_cache,int min) {void *obj;if (cache->nobjs >= min)return 0 ;while (cache->nobjs <ARRAY_SIZE (cache->objects)) { - obj =kmem_cache_zalloc (base_cache, gfp_flags); + obj =kmem_cache_zalloc (base_cache,GFP_KERNEL );if (!obj)return -ENOMEM ; cache->objects[cache->nobjs++] = obj;
@@ -225,14 +224,14 @@ static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc) }static int mmu_topup_memory_cache_page (struct kvm_mmu_memory_cache *cache, -int min,gfp_t gfp_flags) +int min) {struct page *page;if (cache->nobjs >= min)return 0 ;while (cache->nobjs <ARRAY_SIZE (cache->objects)) { - page =alloc_page (gfp_flags); + page =alloc_page (GFP_KERNEL );if (!page)return -ENOMEM ;set_page_private (page,0 );
@@ -247,41 +246,28 @@ static void mmu_free_memory_cache_page(struct kvm_mmu_memory_cache *mc)free_page ((unsigned long )mc->objects[--mc->nobjs]); } -static int __mmu_topup_memory_caches (struct kvm_vcpu *vcpu,gfp_t gfp_flags) +static int mmu_topup_memory_caches (struct kvm_vcpu *vcpu) {int r; +kvm_mmu_free_some_pages (vcpu); r =mmu_topup_memory_cache (&vcpu->mmu_pte_chain_cache, - pte_chain_cache,4 , gfp_flags); + pte_chain_cache,4 );if (r) goto out; r =mmu_topup_memory_cache (&vcpu->mmu_rmap_desc_cache, - rmap_desc_cache,1 , gfp_flags); + rmap_desc_cache,1 );if (r) goto out; - r =mmu_topup_memory_cache_page (&vcpu->mmu_page_cache,4 , gfp_flags); + r =mmu_topup_memory_cache_page (&vcpu->mmu_page_cache,4 );if (r) goto out; r =mmu_topup_memory_cache (&vcpu->mmu_page_header_cache, - mmu_page_header_cache,4 , gfp_flags); + mmu_page_header_cache,4 ); out:return r; } -static int mmu_topup_memory_caches (struct kvm_vcpu *vcpu) -{ -int r; - - r =__mmu_topup_memory_caches (vcpu,GFP_NOWAIT ); -kvm_mmu_free_some_pages (vcpu); -if (r <0 ) { -mutex_unlock (&vcpu->kvm->lock); - r =__mmu_topup_memory_caches (vcpu,GFP_KERNEL ); -mutex_lock (&vcpu->kvm->lock); - } -return r; -} -static void mmu_free_memory_caches (struct kvm_vcpu *vcpu) {mmu_free_memory_cache (&vcpu->mmu_pte_chain_cache);
Signature · 1 line
1.5.3
PATCH 90/104 KVM: VMX: Move vm entry failure handling to the exit handler
In reply to Avi KivityThis will help moving the main loop to subarch independent code.
--- drivers/kvm/vmx.c | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-)
drivers/kvm/vmx.c +10 -9
@@ -43,6 +43,7 @@ struct vmcs {struct vcpu_vmx {struct kvm_vcpu vcpu;int launched; +u8 fail;struct kvm_msr_entry *guest_msrs;struct kvm_msr_entry *host_msrs;int nmsrs;
@@ -2099,6 +2100,14 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) {u32 vectoring_info =vmcs_read32 (IDT_VECTORING_INFO_FIELD );u32 exit_reason =vmcs_read32 (VM_EXIT_REASON ); +struct vcpu_vmx *vmx =to_vmx (vcpu); + +if (unlikely (vmx->fail)) { + kvm_run->exit_reason =KVM_EXIT_FAIL_ENTRY ; + kvm_run->fail_entry.hardware_entry_failure_reason + =vmcs_read32 (VM_INSTRUCTION_ERROR ); +return 0 ; + }if ( (vectoring_info &VECTORING_INFO_VALID_MASK ) && exit_reason !=EXIT_REASON_EXCEPTION_NMI )
@@ -2208,7 +2217,6 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)static int vmx_vcpu_run (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) {struct vcpu_vmx *vmx =to_vmx (vcpu); -u8 fail;int r;if (unlikely (vcpu->mp_state ==VCPU_MP_STATE_SIPI_RECEIVED )) {
@@ -2352,7 +2360,7 @@ again: "pop %%ecx; popa \n\t" #endif "setbe %0 \n\t" - : "=q" (fail) + : "=q" (vmx->fail) : "r"(vmx->launched), "d"((unsigned long)HOST_RSP), "c"(vcpu), [rax]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RAX])),
@@ -2387,13 +2395,6 @@ again:preempt_enable (); -if (unlikely (fail)) { - kvm_run->exit_reason =KVM_EXIT_FAIL_ENTRY ; - kvm_run->fail_entry.hardware_entry_failure_reason - =vmcs_read32 (VM_INSTRUCTION_ERROR ); - r =0 ; - goto out; - }/* * Profile KVM exit RIPs: */
Signature · 1 line
1.5.3
PATCH 91/104 KVM: Move main vcpu loop into subarch independent code
In reply to Avi KivityThis simplifies adding new code as well as reducing overall code size.
--- drivers/kvm/kvm.h | 9 +++- drivers/kvm/kvm_main.c | 124 +++++++++++++++++++++++++++++++++++++++++- drivers/kvm/svm.c | 142 +++++++++++++----------------------------------- drivers/kvm/vmx.c | 129 ++++++-------------------------------------- 4 files changed, 187 insertions(+), 217 deletions(-)
drivers/kvm/kvm.h +8 -1
@@ -453,13 +453,16 @@ struct kvm_x86_ops {/* Create, but do not attach this VCPU */ struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm,unsigned id);void (*vcpu_free)(struct kvm_vcpu *vcpu); +void (*vcpu_reset)(struct kvm_vcpu *vcpu); +void (*prepare_guest_switch)(struct kvm_vcpu *vcpu);void (*vcpu_load)(struct kvm_vcpu *vcpu,int cpu);void (*vcpu_put)(struct kvm_vcpu *vcpu);void (*vcpu_decache)(struct kvm_vcpu *vcpu);int (*set_guest_debug)(struct kvm_vcpu *vcpu,struct kvm_debug_guest *dbg); +void (*guest_debug_pre)(struct kvm_vcpu *vcpu);int (*get_msr)(struct kvm_vcpu *vcpu,u32 msr_index,u64 *pdata);int (*set_msr)(struct kvm_vcpu *vcpu,u32 msr_index,u64 data);u64 (*get_segment_base)(struct kvm_vcpu *vcpu,int seg);
@@ -491,12 +494,16 @@ struct kvm_x86_ops {void (*inject_gp)(struct kvm_vcpu *vcpu,unsigned err_code); -int (*run)(struct kvm_vcpu *vcpu,struct kvm_run *run); +void (*run)(struct kvm_vcpu *vcpu,struct kvm_run *run); +int (*handle_exit)(struct kvm_run *run,struct kvm_vcpu *vcpu);void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);void (*patch_hypercall)(struct kvm_vcpu *vcpu,unsigned char *hypercall_addr);int (*get_irq)(struct kvm_vcpu *vcpu);void (*set_irq)(struct kvm_vcpu *vcpu,int vec); +void (*inject_pending_irq)(struct kvm_vcpu *vcpu); +void (*inject_pending_vectors)(struct kvm_vcpu *vcpu, +struct kvm_run *run); };extern struct kvm_x86_ops *kvm_x86_ops;
drivers/kvm/kvm_main.c +123 -1
142 lines not on this page · raw message
drivers/kvm/svm.c +39 -103
240 lines not on this page · raw message
drivers/kvm/vmx.c +17 -112
206 lines not on this page · raw message
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 92/104 KVM: VMX: Fix exit qualification width on i386
In reply to Avi KivityFrom: He, Qing <[email protected]>
According to Intel Software Developer's Manual, Vol. 3B, Appendix H.4.2, exit qualification should be of natural width. However, current code uses u64 as the data type for this register, which occasionally introduces invalid value to VMExit handling logics. This patch fixes this bug.
I have tested Windows and Linux guest on i386 host, and they can boot successfully with this patch.
--- drivers/kvm/vmx.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
drivers/kvm/vmx.c +6 -6
@@ -1840,12 +1840,12 @@ static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)static int handle_io (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { -u64 exit_qualification; +unsigned long exit_qualification;int size, down, in, string, rep;unsigned port; ++vcpu->stat.io_exits; - exit_qualification =vmcs_read64 (EXIT_QUALIFICATION ); + exit_qualification =vmcs_readl (EXIT_QUALIFICATION ); string = (exit_qualification &16 ) !=0 ;if (string) {
@@ -1877,11 +1877,11 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)static int handle_cr (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { -u64 exit_qualification; +unsigned long exit_qualification;int cr;int reg; - exit_qualification =vmcs_read64 (EXIT_QUALIFICATION ); + exit_qualification =vmcs_readl (EXIT_QUALIFICATION ); cr = exit_qualification &15 ; reg = (exit_qualification >>8 ) &15 ;switch ((exit_qualification >>4 ) &3 ) {
@@ -1950,7 +1950,7 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)static int handle_dr (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { -u64 exit_qualification; +unsigned long exit_qualification;unsigned long val;int dr, reg;
@@ -1958,7 +1958,7 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)* FIXME: this code assumes the host is debugging the guest. * need to deal with guest debugging itself too. */ - exit_qualification =vmcs_read64 (EXIT_QUALIFICATION ); + exit_qualification =vmcs_readl (EXIT_QUALIFICATION ); dr = exit_qualification &7 ; reg = (exit_qualification >>8 ) &15 ;vcpu_load_rsp_rip (vcpu);
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 93/104 KVM: x86 emulator: push imm8
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement the instruction
push imm8
opcode: 0x6a--- drivers/kvm/x86_emulate.c | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-)
drivers/kvm/x86_emulate.c +14 -3
@@ -104,10 +104,11 @@ static u8 opcode_table[256] = {/* 0x58 - 0x5F */ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, -/* 0x60 - 0x6B */ +/* 0x60 - 0x67 */ 0 ,0 ,0 , DstReg | SrcMem32 | ModRM | Mov/* movsxd (x86/64) */ , -0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , -/* 0x6C - 0x6F */ +0 ,0 ,0 ,0 , +/* 0x68 - 0x6F */ +0 ,0 , ImplicitOps|Mov,0 , SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,/* insb, insw/insd */ SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,/* outsb, outsw/outsd */ /* 0x70 - 0x7F */
@@ -919,6 +920,16 @@ done_prefixes: goto cannot_emulate; dst.val = (s32 ) src.val;break ; +case 0x6a :/* push imm8 */ + src.val =0L ; + src.val =insn_fetch (s8,1 , _eip); +push: + dst.type =OP_MEM ; + dst.bytes = op_bytes; + dst.val = src.val; +register_address_increment (_regs[VCPU_REGS_RSP ], -op_bytes); + dst.ptr =register_address (ctxt->ss_base, _regs[VCPU_REGS_RSP ]); +break ; case 0x80 ... 0x83: /* Grp1 */switch (modrm_reg) {case 0 :
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 94/104 KVM: x86 emulator: call near
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement emulation of instruction
opcode: 0xe8 call (near)
--- drivers/kvm/x86_emulate.c | 22 +++++++++++++++++++++- 1 files changed, 21 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +21 -1
@@ -150,7 +150,7 @@ static u8 opcode_table[256] = {/* 0xE0 - 0xE7 */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,/* 0xE8 - 0xEF */ -0 , SrcImm|ImplicitOps,0 , SrcImmByte|ImplicitOps,0 ,0 ,0 ,0 , + ImplicitOps, SrcImm|ImplicitOps,0 , SrcImmByte|ImplicitOps,0 ,0 ,0 ,0 ,/* 0xF0 - 0xF7 */ 0 ,0 ,0 ,0 , ImplicitOps, 0,
@@ -1033,6 +1033,26 @@ push: case 0xd2 ... 0xd3: /* Grp2 */ src.val = _regs[VCPU_REGS_RCX ]; goto grp2; +case 0xe8 :/* call (near) */ { +long int rel; +switch (op_bytes) { +case 2 : + rel =insn_fetch (s16,2 , _eip); +break ; +case 4 : + rel =insn_fetch (s32,4 , _eip); +break ; +case 8 : + rel =insn_fetch (s64,8 , _eip); +break ; +default : +DPRINTF ("Call: Invalid op_bytes\n" ); + goto cannot_emulate; + } + src.val = (unsigned long ) _eip; +JMP_REL (rel); + goto push; + }case 0xe9 :/* jmp rel */ case 0xeb :/* jmp rel short */ JMP_REL (src.val);
Signature · 1 line
1.5.3
PATCH 95/104 KVM: x86 emulator: pushf
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement emulation of instruction
pushf opcode: 0x9c
--- drivers/kvm/x86_emulate.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-)
drivers/kvm/x86_emulate.c +9 -2
@@ -123,7 +123,7 @@ static u8 opcode_table[256] = { ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,0 ,0 ,0 , DstMem | SrcNone | ModRM | Mov,/* 0x90 - 0x9F */ -0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , +0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , ImplicitOps,0 ,0 ,0 ,/* 0xA0 - 0xA7 */ ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov, ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov,
@@ -928,7 +928,8 @@ push: dst.bytes = op_bytes; dst.val = src.val;register_address_increment (_regs[VCPU_REGS_RSP ], -op_bytes); - dst.ptr =register_address (ctxt->ss_base, _regs[VCPU_REGS_RSP ]); + dst.ptr = (void *)register_address (ctxt->ss_base, + _regs[VCPU_REGS_RSP ]);break ; case 0x80 ... 0x83: /* Grp1 */switch (modrm_reg) {
@@ -1216,6 +1217,12 @@ special_insn: ) == 0)return -1 ;return 0 ; + +case 0x9c :/* pushf */ + src.val = (unsigned long ) _eflags; + goto push; +break ; + }if (rep_prefix) {if (_regs[VCPU_REGS_RCX ] ==0 ) {
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 96/104 KVM: Improve emulation failure reporting
In reply to Avi KivityReport failed opcodes from all locations.
--- drivers/kvm/kvm.h | 1 + drivers/kvm/kvm_main.c | 16 ++++++++-------- drivers/kvm/svm.c | 2 +- drivers/kvm/vmx.c | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-)
drivers/kvm/kvm.h +1 -0
@@ -558,6 +558,7 @@ enum emulation_result {int emulate_instruction (struct kvm_vcpu *vcpu,struct kvm_run *run,unsigned long cr2,u16 error_code); +void kvm_report_emulation_failure (struct kvm_vcpu *cvpu,const char *context);void realmode_lgdt (struct kvm_vcpu *vcpu,u16 size,unsigned long address);void realmode_lidt (struct kvm_vcpu *vcpu,u16 size,unsigned long address); void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
drivers/kvm/kvm_main.c +8 -8
@@ -1240,25 +1240,25 @@ int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value)return X86EMUL_CONTINUE ; } -static void report_emulation_failure (struct x86_emulate_ctxt *ctxt) +void kvm_report_emulation_failure (struct kvm_vcpu *vcpu,const char *context) {static int reported;u8 opcodes[4 ]; -unsigned long rip = ctxt->vcpu->rip; +unsigned long rip = vcpu->rip;unsigned long rip_linear; - rip_linear = rip +get_segment_base (ctxt->vcpu,VCPU_SREG_CS ); + rip_linear = rip +get_segment_base (vcpu,VCPU_SREG_CS );if (reported)return ; -emulator_read_std (rip_linear, (void *)opcodes,4 , ctxt->vcpu); +emulator_read_std (rip_linear, (void *)opcodes,4 , vcpu); -printk (KERN_ERR "emulation failed but !mmio_needed?" -" rip %lx %02x %02x %02x %02x\n" , - rip, opcodes[0 ], opcodes[1 ], opcodes[2 ], opcodes[3 ]); +printk (KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n" , + context, rip, opcodes[0 ], opcodes[1 ], opcodes[2 ], opcodes[3 ]); reported =1 ; } +EXPORT_SYMBOL_GPL (kvm_report_emulation_failure);struct x86_emulate_ops emulate_ops = { .read_std = emulator_read_std,
@@ -1323,7 +1323,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,if (kvm_mmu_unprotect_page_virt (vcpu, cr2))return EMULATE_DONE ;if (!vcpu->mmio_needed) { -report_emulation_failure (&emulate_ctxt); +kvm_report_emulation_failure (vcpu,"mmio" );return EMULATE_FAIL ; }return EMULATE_DO_MMIO ;
drivers/kvm/svm.c +1 -1
@@ -960,7 +960,7 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) ++svm->vcpu.stat.mmio_exits;return 0 ;case EMULATE_FAIL : -vcpu_printf (&svm->vcpu,"%s: emulate fail\n" , __FUNCTION__); +kvm_report_emulation_failure (&svm->vcpu,"pagetable" );break ;default :BUG ();
drivers/kvm/vmx.c +1 -1
@@ -1798,7 +1798,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) ++vcpu->stat.mmio_exits;return 0 ;case EMULATE_FAIL : -vcpu_printf (vcpu,"%s: emulate fail\n" , __FUNCTION__); +kvm_report_emulation_failure (vcpu,"pagetable" );break ;default :BUG ();
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 97/104 KVM: x86 emulator: sort opcodes into ascending order
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
--- drivers/kvm/x86_emulate.c | 99 ++++++++++++++++++++++----------------------- 1 files changed, 49 insertions(+), 50 deletions(-)
drivers/kvm/x86_emulate.c +49 -50
@@ -978,19 +978,8 @@ push: dst.val = src.val; lock_prefix =1 ;break ; - case 0xa0 ... 0xa1: /* mov */ - dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX ]; - dst.val = src.val; - _eip += ad_bytes;/* skip src displacement */ -break ; - case 0xa2 ... 0xa3: /* mov */ - dst.val = (unsigned long )_regs[VCPU_REGS_RAX ]; - _eip += ad_bytes;/* skip dst displacement */ -break ; case 0x88 ... 0x8b: /* mov */ - case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ - dst.val = src.val; -break ; + goto mov;case 0x8f :/* pop (sole member of Grp1a) */ /* 64-bit mode: POP always pops a 64-bit operand. */ if (mode ==X86EMUL_MODE_PROT64 )
@@ -1001,6 +990,15 @@ push: goto done;register_address_increment (_regs[VCPU_REGS_RSP ], dst.bytes);break ; + case 0xa0 ... 0xa1: /* mov */ + dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX ]; + dst.val = src.val; + _eip += ad_bytes;/* skip src displacement */ +break ; + case 0xa2 ... 0xa3: /* mov */ + dst.val = (unsigned long )_regs[VCPU_REGS_RAX ]; + _eip += ad_bytes;/* skip dst displacement */ +break ; case 0xc0 ... 0xc1: grp2:/* Grp2 */ switch (modrm_reg) {
@@ -1028,6 +1026,10 @@ push:break ; }break ; + case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ + mov: + dst.val = src.val; +break ; case 0xd0 ... 0xd1: /* Grp2 */ src.val =1 ; goto grp2;
@@ -1186,6 +1188,17 @@ special_insn: dst.ptr = (void *)register_address ( ctxt->ss_base, _regs[VCPU_REGS_RSP ]);break ; + case 0x58 ... 0x5f: /* pop reg */ + dst.ptr = (unsigned long *)&_regs[b &0x7 ]; + pop_instruction: +if ((rc = ops->read_std (register_address (ctxt->ss_base, + _regs[VCPU_REGS_RSP ]), dst.ptr, op_bytes, ctxt->vcpu)) + !=0 ) + goto done; + +register_address_increment (_regs[VCPU_REGS_RSP ], op_bytes); + no_wb =1 ;/* Disable writeback. */ +break ;case 0x6c :/* insb */ case 0x6d :/* insw/insd */ if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
@@ -1217,12 +1230,15 @@ special_insn: ) == 0)return -1 ;return 0 ; -case 0x9c :/* pushf */ src.val = (unsigned long ) _eflags; goto push; -break ; - +case 0xc3 :/* ret */ + dst.ptr = &_eip; + goto pop_instruction; +case 0xf4 :/* hlt */ + ctxt->vcpu->halt_request =1 ; + goto done; }if (rep_prefix) {if (_regs[VCPU_REGS_RCX ] ==0 ) {
@@ -1271,24 +1287,7 @@ special_insn: case 0xae ... 0xaf: /* scas */DPRINTF ("Urk! I don't handle SCAS.\n" ); goto cannot_emulate; -case 0xf4 :/* hlt */ - ctxt->vcpu->halt_request =1 ; - goto done; -case 0xc3 :/* ret */ - dst.ptr = &_eip; - goto pop_instruction; - case 0x58 ... 0x5f: /* pop reg */ - dst.ptr = (unsigned long *)&_regs[b &0x7 ]; - -pop_instruction: -if ((rc = ops->read_std (register_address (ctxt->ss_base, - _regs[VCPU_REGS_RSP ]), dst.ptr, op_bytes, ctxt->vcpu)) - !=0 ) - goto done; -register_address_increment (_regs[VCPU_REGS_RSP ], op_bytes); - no_wb =1 ;/* Disable writeback. */ -break ; } goto writeback;
@@ -1382,6 +1381,16 @@ twobyte_insn:/* Odd cmov opcodes (lsb == 1) have inverted sense. */ no_wb ^= b &1 ;break ; +case 0xa3 : + bt:/* bt */ + src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ +emulate_2op_SrcV_nobyte ("bt" , src, dst, _eflags); +break ; +case 0xab : + bts:/* bts */ + src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ +emulate_2op_SrcV_nobyte ("bts" , src, dst, _eflags); +break ; case 0xb0 ... 0xb1: /* cmpxchg *//* * Save real source value, then compare EAX against
@@ -1399,30 +1408,15 @@ twobyte_insn: dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX ]; }break ; -case 0xa3 : - bt:/* bt */ - src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ -emulate_2op_SrcV_nobyte ("bt" , src, dst, _eflags); -break ;case 0xb3 : btr:/* btr */ src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ emulate_2op_SrcV_nobyte ("btr" , src, dst, _eflags);break ; -case 0xab : - bts:/* bts */ - src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ -emulate_2op_SrcV_nobyte ("bts" , src, dst, _eflags); -break ; case 0xb6 ... 0xb7: /* movzx */ dst.bytes = op_bytes; dst.val = (d & ByteOp) ? (u8 ) src.val : (u16 ) src.val;break ; -case 0xbb : - btc:/* btc */ - src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ -emulate_2op_SrcV_nobyte ("btc" , src, dst, _eflags); -break ;case 0xba :/* Grp8 */ switch (modrm_reg &3 ) {case 0 :
@@ -1435,6 +1429,11 @@ twobyte_insn: goto btc; }break ; +case 0xbb : + btc:/* btc */ + src.val &= (dst.bytes <<3 ) -1 ;/* only subword offset */ +emulate_2op_SrcV_nobyte ("btc" , src, dst, _eflags); +break ; case 0xbe ... 0xbf: /* movsx */ dst.bytes = op_bytes; dst.val = (d & ByteOp) ? (s8 ) src.val : (s16 ) src.val;
@@ -1446,14 +1445,14 @@ twobyte_special_insn:/* Disable writeback. */ no_wb =1 ;switch (b) { +case 0x06 : +emulate_clts (ctxt->vcpu); +break ;case 0x09 :/* wbinvd */ break ;case 0x0d :/* GrpP (prefetch) */ case 0x18 :/* Grp16 (prefetch/nop) */ break ; -case 0x06 : -emulate_clts (ctxt->vcpu); -break ;case 0x20 :/* mov cr, reg */ if (modrm_mod !=3 ) goto cannot_emulate;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 98/104 KVM: x86 emulator: imlpement jump conditional relative
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement emulation of instruction:
jump conditional rel
opcodes: 0x0f 0x80 - 0x0f 0x8f
--- drivers/kvm/x86_emulate.c | 61 ++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 60 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +60 -1
@@ -188,7 +188,10 @@ static u16 twobyte_table[256] = {/* 0x70 - 0x7F */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,/* 0x80 - 0x8F */ -0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,/* 0x90 - 0x9F */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , /* 0xA0 - 0xA7 */
@@ -479,6 +482,41 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt,return rc; } +static int test_cc (unsigned int condition,unsigned int flags) +{ +int rc =0 ; + +switch ((condition &15 ) >>1 ) { +case 0 :/* o */ + rc |= (flags &EFLG_OF ); +break ; +case 1 :/* b/c/nae */ + rc |= (flags &EFLG_CF ); +break ; +case 2 :/* z/e */ + rc |= (flags &EFLG_ZF ); +break ; +case 3 :/* be/na */ + rc |= (flags & (EFLG_CF |EFLG_ZF )); +break ; +case 4 :/* s */ + rc |= (flags &EFLG_SF ); +break ; +case 5 :/* p/pe */ + rc |= (flags &EFLG_PF ); +break ; +case 7 :/* le/ng */ + rc |= (flags &EFLG_ZF ); +/* fall through */ +case 6 :/* l/nge */ + rc |= (!(flags &EFLG_SF ) != !(flags &EFLG_OF )); +break ; + } + +/* Odd condition identifiers (lsb == 1) have inverted sense. */ +return (!!rc ^ (condition &1 )); +} +int x86_emulate_memop (struct x86_emulate_ctxt *ctxt,struct x86_emulate_ops *ops) {
@@ -1486,6 +1524,27 @@ twobyte_special_insn: } rc =X86EMUL_CONTINUE ;break ; + case 0x80 ... 0x8f: /* jnz rel, etc*/ { +long int rel; + +switch (op_bytes) { +case 2 : + rel =insn_fetch (s16,2 , _eip); +break ; +case 4 : + rel =insn_fetch (s32,4 , _eip); +break ; +case 8 : + rel =insn_fetch (s64,8 , _eip); +break ; +default : +DPRINTF ("jnz: Invalid op_bytes\n" ); + goto cannot_emulate; + } +if (test_cc (b, _eflags)) +JMP_REL (rel); +break ; + }case 0xc7 :/* Grp9 (cmpxchg8b) */ {u64 old, new;
Signature · 1 line
1.5.3
PATCH 99/104 KVM: X86 emulator: jump conditional short
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement emulation of more jump conditional instructions
jcc shortrel
opcodes: 0x70 - 0x7f--- drivers/kvm/x86_emulate.c | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-)
drivers/kvm/x86_emulate.c +13 -2
@@ -111,8 +111,12 @@ static u8 opcode_table[256] = {0 ,0 , ImplicitOps|Mov,0 , SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,/* insb, insw/insd */ SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,/* outsb, outsw/outsd */ -/* 0x70 - 0x7F */ -0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , +/* 0x70 - 0x77 */ + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, +/* 0x78 - 0x7F */ + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,/* 0x80 - 0x87 */ ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
@@ -1268,6 +1272,13 @@ special_insn: ) == 0)return -1 ;return 0 ; + case 0x70 ... 0x7f: /* jcc (short) */ { +int rel =insn_fetch (s8,1 , _eip); + +if (test_cc (b, _eflags)) +JMP_REL (rel); +break ; + }case 0x9c :/* pushf */ src.val = (unsigned long ) _eflags; goto push;
Signature · 1 line
1.5.3
PATCH 100/104 KVM: x86 emulator: lea
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement emulation of instruction
lea r16/r32, m
opcode: 0x8d:--- drivers/kvm/x86_emulate.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +4 -1
@@ -125,7 +125,7 @@ static u8 opcode_table[256] = {/* 0x88 - 0x8F */ ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov, ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, -0 ,0 ,0 , DstMem | SrcNone | ModRM | Mov, +0 , ModRM | DstReg,0 , DstMem | SrcNone | ModRM | Mov,/* 0x90 - 0x9F */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , ImplicitOps,0 ,0 ,0 , /* 0xA0 - 0xA7 */
@@ -1022,6 +1022,9 @@ push:break ; case 0x88 ... 0x8b: /* mov */ goto mov; +case 0x8d :/* lea r16/r32, m */ + dst.val = modrm_val; +break ;case 0x8f :/* pop (sole member of Grp1a) */ /* 64-bit mode: POP always pops a 64-bit operand. */ if (mode ==X86EMUL_MODE_PROT64 )
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 101/104 KVM: x86 emulator: jmp abs
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement emulation of instruction:
jump absolute r/m
opcode: 0xff /4
--- drivers/kvm/x86_emulate.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
drivers/kvm/x86_emulate.c +6 -0
@@ -1148,6 +1148,12 @@ push:case 1 :/* dec */ emulate_1op ("dec" , dst, _eflags);break ; +case 4 :/* jmp abs */ +if (b ==0xff ) + _eip = dst.val; +else + goto cannot_emulate; +break ;case 6 :/* push */ /* 64-bit mode: PUSH always pushes a 64-bit operand. */ if (mode ==X86EMUL_MODE_PROT64 ) {
Signature · 1 line
1.5.3
PATCH 102/104 KVM: x86 emulator: fix src, dst value initialization
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Some operand fetches are less than the machine word size and can result in stale bits if used together with operands of different sizes.
--- drivers/kvm/x86_emulate.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/kvm/x86_emulate.c +2 -0
@@ -827,6 +827,7 @@ done_prefixes: srcmem_common: src.type =OP_MEM ; src.ptr = (unsigned long *)cr2; + src.val =0 ;if ((rc = ops->read_emulated ((unsigned long )src.ptr, &src.val, src.bytes, ctxt->vcpu)) !=0 ) goto done;
@@ -891,6 +892,7 @@ done_prefixes: dst.type =OP_MEM ; dst.ptr = (unsigned long *)cr2; dst.bytes = (d & ByteOp) ?1 : op_bytes; + dst.val =0 ;if (d & BitOp) {unsigned long mask = ~(dst.bytes *8 -1 );
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
PATCH 103/104 KVM: x86 emulator: popf
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
Implement emulation of instruction:
popf
opcode: 0x9d--- drivers/kvm/x86_emulate.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/kvm/x86_emulate.c +4 -1
@@ -127,7 +127,7 @@ static u8 opcode_table[256] = { ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,0 , ModRM | DstReg,0 , DstMem | SrcNone | ModRM | Mov,/* 0x90 - 0x9F */ -0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , ImplicitOps,0 ,0 ,0 , +0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , ImplicitOps, ImplicitOps,0 ,0 ,/* 0xA0 - 0xA7 */ ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov, ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov,
@@ -1293,6 +1293,9 @@ special_insn:case 0x9c :/* pushf */ src.val = (unsigned long ) _eflags; goto push; +case 0x9d :/* popf */ + dst.ptr = (unsigned long *) &_eflags; + goto pop_instruction;case 0xc3 :/* ret */ dst.ptr = &_eip; goto pop_instruction;
Signature · 7 lines
1.5.3 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
git-send-email creates duplicate Message-Id's
In reply to Avi KivityThe following might be a bug in git-send-email (git maintainers Cc'ed and KVM list removed from Cc):
Patch 54 got the same Message-Id as patch 61 and patch 89 got the same Message-Id as patch 104.
That's not legal, and users who automatically filter duplicate emails based on the Message-Id will not see two of the patches.
The emails are:
http://marc.info/?l=linux-kernel&m=119002061330270&w=2
http://marc.info/?l=linux-kernel&m=119002059626434&w=2
http://marc.info/?l=linux-kernel&m=119002060011801&w=2
http://marc.info/?l=linux-kernel&m=119002060318915&w=2
cu
Adrian
Signature · 4 lines
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon SeedRe: git-send-email creates duplicate Message-Id's
Quoted 11 lines · Adrian Bunk
The following might be a bug in git-send-email (git maintainers Cc'ed and KVM list removed from Cc):
Patch 54 got the same Message-Id as patch 61 and patch 89 got the same Message-Id as patch 104.
...
The emails are:
http://marc.info/?l=linux-kernel&m=119002061330270&w=2
http://marc.info/?l=linux-kernel&m=119002059626434&w=2
http://marc.info/?l=linux-kernel&m=119002060011801&w=2
http://marc.info/?l=linux-kernel&m=119002060318915&w=2
The old code generated rand(4200) for each message and appended it to the timestamp. I do not know where the original author got 4200 from, but I think if you send many messages within a single second it is possible to get collisions.
I guess something like this patch is an improvement? It generates a single prefix from timestamp and random, and appends a number that is incremented for each message.
---
git-send-email.perl +12 -4
@@ -477,10 +477,18 @@ sub extract_valid_address { # We'll setup a template for the message id, using the "from" address: +my ($message_id_stamp, $message_id_serial); sub make_message_id { - my $date = time; - my $pseudo_rand = int (rand(4200)); + my $uniq; + if (!defined $message_id_stamp) { + $message_id_stamp = sprintf("%s-%s", time, int(rand(4200))); + $message_id_serial = 0; + } + $message_id_serial++; + + $uniq = "$message_id_stamp-$message_id_serial"; + my $du_part; for ($sender, $repocommitter, $repoauthor) { $du_part = extract_valid_address(sanitize_address($_));
@@ -490,8 +498,8 @@ sub make_message_id use Sys::Hostname qw(); $du_part = 'user@' . Sys::Hostname::hostname(); } - my $message_id_template = "<%s-git-send-email-$du_part>"; - $message_id = sprintf $message_id_template, "$date$pseudo_rand"; + my $message_id_template = "<%s-git-send-email-%s>"; + $message_id = sprintf($message_id_template, $uniq, $du_part); #print "new message id = $message_id\n"; # Was useful for debugging }
Re: git-send-email creates duplicate Message-Id's
Quoted 14 lines · Junio C Hamano
Quoted 11 lines · Adrian Bunk
The following might be a bug in git-send-email (git maintainers Cc'ed and KVM list removed from Cc):
Patch 54 got the same Message-Id as patch 61 and patch 89 got the same Message-Id as patch 104.
...
The emails are:
http://marc.info/?l=linux-kernel&m=119002061330270&w=2
http://marc.info/?l=linux-kernel&m=119002059626434&w=2
http://marc.info/?l=linux-kernel&m=119002060011801&w=2
http://marc.info/?l=linux-kernel&m=119002060318915&w=2
Quoted 8 lines
The old code generated rand(4200) for each message and appended it to the timestamp. I do not know where the original author got 4200 from, but I think if you send many messages within a single second it is possible to get collisions.
I guess something like this patch is an improvement? It generates a single prefix from timestamp and random, and appends a number that is incremented for each message.
Much better. You may also consider a possibility of
letting your local MTA do the Message-ID generation, unless you are tracking something with it and thus need to know the generated values. .. but apparently git much prefers sending email by SMTP, where the message-id must be present, or one really should block any such emails.. (except that systems like qmail send error messages without message-id ...)
My own recipe is:
sprintf("%d-%d-%d", time , getpid, ++localsequence)catenate on that your favourite domain name where that recipe is likely to be valid, and you are all set.
/Matti Aarnio -- one of <[email protected]>