kvm updates for 2.6.22
Subsystems (2)
cover kvm updates for 2.6.22
Following is my current 2.6.22 kvm queue. It contains userspace interface updates, improved guest support, cleanups, and plain bugfixes. It will likely grow slightly by the time the merge window opens.
Avi Kivity (34):
KVM: Use own minor number
KVM: Export <linux/kvm.h>
KVM: Fix bogus sign extension in mmu mapping audit
KVM: Use a shared page for kernel/user communication when runing a vcpu
KVM: Do not communicate to userspace through cpu registers during PIO
KVM: Handle cpuid in the kernel instead of punting to userspace
KVM: Remove the 'emulated' field from the userspace interface
KVM: Remove minor wart from KVM_CREATE_VCPU ioctl
KVM: Renumber ioctls
KVM: Add method to check for backwards-compatible API extensions
KVM: Allow userspace to process hypercalls which have no kernel handler
KVM: Fold kvm_run::exit_type into kvm_run::exit_reason
KVM: Add a special exit reason when exiting due to an interrupt
KVM: Initialize the apic_base msr on svm too
KVM: Add guest mode signal mask
KVM: Allow kernel to select size of mmap() buffer
KVM: Future-proof argument-less ioctls
KVM: Avoid guest virtual addresses in string pio userspace interface
KVM: MMU: Remove unnecessary check for pdptr access
KVM: MMU: Remove global pte tracking
KVM: Workaround vmx inability to virtualize the reset state
KVM: Remove set_cr0_no_modeswitch() arch op
KVM: Modify guest segments after potentially switching modes
KVM: Hack real-mode segments on vmx from KVM_SET_SREGS
KVM: Don't allow the guest to turn off the cpu cache
KVM: Remove unused and write-only variables
KVM: MMU: Fix hugepage pdes mapping same physical address with different access
KVM: SVM: Ensure timestamp counter monotonicity
KVM: Use list_move()
KVM: Remove debug message
KVM: x86 emulator: fix bit string operations operand size
KVM: Simply gfn_to_page()
KVM: Add physical memory aliasing feature
KVM: Add fpu get/set operations
Dor Laor (3):
KVM: Fix guest register corruption on paravirt hypercall
KVM: Use the generic skip_emulated_instruction() in hypercall code
KVM: Add mmu cache clear function
Joerg Roedel (2):
KVM: SVM: forbid guest to execute monitor/mwait
KVM: SVM: enable LBRV virtualization if available
Michal Piotrowski (1):
KVM: Remove unused function
Sergey Kiselev (1):
KVM: Handle writes to MCG_STATUS msr
drivers/kvm/kvm.h | 57 +++- drivers/kvm/kvm_main.c | 649 ++++++++++++++++++++++++++++++++++++++++---- drivers/kvm/kvm_svm.h | 2 - drivers/kvm/mmu.c | 69 +++-- drivers/kvm/paging_tmpl.h | 10 +- drivers/kvm/svm.c | 111 +++++--- drivers/kvm/svm.h | 6 + drivers/kvm/vmx.c | 88 +++---- drivers/kvm/x86_emulate.c | 5 +- include/linux/Kbuild | 1 + include/linux/kvm.h | 135 +++++++--- include/linux/miscdevice.h | 1 + 12 files changed, 898 insertions(+), 236 deletions(-)
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 1/41 KVM: Fix guest register corruption on paravirt hypercall
From: Dor Laor <dor.laor-atKUWr5tajBWk0Htik3J/[email protected]>
The hypercall code mixes up the ->cache_regs() and ->decache_regs() callbacks, resulting in guest register corruption.
--- drivers/kvm/kvm_main.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/kvm/kvm_main.c +2 -2
@@ -1177,7 +1177,7 @@ int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run) {unsigned long nr, a0, a1, a2, a3, a4, a5, ret; - kvm_arch_ops->decache_regs (vcpu); + kvm_arch_ops->cache_regs (vcpu); ret = -KVM_EINVAL ;#ifdef CONFIG_X86_64 if (is_long_mode (vcpu)) {
@@ -1204,7 +1204,7 @@ int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run) ; } vcpu->regs[VCPU_REGS_RAX ] = ret; - kvm_arch_ops->cache_regs (vcpu); + kvm_arch_ops->decache_regs (vcpu);return 1 ; }EXPORT_SYMBOL_GPL (kvm_hypercall);
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 2/41 KVM: Use the generic skip_emulated_instruction() in hypercall code
From: Dor Laor <dor.laor-atKUWr5tajBWk0Htik3J/[email protected]>
Instead of twiddling the rip registers directly, use the skip_emulated_instruction() function to do that for us.
--- drivers/kvm/svm.c | 3 ++- drivers/kvm/vmx.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/kvm/svm.c +2 -1
@@ -1078,7 +1078,8 @@ static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)static int vmmcall_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { - vcpu->svm->vmcb->save.rip +=3 ; + vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip +3 ; +skip_emulated_instruction (vcpu);return kvm_hypercall (vcpu, kvm_run); }
drivers/kvm/vmx.c +1 -1
@@ -1658,7 +1658,7 @@ static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)static int handle_vmcall (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { -vmcs_writel (GUEST_RIP ,vmcs_readl (GUEST_RIP )+3 ); +skip_emulated_instruction (vcpu);return kvm_hypercall (vcpu, kvm_run); }
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 3/41 KVM: Use own minor number
Use the minor number (232) allocated to kvm by lanana.
--- drivers/kvm/kvm_main.c | 2 +- include/linux/miscdevice.h | 1 + 2 files changed, 2 insertions(+), 1 deletions(-) mode change 100644 => 100755 drivers/kvm/kvm_main.c
drivers/kvm/kvm_main.c +1 -1
@@ -2299,7 +2299,7 @@ static struct file_operations kvm_chardev_ops = { };static struct miscdevice kvm_dev = { -MISC_DYNAMIC_MINOR , +KVM_MINOR ,"kvm" , &kvm_chardev_ops, };
include/linux/miscdevice.h +1 -0
@@ -29,6 +29,7 @@#define TUN_MINOR 200#define HPET_MINOR 228 +#define KVM_MINOR 232struct device ;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 4/41 KVM: Export <linux/kvm.h>
This allows users to actually build prgrams that use kvm without the entire source tree.
--- include/linux/Kbuild | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
include/linux/Kbuild +1 -0
@@ -99,6 +99,7 @@ header-y += iso_fs.h header-y += ixjuser.h header-y += jffs2.h header-y += keyctl.h +header-y += kvm.h header-y += limits.h header-y += lock_dlm_plock.h header-y += magic.h
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 5/41 KVM: Fix bogus sign extension in mmu mapping audit
When auditing a 32-bit guest on a 64-bit host, sign extension of the page table directory pointer table index caused bogus addresses to be shown on audit errors.
Fix by declaring the index unsigned.
--- drivers/kvm/mmu.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/kvm/mmu.c +1 -1
@@ -1359,7 +1359,7 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,static void audit_mappings (struct kvm_vcpu *vcpu) { -int i; +unsigned i;if (vcpu->mmu.root_level ==4 )audit_mappings_page (vcpu, vcpu->mmu.root_hpa,0 ,4 );
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 6/41 KVM: Use a shared page for kernel/user communication when runing a vcpu
Instead of passing a 'struct kvm_run' back and forth between the kernel and userspace, allocate a page and allow the user to mmap() it. This reduces needless copying and makes the interface expandable by providing lots of free space.
--- drivers/kvm/kvm.h | 1 + drivers/kvm/kvm_main.c | 54 +++++++++++++++++++++++++++++++++++------------ include/linux/kvm.h | 6 ++-- 3 files changed, 44 insertions(+), 17 deletions(-)
drivers/kvm/kvm.h +1 -0
@@ -228,6 +228,7 @@ struct kvm_vcpu {struct mutex mutex;int cpu;int launched; +struct kvm_run *run;int interrupt_window_open;unsigned long irq_summary;/* bit vector: 1 per word in irq_pending */ #define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long)
drivers/kvm/kvm_main.c +40 -14
97 lines not on this page · raw message
include/linux/kvm.h +3 -3
@@ -11,7 +11,7 @@#include <asm/types.h> #include <linux/ioctl.h> -#define KVM_API_VERSION 4 +#define KVM_API_VERSION 5/* * Architectural interrupt line count, and the size of the bitmap needed
@@ -49,7 +49,7 @@ enum kvm_exit_reason { KVM_EXIT_SHUTDOWN = 8, }; -/* for KVM_RUN */ +/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ struct kvm_run {/* in */ __u32 emulated;/* skip current instruction */
@@ -233,7 +233,7 @@ struct kvm_dirty_log {/* * ioctls for vcpu fds */ -#define KVM_RUN _IOWR(KVMIO, 2, struct kvm_run) +#define KVM_RUN _IO(KVMIO, 16)#define KVM_GET_REGS _IOR(KVMIO, 3, struct kvm_regs)#define KVM_SET_REGS _IOW(KVMIO, 4, struct kvm_regs)#define KVM_GET_SREGS _IOR(KVMIO, 5, struct kvm_sregs)
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 7/41 KVM: Do not communicate to userspace through cpu registers during PIO
Currently when passing the a PIO emulation request to userspace, we rely on userspace updating %rax (on 'in' instructions) and %rsi/%rdi/%rcx (on string instructions). This (a) requires two extra ioctls for getting and setting the registers and (b) is unfriendly to non-x86 archs, when they get kvm ports.
So fix by doing the register fixups in the kernel and passing to userspace only an abstract description of the PIO to be done.
--- drivers/kvm/kvm.h | 1 + drivers/kvm/kvm_main.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- drivers/kvm/svm.c | 2 ++ drivers/kvm/vmx.c | 2 ++ include/linux/kvm.h | 6 +++--- 5 files changed, 53 insertions(+), 6 deletions(-) mode change 100755 => 100644 drivers/kvm/kvm_main.c
drivers/kvm/kvm.h +1 -0
@@ -274,6 +274,7 @@ struct kvm_vcpu {int mmio_size;unsigned char mmio_data[8 ];gpa_t mmio_phys_addr; +int pio_pending;struct {int active;
drivers/kvm/kvm_main.c +45 -3
60 lines not on this page · raw message
drivers/kvm/svm.c +2 -0
@@ -1037,6 +1037,7 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) kvm_run->io.size = ((io_info &SVM_IOIO_SIZE_MASK ) >>SVM_IOIO_SIZE_SHIFT ); kvm_run->io.string = (io_info &SVM_IOIO_STR_MASK ) !=0 ; kvm_run->io.rep = (io_info &SVM_IOIO_REP_MASK ) !=0 ; + kvm_run->io.count =1 ;if (kvm_run->io.string) {unsigned addr_mask;
@@ -1056,6 +1057,7 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) } }else kvm_run->io.value = vcpu->svm->vmcb->save.rax; + vcpu->pio_pending =1 ;return 0 ; }
drivers/kvm/vmx.c +2 -0
@@ -1459,12 +1459,14 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0; kvm_run->io.rep = (exit_qualification &32 ) !=0 ; kvm_run->io.port = exit_qualification >>16 ; + kvm_run->io.count =1 ;if (kvm_run->io.string) {if (!get_io_count (vcpu, &kvm_run->io.count))return 1 ; kvm_run->io.address =vmcs_readl (GUEST_LINEAR_ADDRESS ); }else kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX ];/* rax */ + vcpu->pio_pending =1 ;return 0 ; }
include/linux/kvm.h +3 -3
@@ -11,7 +11,7 @@#include <asm/types.h> #include <linux/ioctl.h> -#define KVM_API_VERSION 5 +#define KVM_API_VERSION 6/* * Architectural interrupt line count, and the size of the bitmap needed
@@ -53,7 +53,7 @@ enum kvm_exit_reason {struct kvm_run {/* in */ __u32 emulated;/* skip current instruction */ -__u32 mmio_completed;/* mmio request completed */ +__u32 io_completed;/* mmio/pio request completed */ __u8 request_interrupt_window;__u8 padding1[7 ];
@@ -80,7 +80,7 @@ struct kvm_run {__u32 error_code; } ex;/* KVM_EXIT_IO */ -struct { +struct kvm_io {#define KVM_EXIT_IO_IN 0#define KVM_EXIT_IO_OUT 1__u8 direction;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 8/41 KVM: Handle cpuid in the kernel instead of punting to userspace
KVM used to handle cpuid by letting userspace decide what values to return to the guest. We now handle cpuid completely in the kernel. We still let userspace decide which values the guest will see by having userspace set up the value table beforehand (this is necessary to allow management software to set the cpu features to the least common denominator, so that live migration can work).
The motivation for the change is that kvm kernel code can be impacted by cpuid features, for example the x86 emulator.
--- drivers/kvm/kvm.h | 5 +++ drivers/kvm/kvm_main.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/kvm/svm.c | 4 +- drivers/kvm/vmx.c | 4 +- include/linux/kvm.h | 18 ++++++++++++- 5 files changed, 95 insertions(+), 5 deletions(-)
drivers/kvm/kvm.h +5 -0
@@ -55,6 +55,7 @@#define KVM_NUM_MMU_PAGES 256#define KVM_MIN_FREE_MMU_PAGES 5#define KVM_REFILL_PAGES 25 +#define KVM_MAX_CPUID_ENTRIES 40#define FX_IMAGE_SIZE 512#define FX_IMAGE_ALIGN 16
@@ -286,6 +287,9 @@ struct kvm_vcpu {u32 ar; } tr, es, ds, fs, gs; } rmode; + +int cpuid_nent; +struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES ]; };struct kvm_memory_slot {
@@ -446,6 +450,7 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,struct x86_emulate_ctxt ; +void kvm_emulate_cpuid (struct kvm_vcpu *vcpu);int emulate_invlpg (struct kvm_vcpu *vcpu,gva_t address);int emulate_clts (struct kvm_vcpu *vcpu); int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr,
drivers/kvm/kvm_main.c +69 -0
87 lines not on this page · raw message
drivers/kvm/svm.c +2 -2
@@ -1101,8 +1101,8 @@ static int task_switch_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_rstatic int cpuid_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip +2 ; - kvm_run->exit_reason =KVM_EXIT_CPUID ; -return 0 ; +kvm_emulate_cpuid (vcpu); +return 1 ; }static int emulate_on_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run)
drivers/kvm/vmx.c +2 -2
@@ -1585,8 +1585,8 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)static int handle_cpuid (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { - kvm_run->exit_reason =KVM_EXIT_CPUID ; -return 0 ; +kvm_emulate_cpuid (vcpu); +return 1 ; }static int handle_rdmsr (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run)
include/linux/kvm.h +17 -1
@@ -41,7 +41,6 @@ enum kvm_exit_reason {KVM_EXIT_UNKNOWN =0 ,KVM_EXIT_EXCEPTION =1 ,KVM_EXIT_IO =2 , -KVM_EXIT_CPUID =3 ,KVM_EXIT_DEBUG =4 ,KVM_EXIT_HLT =5 , KVM_EXIT_MMIO = 6,
@@ -210,6 +209,22 @@ struct kvm_dirty_log { }; }; +struct kvm_cpuid_entry { +__u32 function; +__u32 eax; +__u32 ebx; +__u32 ecx; +__u32 edx; +__u32 padding; +}; + +/* for KVM_SET_CPUID */ +struct kvm_cpuid { +__u32 nent; +__u32 padding; +struct kvm_cpuid_entry entries[0 ]; +}; +#define KVMIO 0xAE/*
@@ -243,5 +258,6 @@ struct kvm_dirty_log {#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest)#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs)#define KVM_SET_MSRS _IOW(KVMIO, 14, struct kvm_msrs) +#define KVM_SET_CPUID _IOW(KVMIO, 17, struct kvm_cpuid)#endif
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 9/41 KVM: Remove the 'emulated' field from the userspace interface
We no longer emulate single instructions in userspace. Instead, we service mmio or pio requests.
--- drivers/kvm/kvm_main.c | 5 ----- include/linux/kvm.h | 3 +-- 2 files changed, 1 insertions(+), 7 deletions(-)
drivers/kvm/kvm_main.c +0 -5
@@ -1588,11 +1588,6 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)/* re-sync apic's tpr */ vcpu->cr8 = kvm_run->cr8; -if (kvm_run->emulated) { - kvm_arch_ops->skip_emulated_instruction (vcpu); - kvm_run->emulated =0 ; - } -if (kvm_run->io_completed) {if (vcpu->pio_pending)complete_pio (vcpu);
include/linux/kvm.h +1 -2
@@ -51,10 +51,9 @@ enum kvm_exit_reason {/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ struct kvm_run {/* in */ -__u32 emulated;/* skip current instruction */ __u32 io_completed;/* mmio/pio request completed */ __u8 request_interrupt_window; -__u8 padding1[7 ]; +__u8 padding1[3 ];/* out */ __u32 exit_type;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 10/41 KVM: Remove minor wart from KVM_CREATE_VCPU ioctl
That ioctl does not transfer any data, so it should be an _IO rather than an _IOW.
--- include/linux/kvm.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/kvm.h +1 -1
@@ -241,7 +241,7 @@ struct kvm_cpuid {* KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns * a vcpu fd. */ -#define KVM_CREATE_VCPU _IOW(KVMIO, 11, int) +#define KVM_CREATE_VCPU _IO(KVMIO, 11)#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log)/*
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 11/41 KVM: Renumber ioctls
The recent changes have left the ioctl numbers in complete disarray.
--- include/linux/kvm.h | 34 +++++++++++++++++----------------- 1 files changed, 17 insertions(+), 17 deletions(-)
include/linux/kvm.h +17 -17
@@ -229,34 +229,34 @@ struct kvm_cpuid {/* * ioctls for /dev/kvm fds: */ -#define KVM_GET_API_VERSION _IO(KVMIO, 1) -#define KVM_CREATE_VM _IO(KVMIO, 2)/* returns a VM fd */ -#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 15, struct kvm_msr_list) +#define KVM_GET_API_VERSION _IO(KVMIO, 0x00) +#define KVM_CREATE_VM _IO(KVMIO, 0x01)/* returns a VM fd */ +#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list)/* * ioctls for VM fds */ -#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 10, struct kvm_memory_region) +#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)/* * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns * a vcpu fd. */ -#define KVM_CREATE_VCPU _IO(KVMIO, 11) -#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log) +#define KVM_CREATE_VCPU _IO(KVMIO, 0x41) +#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)/* * ioctls for vcpu fds */ -#define KVM_RUN _IO(KVMIO, 16) -#define KVM_GET_REGS _IOR(KVMIO, 3, struct kvm_regs) -#define KVM_SET_REGS _IOW(KVMIO, 4, struct kvm_regs) -#define KVM_GET_SREGS _IOR(KVMIO, 5, struct kvm_sregs) -#define KVM_SET_SREGS _IOW(KVMIO, 6, struct kvm_sregs) -#define KVM_TRANSLATE _IOWR(KVMIO, 7, struct kvm_translation) -#define KVM_INTERRUPT _IOW(KVMIO, 8, struct kvm_interrupt) -#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest) -#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs) -#define KVM_SET_MSRS _IOW(KVMIO, 14, struct kvm_msrs) -#define KVM_SET_CPUID _IOW(KVMIO, 17, struct kvm_cpuid) +#define KVM_RUN _IO(KVMIO, 0x80) +#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs) +#define KVM_SET_REGS _IOW(KVMIO, 0x82, struct kvm_regs) +#define KVM_GET_SREGS _IOR(KVMIO, 0x83, struct kvm_sregs) +#define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs) +#define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation) +#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt) +#define KVM_DEBUG_GUEST _IOW(KVMIO, 0x87, struct kvm_debug_guest) +#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs) +#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs) +#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)#endif
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 12/41 KVM: Add method to check for backwards-compatible API extensions
--- drivers/kvm/kvm_main.c | 6 ++++++ include/linux/kvm.h | 5 +++++ 2 files changed, 11 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +6 -0
@@ -2416,6 +2416,12 @@ static long kvm_dev_ioctl(struct file *filp, r =0 ;break ; } +case KVM_CHECK_EXTENSION : +/* +* No extensions defined at present. +*/ + r =0 ; +break ;default : ; }
include/linux/kvm.h +5 -0
@@ -232,6 +232,11 @@ struct kvm_cpuid {#define KVM_GET_API_VERSION _IO(KVMIO, 0x00)#define KVM_CREATE_VM _IO(KVMIO, 0x01)/* returns a VM fd */ #define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list) +/* +* Check if a kvm extension is available. Argument is extension number, +* return is 1 (yes) or 0 (no, sorry). +*/ +#define KVM_CHECK_EXTENSION _IO(KVMIO, 0x03)/* * ioctls for VM fds
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 13/41 KVM: Allow userspace to process hypercalls which have no kernel handler
This is useful for paravirtualized graphics devices, for example.
--- drivers/kvm/kvm_main.c | 18 +++++++++++++++++- include/linux/kvm.h | 10 +++++++++- 2 files changed, 26 insertions(+), 2 deletions(-)
drivers/kvm/kvm_main.c +17 -1
@@ -1203,7 +1203,16 @@ int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run) }switch (nr) {default : - ; + run->hypercall.args[0 ] = a0; + run->hypercall.args[1 ] = a1; + run->hypercall.args[2 ] = a2; + run->hypercall.args[3 ] = a3; + run->hypercall.args[4 ] = a4; + run->hypercall.args[5 ] = a5; + run->hypercall.ret = ret; + run->hypercall.longmode =is_long_mode (vcpu); + kvm_arch_ops->decache_regs (vcpu); +return 0 ; } vcpu->regs[VCPU_REGS_RAX ] = ret; kvm_arch_ops->decache_regs (vcpu);
@@ -1599,6 +1608,13 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) vcpu->mmio_needed =0 ; +if (kvm_run->exit_type ==KVM_EXIT_TYPE_VM_EXIT + && kvm_run->exit_reason ==KVM_EXIT_HYPERCALL ) { + kvm_arch_ops->cache_regs (vcpu); + vcpu->regs[VCPU_REGS_RAX ] = kvm_run->hypercall.ret; + kvm_arch_ops->decache_regs (vcpu); + } + r = kvm_arch_ops->run (vcpu, kvm_run);vcpu_put (vcpu);
include/linux/kvm.h +9 -1
@@ -11,7 +11,7 @@#include <asm/types.h> #include <linux/ioctl.h> -#define KVM_API_VERSION 6 +#define KVM_API_VERSION 7/* * Architectural interrupt line count, and the size of the bitmap needed
@@ -41,6 +41,7 @@ enum kvm_exit_reason {KVM_EXIT_UNKNOWN =0 ,KVM_EXIT_EXCEPTION =1 ,KVM_EXIT_IO =2 , +KVM_EXIT_HYPERCALL =3 ,KVM_EXIT_DEBUG =4 ,KVM_EXIT_HLT =5 , KVM_EXIT_MMIO = 6,
@@ -103,6 +104,13 @@ struct kvm_run {__u32 len;__u8 is_write; } mmio; +/* KVM_EXIT_HYPERCALL */ +struct { +__u64 args[6 ]; +__u64 ret; +__u32 longmode; +__u32 pad; + } hypercall; }; };
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 14/41 KVM: Fold kvm_run::exit_type into kvm_run::exit_reason
Currently, userspace is told about the nature of the last exit from the guest using two fields, exit_type and exit_reason, where exit_type has just two enumerations (and no need for more). So fold exit_type into exit_reason, reducing the complexity of determining what really happened.
--- drivers/kvm/kvm_main.c | 3 +-- drivers/kvm/svm.c | 7 +++---- drivers/kvm/vmx.c | 7 +++---- include/linux/kvm.h | 15 ++++++++------- 4 files changed, 15 insertions(+), 17 deletions(-)
drivers/kvm/kvm_main.c +1 -2
@@ -1608,8 +1608,7 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) vcpu->mmio_needed =0 ; -if (kvm_run->exit_type ==KVM_EXIT_TYPE_VM_EXIT - && kvm_run->exit_reason ==KVM_EXIT_HYPERCALL ) { +if (kvm_run->exit_reason ==KVM_EXIT_HYPERCALL ) { kvm_arch_ops->cache_regs (vcpu); vcpu->regs[VCPU_REGS_RAX ] = kvm_run->hypercall.ret; kvm_arch_ops->decache_regs (vcpu);
drivers/kvm/svm.c +3 -4
@@ -1298,8 +1298,6 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) {u32 exit_code = vcpu->svm->vmcb->control.exit_code; - kvm_run->exit_type =KVM_EXIT_TYPE_VM_EXIT ; -if (is_external_interrupt (vcpu->svm->vmcb->control.exit_int_info) && exit_code !=SVM_EXIT_EXCP_BASE +PF_VECTOR ) printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
@@ -1609,8 +1607,9 @@ again: vcpu->svm->next_rip =0 ;if (vcpu->svm->vmcb->control.exit_code ==SVM_EXIT_ERR ) { - kvm_run->exit_type =KVM_EXIT_TYPE_FAIL_ENTRY ; - kvm_run->exit_reason = vcpu->svm->vmcb->control.exit_code; + kvm_run->exit_reason =KVM_EXIT_FAIL_ENTRY ; + kvm_run->fail_entry.hardware_entry_failure_reason + = vcpu->svm->vmcb->control.exit_code;post_kvm_run_save (vcpu, kvm_run);return 0 ; }
drivers/kvm/vmx.c +3 -4
@@ -1922,10 +1922,10 @@ again: asm ("mov %0, %%ds; mov %0, %%es" : :"r" (__USER_DS)); - kvm_run->exit_type =0 ;if (fail) { - kvm_run->exit_type =KVM_EXIT_TYPE_FAIL_ENTRY ; - kvm_run->exit_reason =vmcs_read32 (VM_INSTRUCTION_ERROR ); + kvm_run->exit_reason =KVM_EXIT_FAIL_ENTRY ; + kvm_run->fail_entry.hardware_entry_failure_reason + =vmcs_read32 (VM_INSTRUCTION_ERROR ); r =0 ; }else {/*
@@ -1935,7 +1935,6 @@ again:profile_hit (KVM_PROFILING , (void *)vmcs_readl (GUEST_RIP )); vcpu->launched =1 ; - kvm_run->exit_type =KVM_EXIT_TYPE_VM_EXIT ; r =kvm_handle_exit (kvm_run, vcpu);if (r >0 ) {/* Give scheduler a change to reschedule. */
include/linux/kvm.h +8 -7
@@ -11,7 +11,7 @@#include <asm/types.h> #include <linux/ioctl.h> -#define KVM_API_VERSION 7 +#define KVM_API_VERSION 8/* * Architectural interrupt line count, and the size of the bitmap needed
@@ -34,9 +34,6 @@ struct kvm_memory_region {#define KVM_MEM_LOG_DIRTY_PAGES 1UL -#define KVM_EXIT_TYPE_FAIL_ENTRY 1 -#define KVM_EXIT_TYPE_VM_EXIT 2 -enum kvm_exit_reason {KVM_EXIT_UNKNOWN =0 ,KVM_EXIT_EXCEPTION =1 ,
@@ -47,6 +44,7 @@ enum kvm_exit_reason {KVM_EXIT_MMIO =6 ,KVM_EXIT_IRQ_WINDOW_OPEN =7 ,KVM_EXIT_SHUTDOWN =8 , + KVM_EXIT_FAIL_ENTRY = 9, };/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
@@ -57,12 +55,11 @@ struct kvm_run {__u8 padding1[3 ];/* out */ -__u32 exit_type;__u32 exit_reason;__u32 instruction_length;__u8 ready_for_interrupt_injection;__u8 if_flag; -__u16 padding2; +__u8 padding2[6 ];/* in (pre_kvm_run), out (post_kvm_run) */ __u64 cr8;
@@ -71,8 +68,12 @@ struct kvm_run {union {/* KVM_EXIT_UNKNOWN */ struct { -__u32 hardware_exit_reason; +__u64 hardware_exit_reason; } hw; +/* KVM_EXIT_FAIL_ENTRY */ +struct { +__u64 hardware_entry_failure_reason; + } fail_entry;/* KVM_EXIT_EXCEPTION */ struct {__u32 exception;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 15/41 KVM: Add a special exit reason when exiting due to an interrupt
This is redundant, as we also return -EINTR from the ioctl, but it allows us to examine the exit_reason field on resume without seeing old data.
--- drivers/kvm/svm.c | 2 ++ drivers/kvm/vmx.c | 2 ++ include/linux/kvm.h | 3 ++- 3 files changed, 6 insertions(+), 1 deletions(-)
drivers/kvm/svm.c +2 -0
@@ -1619,12 +1619,14 @@ again:if (signal_pending (current)) { ++kvm_stat.signal_exits;post_kvm_run_save (vcpu, kvm_run); + kvm_run->exit_reason =KVM_EXIT_INTR ;return -EINTR ; }if (dm_request_for_irq_injection (vcpu, kvm_run)) { ++kvm_stat.request_irq_exits;post_kvm_run_save (vcpu, kvm_run); + kvm_run->exit_reason =KVM_EXIT_INTR ;return -EINTR ; }kvm_resched (vcpu);
drivers/kvm/vmx.c +2 -0
@@ -1941,12 +1941,14 @@ again:if (signal_pending (current)) { ++kvm_stat.signal_exits;post_kvm_run_save (vcpu, kvm_run); + kvm_run->exit_reason =KVM_EXIT_INTR ;return -EINTR ; }if (dm_request_for_irq_injection (vcpu, kvm_run)) { ++kvm_stat.request_irq_exits;post_kvm_run_save (vcpu, kvm_run); + kvm_run->exit_reason =KVM_EXIT_INTR ;return -EINTR ; }
include/linux/kvm.h +2 -1
@@ -11,7 +11,7 @@#include <asm/types.h> #include <linux/ioctl.h> -#define KVM_API_VERSION 8 +#define KVM_API_VERSION 9/* * Architectural interrupt line count, and the size of the bitmap needed
@@ -45,6 +45,7 @@ enum kvm_exit_reason {KVM_EXIT_IRQ_WINDOW_OPEN =7 ,KVM_EXIT_SHUTDOWN =8 ,KVM_EXIT_FAIL_ENTRY =9 , + KVM_EXIT_INTR = 10, };/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 16/41 KVM: Initialize the apic_base msr on svm too
Older userspace didn't care, but newer userspace (with the cpuid changes) does.
--- drivers/kvm/svm.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/kvm/svm.c +3 -0
@@ -582,6 +582,9 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu)init_vmcb (vcpu->svm->vmcb);fx_init (vcpu); + vcpu->apic_base =0xfee00000 | +/*for vcpu 0*/ MSR_IA32_APICBASE_BSP | +MSR_IA32_APICBASE_ENABLE ;return 0 ;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 17/41 KVM: Add guest mode signal mask
Allow a special signal mask to be used while executing in guest mode. This allows signals to be used to interrupt a vcpu without requiring signal delivery to a userspace handler, which is quite expensive. Userspace still receives -EINTR and can get the signal via sigwait().
--- drivers/kvm/kvm.h | 3 +++ drivers/kvm/kvm_main.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/linux/kvm.h | 7 +++++++ 3 files changed, 51 insertions(+), 0 deletions(-)
drivers/kvm/kvm.h +3 -0
@@ -277,6 +277,9 @@ struct kvm_vcpu {gpa_t mmio_phys_addr;int pio_pending; +int sigset_active; +sigset_t sigset; +struct {int active;u8 save_iopl;
drivers/kvm/kvm_main.c +41 -0
68 lines not on this page · raw message
include/linux/kvm.h +7 -0
@@ -234,6 +234,12 @@ struct kvm_cpuid {struct kvm_cpuid_entry entries[0 ]; }; +/* for KVM_SET_SIGNAL_MASK */ +struct kvm_signal_mask { +__u32 len; +__u8 sigset[0 ]; +}; +#define KVMIO 0xAE/*
@@ -273,5 +279,6 @@ struct kvm_cpuid {#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs)#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid) +#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask)#endif
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 18/41 KVM: Allow kernel to select size of mmap() buffer
This allows us to store offsets in the kernel/user kvm_run area, and be sure that userspace has them mapped. As offsets can be outside the kvm_run struct, userspace has no way of knowing how much to mmap.
--- drivers/kvm/kvm_main.c | 8 +++++++- include/linux/kvm.h | 4 ++++ 2 files changed, 11 insertions(+), 1 deletions(-)
drivers/kvm/kvm_main.c +7 -1
@@ -2436,7 +2436,7 @@ static long kvm_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { void __user *argp = (void __user *)arg; -int r = -EINVAL ; +long r = -EINVAL ;switch (ioctl) {case KVM_GET_API_VERSION :
@@ -2478,6 +2478,12 @@ static long kvm_dev_ioctl(struct file *filp,*/ r =0 ;break ; +case KVM_GET_VCPU_MMAP_SIZE : + r = -EINVAL ; +if (arg) + goto out; + r =PAGE_SIZE ; +break ;default : ; }
include/linux/kvm.h +4 -0
@@ -253,6 +253,10 @@ struct kvm_signal_mask {* return is 1 (yes) or 0 (no, sorry). */ #define KVM_CHECK_EXTENSION _IO(KVMIO, 0x03) +/* +* Get size for mmap(vcpu_fd) +*/ +#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04)/* in bytes */ /* * ioctls for VM fds
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 19/41 KVM: Future-proof argument-less ioctls
Some ioctls ignore their arguments. By requiring them to be zero now, we allow a nonzero value to have some special meaning in the future.
--- drivers/kvm/kvm_main.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +9 -0
@@ -2169,6 +2169,9 @@ static long kvm_vcpu_ioctl(struct file *filp,switch (ioctl) {case KVM_RUN : + r = -EINVAL ; +if (arg) + goto out; r =kvm_vcpu_ioctl_run (vcpu, vcpu->run);break ;case KVM_GET_REGS : {
@@ -2440,9 +2443,15 @@ static long kvm_dev_ioctl(struct file *filp,switch (ioctl) {case KVM_GET_API_VERSION : + r = -EINVAL ; +if (arg) + goto out; r =KVM_API_VERSION ;break ;case KVM_CREATE_VM : + r = -EINVAL ; +if (arg) + goto out; r =kvm_dev_ioctl_create_vm ();break ;case KVM_GET_MSR_INDEX_LIST : {
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 20/41 KVM: Avoid guest virtual addresses in string pio userspace interface
The current string pio interface communicates using guest virtual addresses, relying on userspace to translate addresses and to check permissions. This interface cannot fully support guest smp, as the check needs to take into account two pages at one in case an unaligned string transfer straddles a page boundary.
Change the interface not to communicate guest addresses at all; instead use a buffer page (mmaped by userspace) and do transfers there. The kernel manages the virtual to physical translation and can perform the checks atomically by taking the appropriate locks.
--- drivers/kvm/kvm.h | 21 ++++++- drivers/kvm/kvm_main.c | 174 +++++++++++++++++++++++++++++++++++++++++++---- drivers/kvm/mmu.c | 9 +++ drivers/kvm/svm.c | 40 +++++------ drivers/kvm/vmx.c | 40 ++++++------ include/linux/kvm.h | 11 +--- 6 files changed, 229 insertions(+), 66 deletions(-)
drivers/kvm/kvm.h +20 -1
@@ -74,6 +74,8 @@#define IOPL_SHIFT 12 +#define KVM_PIO_PAGE_OFFSET 1 +/* * Address types: *
@@ -220,6 +222,18 @@ enum { VCPU_SREG_LDTR, }; +struct kvm_pio_request { +unsigned long count; +int cur_count; +struct page *guest_pages[2 ]; +unsigned guest_page_offset; +int in; +int size; +int string; +int down; +int rep; +}; +struct kvm_vcpu {struct kvm *kvm;union {
@@ -275,7 +289,8 @@ struct kvm_vcpu {int mmio_size;unsigned char mmio_data[8 ];gpa_t mmio_phys_addr; -int pio_pending; +struct kvm_pio_request pio; +void *pio_data;int sigset_active;sigset_t sigset;
@@ -421,6 +436,7 @@ hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa);#define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)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 );
@@ -453,6 +469,9 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,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);void kvm_emulate_cpuid (struct kvm_vcpu *vcpu);int emulate_invlpg (struct kvm_vcpu *vcpu,gva_t address);int emulate_clts (struct kvm_vcpu *vcpu);
drivers/kvm/kvm_main.c +159 -15
258 lines not on this page · raw message
drivers/kvm/mmu.c +9 -0
@@ -735,6 +735,15 @@ hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva)return gpa_to_hpa (vcpu, gpa); } +struct page *gva_to_page (struct kvm_vcpu *vcpu,gva_t gva) +{ +gpa_t gpa = vcpu->mmu.gva_to_gpa (vcpu, gva); + +if (gpa ==UNMAPPED_GVA ) +return NULL ; +return pfn_to_page (gpa_to_hpa (vcpu, gpa) >>PAGE_SHIFT ); +} +static void nonpaging_new_cr3 (struct kvm_vcpu *vcpu) { }
drivers/kvm/svm.c +19 -21
@@ -984,7 +984,7 @@ static int io_get_override(struct kvm_vcpu *vcpu,return 0 ; } -static unsigned long io_adress (struct kvm_vcpu *vcpu,int ins,u64 *address) +static unsigned long io_adress (struct kvm_vcpu *vcpu,int ins,gva_t *address) {unsigned long addr_mask;unsigned long *reg;
@@ -1028,40 +1028,38 @@ static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address)static int io_interception (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) {u32 io_info = vcpu->svm->vmcb->control.exit_info_1;//address size bug? -int _in = io_info &SVM_IOIO_TYPE_MASK ; +int size, down, in, string, rep; +unsigned port; +unsigned long count; +gva_t address =0 ; ++kvm_stat.io_exits; vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2; - kvm_run->exit_reason =KVM_EXIT_IO ; - kvm_run->io.port = io_info >>16 ; - kvm_run->io.direction = (_in) ?KVM_EXIT_IO_IN :KVM_EXIT_IO_OUT ; - kvm_run->io.size = ((io_info &SVM_IOIO_SIZE_MASK ) >>SVM_IOIO_SIZE_SHIFT ); - kvm_run->io.string = (io_info &SVM_IOIO_STR_MASK ) !=0 ; - kvm_run->io.rep = (io_info &SVM_IOIO_REP_MASK ) !=0 ; - kvm_run->io.count =1 ; + in = (io_info &SVM_IOIO_TYPE_MASK ) !=0 ; + port = io_info >>16 ; + size = (io_info &SVM_IOIO_SIZE_MASK ) >>SVM_IOIO_SIZE_SHIFT ; + string = (io_info &SVM_IOIO_STR_MASK ) !=0 ; + rep = (io_info &SVM_IOIO_REP_MASK ) !=0 ; + count =1 ; + down = (vcpu->svm->vmcb->save.rflags &X86_EFLAGS_DF ) !=0 ; -if (kvm_run->io.string) { +if (string) {unsigned addr_mask; - addr_mask =io_adress (vcpu, _in, &kvm_run->io.address); + addr_mask =io_adress (vcpu, in, &address);if (!addr_mask) {printk (KERN_DEBUG "%s: get io address failed\n" , __FUNCTION__);return 1 ; } -if (kvm_run->io.rep) { - kvm_run->io.count - = vcpu->regs[VCPU_REGS_RCX ] & addr_mask; - kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags - &X86_EFLAGS_DF ) !=0 ; - } - }else - kvm_run->io.value = vcpu->svm->vmcb->save.rax; - vcpu->pio_pending =1 ; -return 0 ; +if (rep) + count = vcpu->regs[VCPU_REGS_RCX ] & addr_mask; + } +return kvm_setup_pio (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)
drivers/kvm/vmx.c +20 -20
@@ -1394,7 +1394,7 @@ static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)return 0 ; } -static int get_io_count (struct kvm_vcpu *vcpu,u64 *count) +static int get_io_count (struct kvm_vcpu *vcpu,unsigned long *count) {u64 inst;gva_t rip;
@@ -1439,35 +1439,35 @@ static int get_io_count(struct kvm_vcpu *vcpu, u64 *count) done: countr_size *=8 ; *count = vcpu->regs[VCPU_REGS_RCX ] & (~0ULL >> (64 - countr_size)); +//printk("cx: %lx\n", vcpu->regs[VCPU_REGS_RCX]); return 1 ; }static int handle_io (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) {u64 exit_qualification; +int size, down, in, string, rep; +unsigned port; +unsigned long count; +gva_t address; ++kvm_stat.io_exits; exit_qualification =vmcs_read64 (EXIT_QUALIFICATION ); - kvm_run->exit_reason =KVM_EXIT_IO ; -if (exit_qualification &8 ) - kvm_run->io.direction =KVM_EXIT_IO_IN ; -else - kvm_run->io.direction =KVM_EXIT_IO_OUT ; - kvm_run->io.size = (exit_qualification &7 ) +1 ; - kvm_run->io.string = (exit_qualification &16 ) !=0 ; - kvm_run->io.string_down - = (vmcs_readl (GUEST_RFLAGS ) &X86_EFLAGS_DF ) !=0 ; - kvm_run->io.rep = (exit_qualification &32 ) !=0 ; - kvm_run->io.port = exit_qualification >>16 ; - kvm_run->io.count =1 ; -if (kvm_run->io.string) { -if (!get_io_count (vcpu, &kvm_run->io.count)) + in = (exit_qualification &8 ) !=0 ; + size = (exit_qualification &7 ) +1 ; + string = (exit_qualification &16 ) !=0 ; + down = (vmcs_readl (GUEST_RFLAGS ) &X86_EFLAGS_DF ) !=0 ; + count =1 ; + rep = (exit_qualification &32 ) !=0 ; + port = exit_qualification >>16 ; + address =0 ; +if (string) { +if (rep && !get_io_count (vcpu, &count))return 1 ; - kvm_run->io.address =vmcs_readl (GUEST_LINEAR_ADDRESS ); - }else - kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX ];/* rax */ - vcpu->pio_pending =1 ; -return 0 ; + address =vmcs_readl (GUEST_LINEAR_ADDRESS ); + } +return kvm_setup_pio (vcpu, kvm_run, in, size, count, string, down, + address, rep, port); } static void
include/linux/kvm.h +2 -9
@@ -86,16 +86,9 @@ struct kvm_run {#define KVM_EXIT_IO_OUT 1__u8 direction;__u8 size;/* bytes */ -__u8 string; -__u8 string_down; -__u8 rep; -__u8 pad;__u16 port; -__u64 count; -union { -__u64 address; -__u32 value; - }; +__u32 count; +__u64 data_offset;/* relative to kvm_run start */ } io;struct { } debug;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 21/41 KVM: MMU: Remove unnecessary check for pdptr access
We already special case the pdptr access, so no need to check it again.
--- drivers/kvm/paging_tmpl.h | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/kvm/paging_tmpl.h +1 -2
@@ -148,8 +148,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker,break ; } -if (walker->level !=3 ||is_long_mode (vcpu)) - walker->inherited_ar &= walker->table[index]; + walker->inherited_ar &= walker->table[index]; table_gfn = (*ptep &PT_BASE_ADDR_MASK ) >>PAGE_SHIFT ; paddr =safe_gpa_to_hpa (vcpu, *ptep &PT_BASE_ADDR_MASK );kunmap_atomic (walker->table,KM_USER0 );
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 22/41 KVM: MMU: Remove global pte tracking
The initial, noncaching, version of the kvm mmu flushed the all nonglobal shadow page table translations (much like a native tlb flush). The new implementation flushes translations only when they change, rendering global pte tracking superfluous.
This removes the unused tracking mechanism and storage space.
--- drivers/kvm/kvm.h | 1 - drivers/kvm/mmu.c | 9 --------- 2 files changed, 0 insertions(+), 10 deletions(-)
drivers/kvm/kvm.h +0 -1
@@ -136,7 +136,6 @@ struct kvm_mmu_page {unsigned long slot_bitmap;/* One bit set per slot which has memory * in this shadow page. */ -int global;/* Set if all ptes in this page are global */ int multimapped;/* More than one parent_pte? */ int root_count;/* Currently serving as active root */ union {
drivers/kvm/mmu.c +0 -9
@@ -461,7 +461,6 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,list_add (&page->link, &vcpu->kvm->active_mmu_pages);ASSERT (is_empty_shadow_page (page->page_hpa)); page->slot_bitmap =0 ; - page->global =1 ; page->multimapped =0 ; page->parent_pte = parent_pte; --vcpu->kvm->n_free_mmu_pages;
@@ -927,11 +926,6 @@ static void paging_new_cr3(struct kvm_vcpu *vcpu) kvm_arch_ops->set_cr3 (vcpu, vcpu->mmu.root_hpa); } -static void mark_pagetable_nonglobal (void *shadow_pte) -{ -page_header (__pa (shadow_pte))->global =0 ; -} - static inline void set_pte_common(struct kvm_vcpu *vcpu, u64 *shadow_pte, gpa_t gaddr,
@@ -949,9 +943,6 @@ static inline void set_pte_common(struct kvm_vcpu *vcpu, *shadow_pte |= access_bits; -if (!(*shadow_pte &PT_GLOBAL_MASK )) -mark_pagetable_nonglobal (shadow_pte); -if (is_error_hpa (paddr)) { *shadow_pte |= gaddr; *shadow_pte |=PT_SHADOW_IO_MARK ;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 23/41 KVM: Workaround vmx inability to virtualize the reset state
The reset state has cs.selector == 0xf000 and cs.base == 0xffff0000, which aren't compatible with vm86 mode, which is used for real mode virtualization.
When we create a vcpu, we set cs.base to 0xf0000, but if we get there by way of a reset, the values are inconsistent and vmx refuses to enter guest mode.
Workaround by detecting the state and munging it appropriately.
--- drivers/kvm/vmx.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/kvm/vmx.c +2 -0
@@ -712,6 +712,8 @@ static void enter_rmode(struct kvm_vcpu *vcpu)vmcs_write32 (GUEST_CS_AR_BYTES ,0xf3 );vmcs_write32 (GUEST_CS_LIMIT ,0xffff ); +if (vmcs_readl (GUEST_CS_BASE ) ==0xffff0000 ) +vmcs_writel (GUEST_CS_BASE ,0xf0000 );vmcs_write16 (GUEST_CS_SELECTOR ,vmcs_readl (GUEST_CS_BASE ) >>4 );fix_rmode_seg (VCPU_SREG_ES , &vcpu->rmode.es);
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 24/41 KVM: Remove set_cr0_no_modeswitch() arch op
set_cr0_no_modeswitch() was a hack to avoid corrupting segment registers. As we now cache the protected mode values on entry to real mode, this isn't an issue anymore, and it interferes with reboot (which usually _is_ a modeswitch).
--- drivers/kvm/kvm.h | 2 -- drivers/kvm/kvm_main.c | 2 +- drivers/kvm/svm.c | 1 - drivers/kvm/vmx.c | 17 ----------------- 4 files changed, 1 insertions(+), 21 deletions(-)
drivers/kvm/kvm.h +0 -2
@@ -383,8 +383,6 @@ struct kvm_arch_ops {void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu,int *db,int *l);void (*decache_cr0_cr4_guest_bits)(struct kvm_vcpu *vcpu);void (*set_cr0)(struct kvm_vcpu *vcpu,unsigned long cr0); -void (*set_cr0_no_modeswitch)(struct kvm_vcpu *vcpu, -unsigned long cr0);void (*set_cr3)(struct kvm_vcpu *vcpu,unsigned long cr3);void (*set_cr4)(struct kvm_vcpu *vcpu,unsigned long cr4);void (*set_efer)(struct kvm_vcpu *vcpu,u64 efer);
drivers/kvm/kvm_main.c +1 -1
@@ -1927,7 +1927,7 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, kvm_arch_ops->decache_cr0_cr4_guest_bits (vcpu); mmu_reset_needed |= vcpu->cr0 != sregs->cr0; - kvm_arch_ops->set_cr0_no_modeswitch (vcpu, sregs->cr0); + kvm_arch_ops->set_cr0 (vcpu, sregs->cr0); mmu_reset_needed |= vcpu->cr4 != sregs->cr4; kvm_arch_ops->set_cr4 (vcpu, sregs->cr4);
drivers/kvm/svm.c +0 -1
@@ -1716,7 +1716,6 @@ static struct kvm_arch_ops svm_arch_ops = { .get_cs_db_l_bits = svm_get_cs_db_l_bits, .decache_cr0_cr4_guest_bits = svm_decache_cr0_cr4_guest_bits, .set_cr0 = svm_set_cr0, - .set_cr0_no_modeswitch = svm_set_cr0, .set_cr3 = svm_set_cr3, .set_cr4 = svm_set_cr4, .set_efer = svm_set_efer,
drivers/kvm/vmx.c +0 -17
@@ -788,22 +788,6 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) vcpu->cr0 = cr0; } -/* -* Used when restoring the VM to avoid corrupting segment registers -*/ -static void vmx_set_cr0_no_modeswitch (struct kvm_vcpu *vcpu,unsigned long cr0) -{ -if (!vcpu->rmode.active && !(cr0 &CR0_PE_MASK )) -enter_rmode (vcpu); - - vcpu->rmode.active = ((cr0 &CR0_PE_MASK ) ==0 ); -update_exception_bitmap (vcpu); -vmcs_writel (CR0_READ_SHADOW , cr0); -vmcs_writel (GUEST_CR0 , - (cr0 & ~KVM_GUEST_CR0_MASK ) |KVM_VM_CR0_ALWAYS_ON ); - vcpu->cr0 = cr0; -} -static void vmx_set_cr3 (struct kvm_vcpu *vcpu,unsigned long cr3) {vmcs_writel (GUEST_CR3 , cr3);
@@ -2069,7 +2053,6 @@ static struct kvm_arch_ops vmx_arch_ops = { .get_cs_db_l_bits = vmx_get_cs_db_l_bits, .decache_cr0_cr4_guest_bits = vmx_decache_cr0_cr4_guest_bits, .set_cr0 = vmx_set_cr0, - .set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch, .set_cr3 = vmx_set_cr3, .set_cr4 = vmx_set_cr4,#ifdef CONFIG_X86_64
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 25/41 KVM: Modify guest segments after potentially switching modes
The SET_SREGS ioctl modifies both cr0.pe (real mode/protected mode) and guest segment registers. Since segment handling is modified by the mode on Intel procesors, update the segment registers after the mode switch has taken place.
--- drivers/kvm/kvm_main.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-)
drivers/kvm/kvm_main.c +10 -10
@@ -1895,16 +1895,6 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,vcpu_load (vcpu); -set_segment (vcpu, &sregs->cs,VCPU_SREG_CS ); -set_segment (vcpu, &sregs->ds,VCPU_SREG_DS ); -set_segment (vcpu, &sregs->es,VCPU_SREG_ES ); -set_segment (vcpu, &sregs->fs,VCPU_SREG_FS ); -set_segment (vcpu, &sregs->gs,VCPU_SREG_GS ); -set_segment (vcpu, &sregs->ss,VCPU_SREG_SS ); - -set_segment (vcpu, &sregs->tr,VCPU_SREG_TR ); -set_segment (vcpu, &sregs->ldt,VCPU_SREG_LDTR ); - dt.limit = sregs->idt.limit; dt.base = sregs->idt.base; kvm_arch_ops->set_idt (vcpu, &dt);
@@ -1944,6 +1934,16 @@ static int kvm_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,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 ); +set_segment (vcpu, &sregs->es,VCPU_SREG_ES ); +set_segment (vcpu, &sregs->fs,VCPU_SREG_FS ); +set_segment (vcpu, &sregs->gs,VCPU_SREG_GS ); +set_segment (vcpu, &sregs->ss,VCPU_SREG_SS ); + +set_segment (vcpu, &sregs->tr,VCPU_SREG_TR ); +set_segment (vcpu, &sregs->ldt,VCPU_SREG_LDTR ); +vcpu_put (vcpu);return 0 ;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 26/41 KVM: Hack real-mode segments on vmx from KVM_SET_SREGS
As usual, we need to mangle segment registers when emulating real mode as vm86 has specific constraints. We special case the reset segment base, and set the "access rights" (or descriptor flags) to vm86 comaptible values.
This fixes reboot on vmx.
--- drivers/kvm/vmx.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/kvm/vmx.c +8 -1
@@ -864,7 +864,14 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,vmcs_writel (sf->base, var->base);vmcs_write32 (sf->limit, var->limit);vmcs_write16 (sf->selector, var->selector); -if (var->unusable) +if (vcpu->rmode.active && var->s) { +/* +* Hack real-mode segments into vm86 compatibility. +*/ +if (var->base ==0xffff0000 && var->selector ==0xf000 ) +vmcs_writel (sf->base,0xf0000 ); + ar =0xf3 ; + }else if (var->unusable) ar =1 <<16 ;else { ar = var->type &15 ;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 27/41 KVM: Don't allow the guest to turn off the cpu cache
The cpu cache is a host resource; the guest should not be able to turn it off (even for itself).
--- drivers/kvm/svm.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
drivers/kvm/svm.c +3 -1
@@ -737,8 +737,10 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) }#endif vcpu->svm->cr0 = cr0; - vcpu->svm->vmcb->save.cr0 = cr0 |CR0_PG_MASK |CR0_WP_MASK ; vcpu->cr0 = cr0; + cr0 |=CR0_PG_MASK |CR0_WP_MASK ; + cr0 &= ~(CR0_CD_MASK |CR0_NW_MASK ); + vcpu->svm->vmcb->save.cr0 = cr0; }static void svm_set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4)
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 28/41 KVM: Remove unused and write-only variables
Trivial cleanup.
--- drivers/kvm/kvm_svm.h | 2 -- drivers/kvm/svm.c | 2 -- 2 files changed, 0 insertions(+), 4 deletions(-)
drivers/kvm/kvm_svm.h +0 -2
@@ -28,8 +28,6 @@ struct vcpu_svm {struct svm_cpu_data *svm_data;uint64_t asid_generation; -unsigned long cr0; -unsigned long cr4;unsigned long db_regs[NUM_DB_REGS ];u64 next_rip;
drivers/kvm/svm.c +0 -2
@@ -576,7 +576,6 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu) vcpu->svm->vmcb =page_address (page);memset (vcpu->svm->vmcb,0 ,PAGE_SIZE ); vcpu->svm->vmcb_pa =page_to_pfn (page) <<PAGE_SHIFT ; - vcpu->svm->cr0 =0x00000010 ; vcpu->svm->asid_generation =0 ;memset (vcpu->svm->db_regs,0 ,sizeof (vcpu->svm->db_regs));init_vmcb (vcpu->svm->vmcb);
@@ -736,7 +735,6 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) } }#endif - vcpu->svm->cr0 = cr0; vcpu->cr0 = cr0; cr0 |=CR0_PG_MASK |CR0_WP_MASK ; cr0 &= ~(CR0_CD_MASK |CR0_NW_MASK );
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 29/41 KVM: Handle writes to MCG_STATUS msr
From: Sergey Kiselev <[email protected]>
Some older (~2.6.7) kernels write MCG_STATUS register during kernel boot (mce_clear_all() function, called from mce_init()). It's not currently handled by kvm and will cause it to inject a GPF. Following patch adds a "nop" handler for this.
--- drivers/kvm/kvm_main.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +4 -0
@@ -1467,6 +1467,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)printk (KERN_WARNING "%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" , + __FUNCTION__, data); +break ;case MSR_IA32_UCODE_REV :case MSR_IA32_UCODE_WRITE : case 0x200 ... 0x2ff: /* MTRRs */
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 30/41 KVM: SVM: forbid guest to execute monitor/mwait
From: Joerg Roedel <[email protected]>
This patch forbids the guest to execute monitor/mwait instructions on SVM. This is necessary because the guest can execute these instructions if they are available even if the kvm cpuid doesn't report its existence.
--- drivers/kvm/svm.c | 6 +++++- drivers/kvm/svm.h | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletions(-)
drivers/kvm/svm.c +5 -1
@@ -511,7 +511,9 @@ static void init_vmcb(struct vmcb *vmcb) (1ULL <<INTERCEPT_VMSAVE ) | (1ULL <<INTERCEPT_STGI ) | (1ULL <<INTERCEPT_CLGI ) | - (1ULL <<INTERCEPT_SKINIT ); + (1ULL <<INTERCEPT_SKINIT ) | + (1ULL <<INTERCEPT_MONITOR ) | + (1ULL <<INTERCEPT_MWAIT ); control->iopm_base_pa = iopm_base; control->msrpm_base_pa = msrpm_base;
@@ -1292,6 +1294,8 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, [SVM_EXIT_STGI] = invalid_op_interception, [SVM_EXIT_CLGI] = invalid_op_interception, [SVM_EXIT_SKINIT] = invalid_op_interception, + [SVM_EXIT_MONITOR] = invalid_op_interception, + [SVM_EXIT_MWAIT] = invalid_op_interception, };
drivers/kvm/svm.h +6 -0
@@ -44,6 +44,9 @@ enum {INTERCEPT_RDTSCP ,INTERCEPT_ICEBP ,INTERCEPT_WBINVD , +INTERCEPT_MONITOR , +INTERCEPT_MWAIT , + INTERCEPT_MWAIT_COND, };
@@ -298,6 +301,9 @@ struct __attribute__ ((__packed__)) vmcb {#define SVM_EXIT_RDTSCP 0x087#define SVM_EXIT_ICEBP 0x088#define SVM_EXIT_WBINVD 0x089 +#define SVM_EXIT_MONITOR 0x08a +#define SVM_EXIT_MWAIT 0x08b +#define SVM_EXIT_MWAIT_COND 0x08c#define SVM_EXIT_NPF 0x400#define SVM_EXIT_ERR -1
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 31/41 KVM: MMU: Fix hugepage pdes mapping same physical address with different access
The kvm mmu keeps a shadow page for hugepage pdes; if several such pdes map the same physical address, they share the same shadow page. This is a fairly common case (kernel mappings on i386 nonpae Linux, for example).
However, if the two pdes map the same memory but with different permissions, kvm will happily use the cached shadow page. If the access through the more permissive pde will occur after the access to the strict pde, an endless pagefault loop will be generated and the guest will make no progress.
Fix by making the access permissions part of the cache lookup key.
The fix allows Xen pae to boot on kvm and run guest domains.
Thanks to Jeremy Fitzhardinge for reporting the bug and testing the fix.
--- drivers/kvm/kvm.h | 2 ++ drivers/kvm/mmu.c | 8 +++++--- drivers/kvm/paging_tmpl.h | 7 ++++++- 3 files changed, 13 insertions(+), 4 deletions(-)
drivers/kvm/kvm.h +2 -0
@@ -109,6 +109,7 @@ struct kvm_pte_chain {* bits 4:7 - page table level for this shadow (1-4) * bits 8:9 - page table quadrant for 2-level guests * bit 16 - "metaphysical" - gfn is not a real page (huge page/real mode) +* bits 17:18 - "access" - the user and writable bits of a huge page pde */ union kvm_mmu_page_role {unsigned word;
@@ -118,6 +119,7 @@ union kvm_mmu_page_role { unsigned quadrant : 2; unsigned pad_for_nice_hex_output : 6; unsigned metaphysical : 1; + unsigned hugepage_access : 2; }; };
drivers/kvm/mmu.c +5 -3
@@ -568,6 +568,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,gva_t gaddr, unsigned level, int metaphysical, + unsigned hugepage_access, u64 *parent_pte) { union kvm_mmu_page_role role;
@@ -581,6 +582,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, role.glevels = vcpu->mmu.root_level; role.level = level; role.metaphysical = metaphysical; + role.hugepage_access = hugepage_access;if (vcpu->mmu.root_level <=PT32_ROOT_LEVEL ) { quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level)); quadrant &= (1 << ((PT32_PT_BITS -PT64_PT_BITS ) * level)) -1 ;
@@ -780,7 +782,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, hpa_t p) >> PAGE_SHIFT; new_table =kvm_mmu_get_page (vcpu, pseudo_gfn, v, level -1 , -1 , &table[index]); +1 ,0 , &table[index]);if (!new_table) {pgprintk ("nonpaging_map: ENOMEM\n" );return -ENOMEM ;
@@ -835,7 +837,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)ASSERT (!VALID_PAGE (root)); page =kvm_mmu_get_page (vcpu, root_gfn,0 , -PT64_ROOT_LEVEL ,0 ,NULL ); +PT64_ROOT_LEVEL ,0 ,0 ,NULL ); root = page->page_hpa; ++page->root_count; vcpu->mmu.root_hpa = root;
@@ -852,7 +854,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) root_gfn =0 ; page =kvm_mmu_get_page (vcpu, root_gfn, i <<30 ,PT32_ROOT_LEVEL , !is_paging (vcpu), -NULL ); +0 ,NULL ); root = page->page_hpa; ++page->root_count; vcpu->mmu.pae_root[i] = root |PT_PRESENT_MASK ;
drivers/kvm/paging_tmpl.h +6 -1
@@ -247,6 +247,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,u64 shadow_pte;int metaphysical;gfn_t table_gfn; +unsigned hugepage_access =0 ;if (is_present_pte (*shadow_ent) ||is_io_pte (*shadow_ent)) {if (level ==PT_PAGE_TABLE_LEVEL )
@@ -276,6 +277,9 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,if (level -1 ==PT_PAGE_TABLE_LEVEL && walker->level ==PT_DIRECTORY_LEVEL ) { metaphysical =1 ; + hugepage_access = *guest_ent; + hugepage_access &=PT_USER_MASK |PT_WRITABLE_MASK ; + hugepage_access >>=PT_WRITABLE_SHIFT ; table_gfn = (*guest_ent &PT_BASE_ADDR_MASK ) >>PAGE_SHIFT ; }else {
@@ -283,7 +287,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, table_gfn = walker->table_gfn[level -2 ]; } shadow_page =kvm_mmu_get_page (vcpu, table_gfn, addr, level-1 , - metaphysical, shadow_ent); + metaphysical, hugepage_access, + shadow_ent); shadow_addr = shadow_page->page_hpa; shadow_pte = shadow_addr |PT_PRESENT_MASK |PT_ACCESSED_MASK |PT_WRITABLE_MASK |PT_USER_MASK ;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 32/41 KVM: SVM: Ensure timestamp counter monotonicity
When a vcpu is migrated from one cpu to another, its timestamp counter may lose its monotonic property if the host has unsynced timestamp counters. This can confuse the guest, sometimes to the point of refusing to boot.
As the rdtsc instruction is rather fast on AMD processors (7-10 cycles), we can simply record the last host tsc when we drop the cpu, and adjust the vcpu tsc offset when we detect that we've migrated to a different cpu.
--- drivers/kvm/kvm.h | 1 + drivers/kvm/svm.c | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-)
drivers/kvm/kvm.h +1 -0
@@ -244,6 +244,7 @@ struct kvm_vcpu {struct mutex mutex;int cpu;int launched; +u64 host_tsc;struct kvm_run *run;int interrupt_window_open;unsigned long irq_summary;/* bit vector: 1 per word in irq_pending */
drivers/kvm/svm.c +17 -4
@@ -459,7 +459,6 @@ static void init_vmcb(struct vmcb *vmcb) {struct vmcb_control_area *control = &vmcb->control;struct vmcb_save_area *save = &vmcb->save; -u64 tsc; control->intercept_cr_read =INTERCEPT_CR0_MASK | INTERCEPT_CR3_MASK |
@@ -517,8 +516,7 @@ static void init_vmcb(struct vmcb *vmcb) control->iopm_base_pa = iopm_base; control->msrpm_base_pa = msrpm_base; -rdtscll (tsc); - control->tsc_offset = -tsc; + control->tsc_offset =0 ; control->int_ctl =V_INTR_MASKING_MASK ;init_seg (&save->es);
@@ -606,11 +604,26 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)static void svm_vcpu_load (struct kvm_vcpu *vcpu) { -get_cpu (); +int cpu; + + cpu =get_cpu (); +if (unlikely (cpu != vcpu->cpu)) { +u64 tsc_this, delta; + +/* +* Make sure that the guest sees a monotonically +* increasing TSC. +*/ +rdtscll (tsc_this); + delta = vcpu->host_tsc - tsc_this; + vcpu->svm->vmcb->control.tsc_offset += delta; + vcpu->cpu = cpu; + } }static void svm_vcpu_put (struct kvm_vcpu *vcpu) { +rdtscll (vcpu->host_tsc);put_cpu (); }
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 33/41 KVM: Remove unused function
From: Michal Piotrowski <[email protected]>
Remove unused function
CC drivers/kvm/svm.odrivers/kvm/svm.c:207: warning: ‘inject_db’ defined but not used
--- drivers/kvm/svm.c | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-)
drivers/kvm/svm.c +0 -7
@@ -203,13 +203,6 @@ static void inject_ud(struct kvm_vcpu *vcpu)UD_VECTOR ; } -static void inject_db (struct kvm_vcpu *vcpu) -{ - vcpu->svm->vmcb->control.event_inj =SVM_EVTINJ_VALID | -SVM_EVTINJ_TYPE_EXEPT | -DB_VECTOR ; -} -static int is_page_fault (uint32_t info) { info &=SVM_EVTINJ_VEC_MASK |SVM_EVTINJ_TYPE_MASK |SVM_EVTINJ_VALID ;
Signature · 12 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ kvm-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/kvm-devel
PATCH 34/41 KVM: Use list_move()
Use list_move() where possible. Noticed by Dor Laor.
--- drivers/kvm/mmu.c | 12 ++++-------- 1 files changed, 4 insertions(+), 8 deletions(-)
drivers/kvm/mmu.c +4 -8
@@ -437,9 +437,8 @@ static void kvm_mmu_free_page(struct kvm_vcpu *vcpu, hpa_t page_hpa)struct kvm_mmu_page *page_head =page_header (page_hpa);ASSERT (is_empty_shadow_page (page_hpa)); -list_del (&page_head->link); page_head->page_hpa = page_hpa; -list_add (&page_head->link, &vcpu->free_pages); +list_move (&page_head->link, &vcpu->free_pages); ++vcpu->kvm->n_free_mmu_pages; }
@@ -457,8 +456,7 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,return NULL ; page = list_entry(vcpu->free_pages.next, struct kvm_mmu_page, link); -list_del (&page->link); -list_add (&page->link, &vcpu->kvm->active_mmu_pages); +list_move (&page->link, &vcpu->kvm->active_mmu_pages);ASSERT (is_empty_shadow_page (page->page_hpa)); page->slot_bitmap =0 ; page->multimapped =0 ;
@@ -670,10 +668,8 @@ static void kvm_mmu_zap_page(struct kvm_vcpu *vcpu,if (!page->root_count) {hlist_del (&page->hash_link);kvm_mmu_free_page (vcpu, page->page_hpa); - }else { -list_del (&page->link); -list_add (&page->link, &vcpu->kvm->active_mmu_pages); - } + }else +list_move (&page->link, &vcpu->kvm->active_mmu_pages); }static int kvm_mmu_unprotect_page (struct kvm_vcpu *vcpu,gfn_t gfn)
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 35/41 KVM: Remove debug message
No longer interesting.
--- drivers/kvm/vmx.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/kvm/vmx.c +0 -1
@@ -1131,7 +1131,6 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu) vcpu->guest_msrs[j] = vcpu->host_msrs[j]; ++vcpu->nmsrs; } -printk (KERN_DEBUG "kvm: msrs: %d\n" , vcpu->nmsrs); nr_good_msrs = vcpu->nmsrs -NR_BAD_MSRS ; vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR,
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 36/41 KVM: x86 emulator: fix bit string operations operand size
On x86, bit operations operate on a string of bits that can reside in multiple words. For example, 'btsl %eax, (blah)' will touch the word at blah+4 if %eax is between 32 and 63.
The x86 emulator compensates for that by advancing the operand address by (bit offset / BITS_PER_LONG) and truncating the bit offset to the range (0..BITS_PER_LONG-1). This has a side effect of forcing the operand size to 8 bytes on 64-bit hosts.
Now, a 32-bit guest goes and fork()s a process. It write protects a stack page at 0xbffff000 using the 'btr' instruction, at offset 0xffc in the page table, with bit offset 1 (for the write permission bit).
The emulator now forces the operand size to 8 bytes as previously described, and an innocent page table update turns into a cross-page-boundary write, which is assumed by the mmu code not to be a page table, so it doesn't actually clear the corresponding shadow page table entry. The guest and host permissions are out of sync and guest memory is corrupted soon afterwards, leading to guest failure.
Fix by not using BITS_PER_LONG as the word size; instead use the actual operand size, so we get a 32-bit write in that case.
Note we still have to teach the mmu to handle cross-page-boundary writes to guest page table; but for now this allows Damn Small Linux 0.4 (2.4.20) to boot.
--- drivers/kvm/x86_emulate.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/kvm/x86_emulate.c +3 -2
@@ -833,8 +833,9 @@ done_prefixes: dst.ptr = (unsigned long *)cr2; dst.bytes = (d & ByteOp) ?1 : op_bytes;if (d & BitOp) { - dst.ptr += src.val /BITS_PER_LONG ; - dst.bytes =sizeof (long ); +unsigned long mask = ~(dst.bytes *8 -1 ); + + dst.ptr = (void *)dst.ptr + (src.val & mask) /8 ; } if (!(d & Mov) && /* optimisation - avoid slow emulated read */ ((rc = ops->read_emulated((unsigned long)dst.ptr,
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 37/41 KVM: Add mmu cache clear function
From: Dor Laor <dor.laor-atKUWr5tajBWk0Htik3J/[email protected]>
Functions that play around with the physical memory map need a way to clear mappings to possibly nonexistent or invalid memory. Both the mmu cache and the processor tlb are cleared.
--- drivers/kvm/kvm.h | 1 + drivers/kvm/mmu.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 0 deletions(-)
drivers/kvm/kvm.h +1 -0
@@ -430,6 +430,7 @@ int kvm_mmu_setup(struct kvm_vcpu *vcpu);int kvm_mmu_reset_context (struct kvm_vcpu *vcpu);void kvm_mmu_slot_remove_write_access (struct kvm_vcpu *vcpu,int slot); +void kvm_mmu_zap_all (struct kvm_vcpu *vcpu);hpa_t gpa_to_hpa (struct kvm_vcpu *vcpu,gpa_t gpa);#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
drivers/kvm/mmu.c +17 -0
@@ -1313,6 +1313,23 @@ void kvm_mmu_slot_remove_write_access(struct kvm_vcpu *vcpu, int slot) } } +void kvm_mmu_zap_all (struct kvm_vcpu *vcpu) +{ +destroy_kvm_mmu (vcpu); + +while (!list_empty (&vcpu->kvm->active_mmu_pages)) { +struct kvm_mmu_page *page; + + page =container_of (vcpu->kvm->active_mmu_pages.next, + struct kvm_mmu_page, link); +kvm_mmu_zap_page (vcpu, page); + } + +mmu_free_memory_caches (vcpu); + kvm_arch_ops->tlb_flush (vcpu); +init_kvm_mmu (vcpu); +} +#ifdef AUDIT static const char *audit_msg;
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 38/41 KVM: Simply gfn_to_page()
Mapping a guest page to a host page is a common operation. Currently, one has first to find the memory slot where the page belongs (gfn_to_memslot), then locate the page itself (gfn_to_page()).
This is clumsy, and also won't work well with memory aliases. So simplify gfn_to_page() not to require memory slot translation first, and instead do it internally.
--- drivers/kvm/kvm.h | 12 +----------- drivers/kvm/kvm_main.c | 45 +++++++++++++++++++++++++-------------------- drivers/kvm/mmu.c | 12 ++++-------- drivers/kvm/vmx.c | 6 +++--- 4 files changed, 33 insertions(+), 42 deletions(-)
drivers/kvm/kvm.h +1 -11
@@ -443,11 +443,7 @@ void kvm_emulator_want_group7_invlpg(void);extern hpa_t bad_page_address; -static inline struct page *gfn_to_page (struct kvm_memory_slot *slot,gfn_t gfn) -{ -return slot->phys_mem[gfn - slot->base_gfn]; -} - +struct page *gfn_to_page (struct kvm *kvm,gfn_t gfn);struct kvm_memory_slot *gfn_to_memslot (struct kvm *kvm,gfn_t gfn);void mark_page_dirty (struct kvm *kvm,gfn_t gfn);
@@ -523,12 +519,6 @@ static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva,return vcpu->mmu.page_fault (vcpu, gva, error_code); } -static inline struct page *_gfn_to_page (struct kvm *kvm,gfn_t gfn) -{ -struct kvm_memory_slot *slot =gfn_to_memslot (kvm, gfn); -return (slot) ? slot->phys_mem[gfn - slot->base_gfn] :NULL ; -} -static inline int is_long_mode (struct kvm_vcpu *vcpu) {#ifdef CONFIG_X86_64
drivers/kvm/kvm_main.c +25 -20
94 lines not on this page · raw message
drivers/kvm/mmu.c +4 -8
@@ -390,13 +390,11 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn) {struct kvm *kvm = vcpu->kvm;struct page *page; -struct kvm_memory_slot *slot;struct kvm_rmap_desc *desc;u64 *spte; - slot =gfn_to_memslot (kvm, gfn); -BUG_ON (!slot); - page =gfn_to_page (slot, gfn); + page =gfn_to_page (kvm, gfn); +BUG_ON (!page);while (page_private (page)) {if (!(page_private (page) &1 ))
@@ -711,14 +709,12 @@ hpa_t safe_gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa)hpa_t gpa_to_hpa (struct kvm_vcpu *vcpu,gpa_t gpa) { -struct kvm_memory_slot *slot;struct page *page;ASSERT ((gpa &HPA_ERR_MASK ) ==0 ); - slot =gfn_to_memslot (vcpu->kvm, gpa >>PAGE_SHIFT ); -if (!slot) + page =gfn_to_page (vcpu->kvm, gpa >>PAGE_SHIFT ); +if (!page)return gpa |HPA_ERR_MASK ; - page =gfn_to_page (slot, gpa >>PAGE_SHIFT );return ((hpa_t )page_to_pfn (page) <<PAGE_SHIFT ) | (gpa & (PAGE_SIZE -1 )); }
drivers/kvm/vmx.c +3 -3
@@ -926,9 +926,9 @@ static int init_rmode_tss(struct kvm* kvm)gfn_t fn =rmode_tss_base (kvm) >>PAGE_SHIFT ;char *page; - p1 =_gfn_to_page (kvm, fn++); - p2 =_gfn_to_page (kvm, fn++); - p3 =_gfn_to_page (kvm, fn); + p1 =gfn_to_page (kvm, fn++); + p2 =gfn_to_page (kvm, fn++); + p3 =gfn_to_page (kvm, fn);if (!p1 || !p2 || !p3) {kvm_printf (kvm,"%s: gfn_to_page failed\n" , __FUNCTION__);
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 39/41 KVM: Add physical memory aliasing feature
With this, we can specify that accesses to one physical memory range will be remapped to another. This is useful for the vga window at 0xa0000 which is used as a movable window into the (much larger) framebuffer.
--- drivers/kvm/kvm.h | 9 +++++ drivers/kvm/kvm_main.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/kvm.h | 10 +++++- 3 files changed, 104 insertions(+), 4 deletions(-)
drivers/kvm/kvm.h +9 -0
@@ -51,6 +51,7 @@#define UNMAPPED_GVA (~(gpa_t)0)#define KVM_MAX_VCPUS 1 +#define KVM_ALIAS_SLOTS 4#define KVM_MEMORY_SLOTS 4#define KVM_NUM_MMU_PAGES 256#define KVM_MIN_FREE_MMU_PAGES 5
@@ -312,6 +313,12 @@ struct kvm_vcpu {struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES ]; }; +struct kvm_mem_alias { +gfn_t base_gfn; +unsigned long npages; +gfn_t target_gfn; +}; +struct kvm_memory_slot {gfn_t base_gfn;unsigned long npages;
@@ -322,6 +329,8 @@ struct kvm_memory_slot {struct kvm {spinlock_t lock;/* protects everything except vcpus */ +int naliases; +struct kvm_mem_alias aliases[KVM_ALIAS_SLOTS ];int nmemslots;struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS ];/*
drivers/kvm/kvm_main.c +86 -3
112 lines not on this page · raw message
include/linux/kvm.h +9 -1
@@ -11,7 +11,7 @@#include <asm/types.h> #include <linux/ioctl.h> -#define KVM_API_VERSION 9 +#define KVM_API_VERSION 10/* * Architectural interrupt line count, and the size of the bitmap needed
@@ -33,6 +33,13 @@ struct kvm_memory_region {/* for kvm_memory_region::flags */ #define KVM_MEM_LOG_DIRTY_PAGES 1UL +struct kvm_memory_alias { +__u32 slot;/* this has a different namespace than memory slots */ +__u32 flags; +__u64 guest_phys_addr; +__u64 memory_size; +__u64 target_phys_addr; +};enum kvm_exit_reason {KVM_EXIT_UNKNOWN =0 ,
@@ -261,6 +268,7 @@ 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)/* * ioctls for vcpu fds
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 40/41 KVM: Add fpu get/set operations
These are really helpful when migrating an floating point app to another machine.
--- drivers/kvm/kvm_main.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/kvm.h | 17 +++++++++ 2 files changed, 103 insertions(+), 0 deletions(-)
drivers/kvm/kvm_main.c +86 -0
@@ -2389,6 +2389,67 @@ static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)return 0 ; } +/* +* fxsave fpu state. Taken from x86_64/processor.h. To be killed when +* we have asm/x86/processor.h +*/ +struct fxsave { +u16 cwd; +u16 swd; +u16 twd; +u16 fop; +u64 rip; +u64 rdp; +u32 mxcsr; +u32 mxcsr_mask; +u32 st_space[32 ];/* 8*16 bytes for each FP-reg = 128 bytes */ +#ifdef CONFIG_X86_64 +u32 xmm_space[64 ];/* 16*16 bytes for each XMM-reg = 256 bytes */ +#else +u32 xmm_space[32 ];/* 8*16 bytes for each XMM-reg = 128 bytes */ +#endif +}; + +static int kvm_vcpu_ioctl_get_fpu (struct kvm_vcpu *vcpu,struct kvm_fpu *fpu) +{ +struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image; + +vcpu_load (vcpu); + +memcpy (fpu->fpr, fxsave->st_space,128 ); + fpu->fcw = fxsave->cwd; + fpu->fsw = fxsave->swd; + fpu->ftwx = fxsave->twd; + fpu->last_opcode = fxsave->fop; + fpu->last_ip = fxsave->rip; + fpu->last_dp = fxsave->rdp; +memcpy (fpu->xmm, fxsave->xmm_space,sizeof fxsave->xmm_space); + +vcpu_put (vcpu); + +return 0 ; +} + +static int kvm_vcpu_ioctl_set_fpu (struct kvm_vcpu *vcpu,struct kvm_fpu *fpu) +{ +struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image; + +vcpu_load (vcpu); + +memcpy (fxsave->st_space, fpu->fpr,128 ); + fxsave->cwd = fpu->fcw; + fxsave->swd = fpu->fsw; + fxsave->twd = fpu->ftwx; + fxsave->fop = fpu->last_opcode; + fxsave->rip = fpu->last_ip; + fxsave->rdp = fpu->last_dp; +memcpy (fxsave->xmm_space, fpu->xmm,sizeof fxsave->xmm_space); + +vcpu_put (vcpu); + +return 0 ; +} +static long kvm_vcpu_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg) {
@@ -2533,6 +2594,31 @@ static long kvm_vcpu_ioctl(struct file *filp, r =kvm_vcpu_ioctl_set_sigmask (vcpu, &sigset);break ; } +case KVM_GET_FPU : { +struct kvm_fpu fpu; + +memset (&fpu,0 ,sizeof fpu); + r =kvm_vcpu_ioctl_get_fpu (vcpu, &fpu); +if (r) + goto out; + r = -EFAULT ; +if (copy_to_user (argp, &fpu,sizeof fpu)) + goto out; + r =0 ; +break ; + } +case KVM_SET_FPU : { +struct kvm_fpu fpu; + + r = -EFAULT ; +if (copy_from_user (&fpu, argp,sizeof fpu)) + goto out; + r =kvm_vcpu_ioctl_set_fpu (vcpu, &fpu); +if (r) + goto out; + r =0 ; +break ; + }default : ; }
include/linux/kvm.h +17 -0
@@ -126,6 +126,21 @@ struct kvm_regs {__u64 rip, rflags; }; +/* for KVM_GET_FPU and KVM_SET_FPU */ +struct kvm_fpu { +__u8 fpr[8 ][16 ]; +__u16 fcw; +__u16 fsw; +__u8 ftwx;/* in fxsave format */ +__u8 pad1; +__u16 last_opcode; +__u64 last_ip; +__u64 last_dp; +__u8 xmm[16 ][16 ]; +__u32 mxcsr; +__u32 pad2; +}; +struct kvm_segment {__u64 base;__u32 limit;
@@ -285,5 +300,7 @@ struct kvm_signal_mask {#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)#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)#endif
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 41/41 KVM: SVM: enable LBRV virtualization if available
From: Joerg Roedel <[email protected]>
This patch enables the virtualization of the last branch record MSRs on SVM if this feature is available in hardware. It also introduces a small and simple check feature for specific SVM extensions.
--- drivers/kvm/svm.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
drivers/kvm/svm.c +13 -0
@@ -44,6 +44,10 @@ MODULE_LICENSE("GPL");#define KVM_EFER_LMA (1 << 10)#define KVM_EFER_LME (1 << 8) +#define SVM_FEATURE_NPT (1 << 0) +#define SVM_FEATURE_LBRV (1 << 1) +#define SVM_DEATURE_SVML (1 << 2) +unsigned long iopm_base;unsigned long msrpm_base;
@@ -68,6 +72,7 @@ struct svm_cpu_data { }; static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data); +static uint32_t svm_features;struct svm_init_data {int cpu;
@@ -82,6 +87,11 @@ static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};#define MAX_INST_SIZE 15 +static inline u32 svm_has (u32 feat) +{ +return svm_features & feat; +} +static unsigned get_addr_size (struct kvm_vcpu *vcpu) {struct vmcb_save_area *sa = &vcpu->svm->vmcb->save;
@@ -302,6 +312,7 @@ static void svm_hardware_enable(void *garbage) svm_data->asid_generation =1 ; svm_data->max_asid =cpuid_ebx (SVM_CPUID_FUNC ) -1 ; svm_data->next_asid = svm_data->max_asid +1 ; + svm_features =cpuid_edx (SVM_CPUID_FUNC ); asmvolatile ("sgdt %0" :"=m" (gdt_descr) ); gdt = (struct desc_struct *)gdt_descr.address;
@@ -511,6 +522,8 @@ static void init_vmcb(struct vmcb *vmcb) control->msrpm_base_pa = msrpm_base; control->tsc_offset =0 ; control->int_ctl =V_INTR_MASKING_MASK ; +if (svm_has (SVM_FEATURE_LBRV )) + control->lbr_ctl =1ULL ;init_seg (&save->es);init_seg (&save->ss);
Signature · 8 lines
1.5.0.5 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV