KVM updates for 2.6.32 merge window (1/4)
cover KVM updates for 2.6.32 merge window (1/4)
Here is the first of four batches containing the KVM changes for 2.6.32. The 2.6.32 cycle will see scalability improvements, support for new hardware features, improvements in nested svm support, and eventfd-based infrastructure for connecting kvm guests to components in the host kernel, host userspace, and other guests. Also of note is conversion to the new trace infrastructure and x2apic emulation.
Andre Przywara (1):
KVM: SVM: use explicit 64bit storage for sysenter values
Avi Kivity (14):
KVM: x86 emulator: Implement zero-extended immediate decoding
KVM: x86 emulator: fix jmp far decoding (opcode 0xea)
KVM: Move common KVM Kconfig items to new file virt/kvm/Kconfig
KVM: SVM: Fold kvm_svm.h info svm.c
KVM: VMX: Avoid duplicate ept tlb flush when setting cr3
KVM: VMX: Simplify pdptr and cr3 management
KVM: Cache pdptrs
KVM: VMX: Fix reporting of unhandled EPT violations
KVM: Calculate available entries in coalesced mmio ring
KVM: Reorder ioctls in kvm.h
KVM: VMX: Move rmode structure to vmx-specific code
KVM: MMU: Fix is_dirty_pte()
KVM: MMU: Adjust pte accessors to explicitly indicate guest or shadow
pte
KVM: MMU: s/shadow_pte/spte/
Christian Ehrhardt (4):
KVM: s390: infrastructure to kick vcpus out of guest state
KVM: s390: fix signal handling
KVM: s390: streamline memslot handling
KVM: remove redundant declarations
Christoph Hellwig (1):
KVM: cleanup arch/x86/kvm/Makefile
Gleb Natapov (6):
KVM: VMX: Properly handle software interrupt re-injection in real
mode
KVM: Drop interrupt shadow when single stepping should be done only
on VMX
KVM: Introduce kvm_vcpu_is_bsp() function.
KVM: Use pointer to vcpu instead of vcpu_id in timer code.
KVM: Break dependency between vcpu index in vcpus array and vcpu_id.
KVM: Use macro to iterate over vcpus.
Gregory Haskins (4):
KVM: irqfd
KVM: Clean up coalesced_mmio destruction
KVM: cleanup io_device code
KVM: do not register i8254 PIO regions until we are initialized
Huang Ying (1):
KVM: Add MCE support
Jan Kiszka (2):
KVM: Allow PIT emulation without speaker port
KVM: Cleanup LAPIC interface
Jaswinder Singh Rajput (2):
KVM: Replace MSR_IA32_TIME_STAMP_COUNTER with MSR_IA32_TSC of
msr-index.h
KVM: Use MSR names in place of address
Jes Sorensen (1):
KVM: ia64: Correct itc_offset calculations
Liu Yu (3):
KVM: ppc: e500: Move to Book-3e MMU definitions
KVM: ppc: e500: Directly pass pvr to guest
KVM: ppc: e500: Add MMUCFG and PVR emulation
Marcelo Tosatti (4):
KVM: Grab pic lock in kvm_pic_clear_isr_ack
KVM: move coalesced_mmio locking to its own device
KVM: introduce irq_lock, use it to protect ioapic
KVM: switch irq injection/acking data structures to irq_lock
Mark McLoughlin (1):
KVM: fix cpuid E2BIG handling for extended request types
Nitin A Kamble (1):
KVM: VMX: Support Unrestricted Guest feature
Sheng Yang (2):
KVM: Downsize max support MSI-X entry to 256
KVM: No disable_irq for MSI/MSI-X interrupt on device assignment
Stephen Rothwell (1):
KVM: powerpc: fix some init/exit annotations
arch/ia64/include/asm/kvm_host.h | 1 - arch/ia64/kvm/Kconfig | 8 +- arch/ia64/kvm/kvm-ia64.c | 41 ++--- arch/ia64/kvm/vcpu.c | 4 +- arch/powerpc/include/asm/kvm_host.h | 1 - arch/powerpc/kvm/44x.c | 4 +- arch/powerpc/kvm/Kconfig | 3 +- arch/powerpc/kvm/booke.c | 2 +- arch/powerpc/kvm/e500.c | 7 +- arch/powerpc/kvm/e500_emulate.c | 3 + arch/powerpc/kvm/e500_tlb.c | 10 +- arch/powerpc/kvm/e500_tlb.h | 6 +- arch/powerpc/kvm/emulate.c | 4 +- arch/powerpc/kvm/powerpc.c | 16 +- arch/s390/include/asm/kvm_host.h | 9 +- arch/s390/kvm/Kconfig | 6 +- arch/s390/kvm/gaccess.h | 23 ++-- arch/s390/kvm/intercept.c | 18 ++- arch/s390/kvm/kvm-s390.c | 80 ++++----- arch/s390/kvm/kvm-s390.h | 32 ++++- arch/s390/kvm/sigp.c | 60 ++++--- arch/x86/include/asm/kvm.h | 1 + arch/x86/include/asm/kvm_host.h | 33 ++-- arch/x86/include/asm/vmx.h | 1 + arch/x86/kvm/Kconfig | 9 +- arch/x86/kvm/Makefile | 32 ++-- arch/x86/kvm/i8254.c | 70 +++++--- arch/x86/kvm/i8254.h | 2 +- arch/x86/kvm/i8259.c | 28 ++- arch/x86/kvm/kvm_cache_regs.h | 9 + arch/x86/kvm/kvm_svm.h | 51 ------ arch/x86/kvm/kvm_timer.h | 2 +- arch/x86/kvm/lapic.c | 47 +++--- arch/x86/kvm/mmu.c | 127 +++++++------- arch/x86/kvm/mmu.h | 2 +- arch/x86/kvm/paging_tmpl.h | 40 ++-- arch/x86/kvm/svm.c | 86 ++++++++-- arch/x86/kvm/timer.c | 2 +- arch/x86/kvm/vmx.c | 210 ++++++++++++++++------- arch/x86/kvm/x86.c | 305 ++++++++++++++++++++++++++------ arch/x86/kvm/x86_emulate.c | 17 ++- include/linux/kvm.h | 57 ++++++- include/linux/kvm_host.h | 54 ++++++- virt/kvm/Kconfig | 14 ++ virt/kvm/coalesced_mmio.c | 44 +++-- virt/kvm/coalesced_mmio.h | 1 + virt/kvm/eventfd.c | 329 +++++++++++++++++++++++++++++++++++ virt/kvm/ioapic.c | 31 +++- virt/kvm/iodev.h | 29 ++- virt/kvm/irq_comm.c | 40 ++++- virt/kvm/kvm_main.c | 130 ++++++++------ 51 files changed, 1502 insertions(+), 639 deletions(-) delete mode 100644 arch/x86/kvm/kvm_svm.h create mode 100644 virt/kvm/Kconfig create mode 100644 virt/kvm/eventfd.c
PATCH 1/48 KVM: VMX: Properly handle software interrupt re-injection in real mode
From: Gleb Natapov <[email protected]>
When reinjecting a software interrupt or exception, use the correct instruction length provided by the hardware instead of a hardcoded 1.
Fixes problems running the suse 9.1 livecd boot loader.
Problem introduced by commit f0a3602c20 ("KVM: Move interrupt injection logic to x86.c").
--- arch/x86/kvm/vmx.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
arch/x86/kvm/vmx.c +6 -2
@@ -801,8 +801,9 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, vmx->rmode.irq.pending = true; vmx->rmode.irq.vector = nr; vmx->rmode.irq.rip =kvm_rip_read (vcpu); -if (nr ==BP_VECTOR || nr ==OF_VECTOR ) - vmx->rmode.irq.rip++; +if (kvm_exception_is_soft (nr)) + vmx->rmode.irq.rip += + vmx->vcpu.arch.event_exit_inst_len; intr_info |=INTR_TYPE_SOFT_INTR ;vmcs_write32 (VM_ENTRY_INTR_INFO_FIELD , intr_info);vmcs_write32 (VM_ENTRY_INSTRUCTION_LEN ,1 );
@@ -2468,6 +2469,9 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu) vmx->rmode.irq.pending = true; vmx->rmode.irq.vector = irq; vmx->rmode.irq.rip =kvm_rip_read (vcpu); +if (vcpu->arch.interrupt.soft) + vmx->rmode.irq.rip += + vmx->vcpu.arch.event_exit_inst_len;vmcs_write32 (VM_ENTRY_INTR_INFO_FIELD , irq |INTR_TYPE_SOFT_INTR |INTR_INFO_VALID_MASK );vmcs_write32 (VM_ENTRY_INSTRUCTION_LEN ,1 );
Signature · 1 line
1.6.3.3
PATCH 2/48 KVM: Replace MSR_IA32_TIME_STAMP_COUNTER with MSR_IA32_TSC of msr-index.h
In reply to Avi KivityFrom: Jaswinder Singh Rajput <[email protected]>
Use standard msr-index.h's MSR declaration.
MSR_IA32_TSC is better than MSR_IA32_TIME_STAMP_COUNTER as it also solves 80 column issue.
--- arch/x86/include/asm/kvm_host.h | 2 -- arch/x86/kvm/svm.c | 4 ++-- arch/x86/kvm/vmx.c | 4 ++-- arch/x86/kvm/x86.c | 5 ++--- 4 files changed, 6 insertions(+), 9 deletions(-)
arch/x86/include/asm/kvm_host.h +0 -2
@@ -752,8 +752,6 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)kvm_queue_exception_e (vcpu,GP_VECTOR , error_code); } -#define MSR_IA32_TIME_STAMP_COUNTER 0x010 -#define TSS_IOPB_BASE_OFFSET 0x66#define TSS_BASE_SIZE 0x68#define TSS_IOPB_SIZE (65536 / 8)
arch/x86/kvm/svm.c +2 -2
@@ -1953,7 +1953,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)struct vcpu_svm *svm =to_svm (vcpu);switch (ecx) { -case MSR_IA32_TIME_STAMP_COUNTER : { +case MSR_IA32_TSC : {u64 tsc;rdtscll (tsc);
@@ -2043,7 +2043,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)struct vcpu_svm *svm =to_svm (vcpu);switch (ecx) { -case MSR_IA32_TIME_STAMP_COUNTER : { +case MSR_IA32_TSC : {u64 tsc;rdtscll (tsc);
arch/x86/kvm/vmx.c +2 -2
@@ -941,7 +941,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)case MSR_EFER :return kvm_get_msr_common (vcpu, msr_index, pdata);#endif -case MSR_IA32_TIME_STAMP_COUNTER : +case MSR_IA32_TSC : data =guest_read_tsc ();break ;case MSR_IA32_SYSENTER_CS :
@@ -1001,7 +1001,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)case MSR_IA32_SYSENTER_ESP :vmcs_writel (GUEST_SYSENTER_ESP , data);break ; -case MSR_IA32_TIME_STAMP_COUNTER : +case MSR_IA32_TSC :rdtscll (host_tsc);guest_write_tsc (data, host_tsc);break ;
arch/x86/kvm/x86.c +2 -3
@@ -466,7 +466,7 @@ static u32 msrs_to_save[] = {#ifdef CONFIG_X86_64 MSR_CSTAR ,MSR_KERNEL_GS_BASE ,MSR_SYSCALL_MASK ,MSR_LSTAR , #endif -MSR_IA32_TIME_STAMP_COUNTER ,MSR_KVM_SYSTEM_TIME ,MSR_KVM_WALL_CLOCK , +MSR_IA32_TSC ,MSR_KVM_SYSTEM_TIME ,MSR_KVM_WALL_CLOCK ,MSR_IA32_PERF_STATUS ,MSR_IA32_CR_PAT ,MSR_VM_HSAVE_PA };
@@ -644,8 +644,7 @@ static void kvm_write_guest_time(struct kvm_vcpu *v)/* Keep irq disabled to prevent changes to the clock */ local_irq_save (flags); -kvm_get_msr (v,MSR_IA32_TIME_STAMP_COUNTER , - &vcpu->hv_clock.tsc_timestamp); +kvm_get_msr (v,MSR_IA32_TSC , &vcpu->hv_clock.tsc_timestamp);ktime_get_ts (&ts);local_irq_restore (flags);
Signature · 1 line
1.6.3.3
PATCH 3/48 KVM: Add MCE support
In reply to Avi KivityFrom: Huang Ying <[email protected]>
The related MSRs are emulated. MCE capability is exported via extension KVM_CAP_MCE and ioctl KVM_X86_GET_MCE_CAP_SUPPORTED. A new vcpu ioctl command KVM_X86_SETUP_MCE is used to setup MCE emulation such as the mcg_cap. MCE is injected via vcpu ioctl command KVM_X86_SET_MCE. Extended machine-check state (MCG_EXT_P) and CMCI are not implemented.
--- arch/x86/include/asm/kvm.h | 1 + arch/x86/include/asm/kvm_host.h | 5 + arch/x86/kvm/x86.c | 220 ++++++++++++++++++++++++++++++++++---- include/linux/kvm.h | 20 ++++ 4 files changed, 222 insertions(+), 24 deletions(-)
arch/x86/include/asm/kvm.h +1 -0
@@ -17,6 +17,7 @@#define __KVM_HAVE_USER_NMI#define __KVM_HAVE_GUEST_DEBUG#define __KVM_HAVE_MSIX +#define __KVM_HAVE_MCE/* Architectural interrupt line count. */ #define KVM_NR_INTERRUPTS 256
arch/x86/include/asm/kvm_host.h +5 -0
@@ -373,6 +373,11 @@ struct kvm_vcpu_arch {unsigned long dr6;unsigned long dr7;unsigned long eff_db[KVM_NR_DB_REGS ]; + +u64 mcg_cap; +u64 mcg_status; +u64 mcg_ctl; +u64 *mce_banks; };struct kvm_mem_alias {
arch/x86/kvm/x86.c +196 -24
299 lines not on this page · raw message
include/linux/kvm.h +20 -0
@@ -415,6 +415,9 @@ struct kvm_trace_rec {#define KVM_CAP_ASSIGN_DEV_IRQ 29/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */ #define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30 +#ifdef __KVM_HAVE_MCE +#define KVM_CAP_MCE 31 +#endif #ifdef KVM_CAP_IRQ_ROUTING
@@ -454,6 +457,19 @@ struct kvm_irq_routing {#endif +#ifdef KVM_CAP_MCE +/* x86 MCE */ +struct kvm_x86_mce { +__u64 status; +__u64 addr; +__u64 misc; +__u64 mcg_status; +__u8 bank; +__u8 pad1[7 ]; +__u64 pad2[3 ]; +}; +#endif +/* * ioctls for VM fds */
@@ -541,6 +557,10 @@ struct kvm_irq_routing {#define KVM_NMI _IO(KVMIO, 0x9a)/* Available with KVM_CAP_SET_GUEST_DEBUG */ #define KVM_SET_GUEST_DEBUG _IOW(KVMIO, 0x9b, struct kvm_guest_debug) +/* MCE for x86 */ +#define KVM_X86_SETUP_MCE _IOW(KVMIO, 0x9c, __u64) +#define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO, 0x9d, __u64) +#define KVM_X86_SET_MCE _IOW(KVMIO, 0x9e, struct kvm_x86_mce)/* * Deprecated interfaces
Signature · 1 line
1.6.3.3
PATCH 4/48 KVM: Use MSR names in place of address
In reply to Avi KivityFrom: Jaswinder Singh Rajput <[email protected]>
Replace 0xc0010010 with MSR_K8_SYSCFG and 0xc0010015 with MSR_K7_HWCR.
--- arch/x86/kvm/x86.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +2 -2
@@ -973,8 +973,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)u64 data;switch (msr) { -case 0xc0010010 :/* SYSCFG */ -case 0xc0010015 :/* HWCR */ case MSR_IA32_PLATFORM_ID :case MSR_IA32_UCODE_REV :case MSR_IA32_EBL_CR_POWERON :
@@ -983,6 +981,8 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)case MSR_IA32_LASTBRANCHTOIP :case MSR_IA32_LASTINTFROMIP :case MSR_IA32_LASTINTTOIP : +case MSR_K8_SYSCFG : +case MSR_K7_HWCR :case MSR_VM_HSAVE_PA :case MSR_P6_EVNTSEL0 :case MSR_P6_EVNTSEL1 :
Signature · 1 line
1.6.3.3
PATCH 5/48 KVM: fix cpuid E2BIG handling for extended request types
In reply to Avi KivityFrom: Mark McLoughlin <[email protected]>
If we run out of cpuid entries for extended request types we should return -E2BIG, just like we do for the standard request types.
--- arch/x86/kvm/x86.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
arch/x86/kvm/x86.c +4 -0
@@ -1506,6 +1506,10 @@ static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,for (func =0x80000001 ; func <= limit && nent < cpuid->nent; ++func)do_cpuid_ent (&cpuid_entries[nent], func,0 , &nent, cpuid->nent); + r = -E2BIG ; +if (nent >= cpuid->nent) + goto out_free; + r = -EFAULT ;if (copy_to_user (entries, cpuid_entries, nent *sizeof (struct kvm_cpuid_entry2 )))
Signature · 1 line
1.6.3.3
PATCH 6/48 KVM: x86 emulator: Implement zero-extended immediate decoding
In reply to Avi KivityAbsolute jumps use zero extended immediate operands.
--- arch/x86/kvm/x86_emulate.c | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-)
arch/x86/kvm/x86_emulate.c +15 -0
@@ -60,6 +60,7 @@#define SrcImmByte (6<<4)/* 8-bit sign-extended immediate operand. */ #define SrcOne (7<<4)/* Implied '1' */ #define SrcImmUByte (8<<4)/* 8-bit unsigned immediate operand. */ +#define SrcImmU (9<<4)/* Immediate operand, unsigned */ #define SrcMask (0xf<<4)/* Generic ModRM decode. */ #define ModRM (1<<8)
@@ -1027,6 +1028,7 @@ done_prefixes: c->src.type =OP_MEM ;break ;case SrcImm: +case SrcImmU: c->src.type =OP_IMM ; c->src.ptr = (unsigned long *)c->eip; c->src.bytes = (c->d & ByteOp) ?1 : c->op_bytes;
@@ -1044,6 +1046,19 @@ done_prefixes: c->src.val =insn_fetch (s32,4 , c->eip);break ; } +if ((c->d & SrcMask) == SrcImmU) { +switch (c->src.bytes) { +case 1 : + c->src.val &=0xff ; +break ; +case 2 : + c->src.val &=0xffff ; +break ; +case 4 : + c->src.val &=0xffffffff ; +break ; + } + }break ;case SrcImmByte:case SrcImmUByte:
Signature · 1 line
1.6.3.3
PATCH 7/48 KVM: x86 emulator: fix jmp far decoding (opcode 0xea)
In reply to Avi KivityThe jump target should not be sign extened; use an unsigned decode flag.
--- arch/x86/kvm/x86_emulate.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kvm/x86_emulate.c +1 -1
@@ -196,7 +196,7 @@ static u32 opcode_table[256] = { ByteOp | SrcImmUByte, SrcImmUByte,/* 0xE8 - 0xEF */ SrcImm | Stack, SrcImm | ImplicitOps, - SrcImm | Src2Imm16, SrcImmByte | ImplicitOps, + SrcImmU | Src2Imm16, SrcImmByte | ImplicitOps, SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,/* 0xF0 - 0xF7 */
Signature · 1 line
1.6.3.3
PATCH 8/48 KVM: cleanup arch/x86/kvm/Makefile
In reply to Avi KivityFrom: Christoph Hellwig <[email protected]>
Use proper foo-y style list additions to cleanup all the conditionals, move module selection after compound object selection and remove the superflous comment.
--- arch/x86/kvm/Makefile | 32 +++++++++++++------------------- 1 files changed, 13 insertions(+), 19 deletions(-)
arch/x86/kvm/Makefile +13 -19
@@ -1,22 +1,16 @@ -# -# Makefile for Kernel-based Virtual Machine module -# - -common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \ - coalesced_mmio.o irq_comm.o) -ifeq ($(CONFIG_KVM_TRACE),y) -common-objs += $(addprefix ../../../virt/kvm/, kvm_trace.o) -endif -ifeq ($(CONFIG_IOMMU_API),y) -common-objs += $(addprefix ../../../virt/kvm/, iommu.o) -endif EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm -kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \ - i8254.o timer.o -obj-$(CONFIG_KVM) += kvm.o -kvm-intel-objs = vmx.o -obj-$(CONFIG_KVM_INTEL) += kvm-intel.o -kvm-amd-objs = svm.o -obj-$(CONFIG_KVM_AMD) += kvm-amd.o +kvm-y += $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \ + coalesced_mmio.o irq_comm.o) +kvm-$(CONFIG_KVM_TRACE) += $(addprefix ../../../virt/kvm/, kvm_trace.o) +kvm-$(CONFIG_IOMMU_API) += $(addprefix ../../../virt/kvm/, iommu.o) + +kvm-y += x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \ + i8254.o timer.o +kvm-intel-y += vmx.o +kvm-amd-y += svm.o + +obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM_INTEL) += kvm-intel.o +obj-$(CONFIG_KVM_AMD) += kvm-amd.o
Signature · 1 line
1.6.3.3
PATCH 9/48 KVM: Drop interrupt shadow when single stepping should be done only on VMX
In reply to Avi KivityFrom: Gleb Natapov <[email protected]>
The problem exists only on VMX. Also currently we skip this step if there is pending exception. The patch fixes this too.
--- arch/x86/kvm/vmx.c | 8 ++++++++ arch/x86/kvm/x86.c | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-)
arch/x86/kvm/vmx.c +8 -0
@@ -3453,6 +3453,14 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)if (test_bit (VCPU_REGS_RIP , (unsigned long *)&vcpu->arch.regs_dirty))vmcs_writel (GUEST_RIP , vcpu->arch.regs[VCPU_REGS_RIP ]); +/* When single-stepping over STI and MOV SS, we must clear the +* corresponding interruptibility bits in the guest state. Otherwise +* vmentry fails as it then expects bit 14 (BS) in pending debug +* exceptions being set, but that's not correct for the guest debugging +* case. */ +if (vcpu->guest_debug &KVM_GUESTDBG_SINGLESTEP ) +vmx_set_interrupt_shadow (vcpu,0 ); +/* * Loading guest fpu may have cleared host cr0.ts */
arch/x86/kvm/x86.c +0 -3
@@ -3361,9 +3361,6 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu)static void inject_pending_irq (struct kvm_vcpu *vcpu,struct kvm_run *kvm_run) { -if (vcpu->guest_debug &KVM_GUESTDBG_SINGLESTEP ) - kvm_x86_ops->set_interrupt_shadow (vcpu,0 ); -/* try to reinject previous events if any */ if (vcpu->arch.nmi_injected) { kvm_x86_ops->set_nmi (vcpu);
Signature · 1 line
1.6.3.3
PATCH 10/48 KVM: Move common KVM Kconfig items to new file virt/kvm/Kconfig
In reply to Avi KivityReduce Kconfig code duplication.
--- arch/ia64/kvm/Kconfig | 7 ++----- arch/powerpc/kvm/Kconfig | 3 +-- arch/s390/kvm/Kconfig | 6 +----- arch/x86/kvm/Kconfig | 7 ++----- virt/kvm/Kconfig | 7 +++++++ 5 files changed, 13 insertions(+), 17 deletions(-) create mode 100644 virt/kvm/Kconfig
arch/ia64/kvm/Kconfig +2 -5
@@ -1,12 +1,8 @@ # # KVM configuration # -config HAVE_KVM - bool -config HAVE_KVM_IRQCHIP - bool - default y +source "virt/kvm/Kconfig" menuconfig VIRTUALIZATION bool "Virtualization"
@@ -28,6 +24,7 @@ config KVM depends on PCI select PREEMPT_NOTIFIERS select ANON_INODES + select HAVE_KVM_IRQCHIP ---help--- Support hosting fully virtualized guest machines using hardware virtualization extensions. You will need a fairly recent
arch/powerpc/kvm/Kconfig +1 -2
@@ -2,8 +2,7 @@ # KVM configuration # -config HAVE_KVM_IRQCHIP - bool +source "virt/kvm/Kconfig" menuconfig VIRTUALIZATION bool "Virtualization"
arch/s390/kvm/Kconfig +1 -5
@@ -1,11 +1,7 @@ # # KVM configuration # -config HAVE_KVM - bool - -config HAVE_KVM_IRQCHIP - bool +source "virt/kvm/Kconfig" menuconfig VIRTUALIZATION bool "Virtualization"
arch/x86/kvm/Kconfig +2 -5
@@ -1,12 +1,8 @@ # # KVM configuration # -config HAVE_KVM - bool -config HAVE_KVM_IRQCHIP - bool - default y +source "virt/kvm/Kconfig" menuconfig VIRTUALIZATION bool "Virtualization"
@@ -29,6 +25,7 @@ config KVM select PREEMPT_NOTIFIERS select MMU_NOTIFIER select ANON_INODES + select HAVE_KVM_IRQCHIP ---help--- Support hosting fully virtualized guest machines using hardware virtualization extensions. You will need a fairly recent
virt/kvm/Kconfig new file +7 -0
@@ -0,0 +1,7 @@ +# KVM common configuration items and defaults + +config HAVE_KVM + bool + +config HAVE_KVM_IRQCHIP + bool
Signature · 1 line
1.6.3.3
PATCH 11/48 KVM: irqfd
In reply to Avi KivityFrom: Gregory Haskins <[email protected]>
KVM provides a complete virtual system environment for guests, including support for injecting interrupts modeled after the real exception/interrupt facilities present on the native platform (such as the IDT on x86). Virtual interrupts can come from a variety of sources (emulated devices, pass-through devices, etc) but all must be injected to the guest via the KVM infrastructure. This patch adds a new mechanism to inject a specific interrupt to a guest using a decoupled eventfd mechnanism: Any legal signal on the irqfd (using eventfd semantics from either userspace or kernel) will translate into an injected interrupt in the guest at the next available interrupt window.
--- arch/x86/kvm/Kconfig | 1 + arch/x86/kvm/Makefile | 2 +- arch/x86/kvm/x86.c | 1 + include/linux/kvm.h | 11 ++ include/linux/kvm_host.h | 24 ++++ virt/kvm/Kconfig | 4 + virt/kvm/eventfd.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++ virt/kvm/kvm_main.c | 12 ++ 8 files changed, 383 insertions(+), 1 deletions(-) create mode 100644 virt/kvm/eventfd.c
arch/x86/kvm/Kconfig +1 -0
@@ -26,6 +26,7 @@ config KVM select MMU_NOTIFIER select ANON_INODES select HAVE_KVM_IRQCHIP + select HAVE_KVM_EVENTFD ---help--- Support hosting fully virtualized guest machines using hardware virtualization extensions. You will need a fairly recent
arch/x86/kvm/Makefile +1 -1
@@ -2,7 +2,7 @@ EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm kvm-y += $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \ - coalesced_mmio.o irq_comm.o) + coalesced_mmio.o irq_comm.o eventfd.o) kvm-$(CONFIG_KVM_TRACE) += $(addprefix ../../../virt/kvm/, kvm_trace.o) kvm-$(CONFIG_IOMMU_API) += $(addprefix ../../../virt/kvm/, iommu.o)
arch/x86/kvm/x86.c +1 -0
@@ -1126,6 +1126,7 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_REINJECT_CONTROL :case KVM_CAP_IRQ_INJECT_STATUS :case KVM_CAP_ASSIGN_DEV_IRQ : +case KVM_CAP_IRQFD : r =1 ;break ;case KVM_CAP_COALESCED_MMIO :
include/linux/kvm.h +11 -0
@@ -418,6 +418,7 @@ struct kvm_trace_rec {#ifdef __KVM_HAVE_MCE#define KVM_CAP_MCE 31#endif +#define KVM_CAP_IRQFD 32#ifdef KVM_CAP_IRQ_ROUTING
@@ -470,6 +471,15 @@ struct kvm_x86_mce { };#endif +#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0) + +struct kvm_irqfd { +__u32 fd; +__u32 gsi; +__u32 flags; +__u8 pad[20 ]; +}; +/* * ioctls for VM fds */
@@ -514,6 +524,7 @@ struct kvm_x86_mce {#define KVM_ASSIGN_SET_MSIX_ENTRY \ _IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry)#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq) +#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)/* * ioctls for vcpu fds
include/linux/kvm_host.h +24 -0
@@ -136,6 +136,12 @@ struct kvm {struct list_head vm_list;struct kvm_io_bus mmio_bus;struct kvm_io_bus pio_bus; +#ifdef CONFIG_HAVE_KVM_EVENTFD +struct { +spinlock_t lock; +struct list_head items; + } irqfds; +#endif struct kvm_vm_stat stat;struct kvm_arch arch;atomic_t users_count;
@@ -525,4 +531,22 @@ static inline void kvm_free_irq_routing(struct kvm *kvm) {}#endif +#ifdef CONFIG_HAVE_KVM_EVENTFD + +void kvm_irqfd_init (struct kvm *kvm); +int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags); +void kvm_irqfd_release (struct kvm *kvm); + +#else + +static inline void kvm_irqfd_init (struct kvm *kvm) {} +static inline int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags) +{ +return -EINVAL ; +} + +static inline void kvm_irqfd_release (struct kvm *kvm) {} + +#endif /* CONFIG_HAVE_KVM_EVENTFD */ +#endif
virt/kvm/Kconfig +4 -0
@@ -5,3 +5,7 @@ config HAVE_KVM config HAVE_KVM_IRQCHIP bool + +config HAVE_KVM_EVENTFD + bool + select EVENTFD
virt/kvm/eventfd.c new file +329 -0
329 lines not on this page · raw message
virt/kvm/kvm_main.c +12 -0
@@ -986,6 +986,7 @@ static struct kvm *kvm_create_vm(void)spin_lock_init (&kvm->mmu_lock);spin_lock_init (&kvm->requests_lock);kvm_io_bus_init (&kvm->pio_bus); +kvm_irqfd_init (kvm);mutex_init (&kvm->lock);kvm_io_bus_init (&kvm->mmio_bus);init_rwsem (&kvm->slots_lock);
@@ -1071,6 +1072,8 @@ static int kvm_vm_release(struct inode *inode, struct file *filp) {struct kvm *kvm = filp->private_data; +kvm_irqfd_release (kvm); +kvm_put_kvm (kvm);return 0 ; }
@@ -2222,6 +2225,15 @@ static long kvm_vm_ioctl(struct file *filp, }#endif #endif /* KVM_CAP_IRQ_ROUTING */ +case KVM_IRQFD : { +struct kvm_irqfd data; + + r = -EFAULT ; +if (copy_from_user (&data, argp,sizeof data)) + goto out; + r =kvm_irqfd (kvm, data.fd, data.gsi, data.flags); +break ; + }default : r =kvm_arch_vm_ioctl (filp, ioctl, arg); }
Signature · 1 line
1.6.3.3
PATCH 12/48 KVM: Allow PIT emulation without speaker port
In reply to Avi KivityFrom: Jan Kiszka <[email protected]>
The in-kernel speaker emulation is only a dummy and also unneeded from the performance point of view. Rather, it takes user space support to generate sound output on the host, e.g. console beeps.
To allow this, introduce KVM_CREATE_PIT2 which controls in-kernel speaker port emulation via a flag passed along the new IOCTL. It also leaves room for future extensions of the PIT configuration interface.
--- arch/x86/kvm/i8254.c | 14 ++++++++------ arch/x86/kvm/i8254.h | 2 +- arch/x86/kvm/x86.c | 12 +++++++++++- include/linux/kvm.h | 12 ++++++++++++ 4 files changed, 32 insertions(+), 8 deletions(-)
arch/x86/kvm/i8254.c +8 -6
@@ -563,7 +563,7 @@ static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask) } } -struct kvm_pit *kvm_create_pit (struct kvm *kvm) +struct kvm_pit *kvm_create_pit (struct kvm *kvm,u32 flags) {struct kvm_pit *pit;struct kvm_kpit_state *pit_state;
@@ -589,11 +589,13 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) pit->dev.private = pit;kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); - pit->speaker_dev.read = speaker_ioport_read; - pit->speaker_dev.write = speaker_ioport_write; - pit->speaker_dev.in_range = speaker_in_range; - pit->speaker_dev.private = pit; -kvm_io_bus_register_dev (&kvm->pio_bus, &pit->speaker_dev); +if (flags &KVM_PIT_SPEAKER_DUMMY ) { + pit->speaker_dev.read = speaker_ioport_read; + pit->speaker_dev.write = speaker_ioport_write; + pit->speaker_dev.in_range = speaker_in_range; + pit->speaker_dev.private = pit; +kvm_io_bus_register_dev (&kvm->pio_bus, &pit->speaker_dev); + } kvm->arch.vpit = pit; pit->kvm = kvm;
arch/x86/kvm/i8254.h +1 -1
@@ -50,7 +50,7 @@ struct kvm_pit {void kvm_inject_pit_timer_irqs (struct kvm_vcpu *vcpu);void kvm_pit_load_count (struct kvm *kvm,int channel,u32 val); -struct kvm_pit *kvm_create_pit (struct kvm *kvm); +struct kvm_pit *kvm_create_pit (struct kvm *kvm,u32 flags);void kvm_free_pit (struct kvm *kvm);void kvm_pit_reset (struct kvm_pit *pit);
arch/x86/kvm/x86.c +11 -1
@@ -1127,6 +1127,7 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_IRQ_INJECT_STATUS :case KVM_CAP_ASSIGN_DEV_IRQ :case KVM_CAP_IRQFD : +case KVM_CAP_PIT2 : r =1 ;break ;case KVM_CAP_COALESCED_MMIO :
@@ -2038,6 +2039,7 @@ long kvm_arch_vm_ioctl(struct file *filp,union {struct kvm_pit_state ps;struct kvm_memory_alias alias; +struct kvm_pit_config pit_config; } u;switch (ioctl) {
@@ -2098,12 +2100,20 @@ long kvm_arch_vm_ioctl(struct file *filp, }break ;case KVM_CREATE_PIT : + u.pit_config.flags =KVM_PIT_SPEAKER_DUMMY ; + goto create_pit; +case KVM_CREATE_PIT2 : + r = -EFAULT ; +if (copy_from_user (&u.pit_config, argp, +sizeof (struct kvm_pit_config ))) + goto out; + create_pit:mutex_lock (&kvm->lock); r = -EEXIST ;if (kvm->arch.vpit) goto create_pit_unlock; r = -ENOMEM ; - kvm->arch.vpit =kvm_create_pit (kvm); + kvm->arch.vpit =kvm_create_pit (kvm, u.pit_config.flags);if (kvm->arch.vpit) r =0 ; create_pit_unlock:
include/linux/kvm.h +12 -0
@@ -70,6 +70,14 @@ struct kvm_irqchip { } chip; }; +/* for KVM_CREATE_PIT2 */ +struct kvm_pit_config { +__u32 flags; +__u32 pad[15 ]; +}; + +#define KVM_PIT_SPEAKER_DUMMY 1 +#define KVM_EXIT_UNKNOWN 0#define KVM_EXIT_EXCEPTION 1#define KVM_EXIT_IO 2
@@ -419,6 +427,9 @@ struct kvm_trace_rec {#define KVM_CAP_MCE 31#endif #define KVM_CAP_IRQFD 32 +#ifdef __KVM_HAVE_PIT +#define KVM_CAP_PIT2 33 +#endif #ifdef KVM_CAP_IRQ_ROUTING
@@ -525,6 +536,7 @@ struct kvm_irqfd { _IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry)#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd) +#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)/* * ioctls for vcpu fds
Signature · 1 line
1.6.3.3
PATCH 13/48 KVM: ia64: Correct itc_offset calculations
In reply to Avi KivityFrom: Jes Sorensen <[email protected]>
Init the itc_offset for all possible vCPUs. The current code by mistake ends up only initializing the offset on vCPU 0.
Spotted by Gleb Natapov.
--- arch/ia64/kvm/kvm-ia64.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/ia64/kvm/kvm-ia64.c +1 -1
@@ -1224,7 +1224,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)/*Initialize itc offset for vcpus*/ itc_offset =0UL -kvm_get_itc (vcpu); -for (i =0 ; i < kvm->arch.online_vcpus; i++) { +for (i =0 ; i <KVM_MAX_VCPUS ; i++) { v = (struct kvm_vcpu *)((char *)vcpu +sizeof (struct kvm_vcpu_data ) * i); v->arch.itc_offset = itc_offset;
Signature · 1 line
1.6.3.3
PATCH 14/48 KVM: s390: infrastructure to kick vcpus out of guest state
In reply to Avi KivityFrom: Christian Ehrhardt <[email protected]>
To ensure vcpu's come out of guest context in certain cases this patch adds a s390 specific way to kick them out of guest context. Currently it kicks them out to rerun the vcpu_run path in the s390 code, but the mechanism itself is expandable and with a new flag we could also add e.g. kicks to userspace etc.
--- arch/s390/include/asm/kvm_host.h | 5 ++- arch/s390/kvm/intercept.c | 12 ++++++-- arch/s390/kvm/kvm-s390.c | 5 +++ arch/s390/kvm/kvm-s390.h | 3 ++ arch/s390/kvm/sigp.c | 56 +++++++++++++++++++++++--------------- 5 files changed, 54 insertions(+), 27 deletions(-)
arch/s390/include/asm/kvm_host.h +3 -2
@@ -182,8 +182,9 @@ struct kvm_s390_interrupt_info { };/* for local_interrupt.action_flags */ -#define ACTION_STORE_ON_STOP 1 -#define ACTION_STOP_ON_STOP 2 +#define ACTION_STORE_ON_STOP (1<<0) +#define ACTION_STOP_ON_STOP (1<<1) +#define ACTION_RELOADVCPU_ON_STOP (1<<2)struct kvm_s390_local_interrupt {spinlock_t lock;
arch/s390/kvm/intercept.c +9 -3
@@ -128,7 +128,7 @@ static int handle_noop(struct kvm_vcpu *vcpu)static int handle_stop (struct kvm_vcpu *vcpu) { -int rc; +int rc =0 ; vcpu->stat.exit_stop_request++;atomic_clear_mask (CPUSTAT_RUNNING , &vcpu->arch.sie_block->cpuflags);
@@ -141,12 +141,18 @@ static int handle_stop(struct kvm_vcpu *vcpu) rc = -ENOTSUPP ; } +if (vcpu->arch.local_int.action_bits &ACTION_RELOADVCPU_ON_STOP ) { + vcpu->arch.local_int.action_bits &= ~ACTION_RELOADVCPU_ON_STOP ; + rc =SIE_INTERCEPT_RERUNVCPU ; + vcpu->run->exit_reason =KVM_EXIT_INTR ; + } +if (vcpu->arch.local_int.action_bits &ACTION_STOP_ON_STOP ) { vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP ;VCPU_EVENT (vcpu,3 ,"%s" ,"cpu stopped" ); rc = -ENOTSUPP ; - }else - rc =0 ; + } +spin_unlock_bh (&vcpu->arch.local_int.lock);return rc; }
arch/s390/kvm/kvm-s390.c +5 -0
@@ -490,6 +490,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)vcpu_load (vcpu); +rerun_vcpu:/* verify, that memory has been registered */ if (!vcpu->kvm->arch.guest_memsize) {vcpu_put (vcpu);
@@ -509,6 +510,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) vcpu->arch.sie_block->gpsw.addr = kvm_run->s390_sieic.addr;break ;case KVM_EXIT_UNKNOWN : +case KVM_EXIT_INTR :case KVM_EXIT_S390_RESET :break ;default :
@@ -522,6 +524,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) rc =kvm_handle_sie_intercept (vcpu); }while (!signal_pending (current) && !rc); +if (rc ==SIE_INTERCEPT_RERUNVCPU ) + goto rerun_vcpu; +if (signal_pending (current) && !rc) rc = -EINTR ;
arch/s390/kvm/kvm-s390.h +3 -0
@@ -20,6 +20,8 @@typedef int (*intercept_handler_t )(struct kvm_vcpu *vcpu); +/* negativ values are error codes, positive values for internal conditions */ +#define SIE_INTERCEPT_RERUNVCPU (1<<0)int kvm_handle_sie_intercept (struct kvm_vcpu *vcpu); #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
@@ -50,6 +52,7 @@ int kvm_s390_inject_vm(struct kvm *kvm,int kvm_s390_inject_vcpu (struct kvm_vcpu *vcpu,struct kvm_s390_interrupt *s390int);int kvm_s390_inject_program_int (struct kvm_vcpu *vcpu,u16 code); +int kvm_s390_inject_sigp_stop (struct kvm_vcpu *vcpu,int action);/* implemented in priv.c */ int kvm_s390_handle_b2 (struct kvm_vcpu *vcpu);
arch/s390/kvm/sigp.c +34 -22
104 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH 15/48 KVM: s390: fix signal handling
In reply to Avi KivityFrom: Christian Ehrhardt <[email protected]>
If signal pending is true we exit without updating kvm_run, userspace currently just does nothing and jumps to kvm_run again. Since we did not set an exit_reason we might end up with a random one (whatever was the last exit). Therefore it was possible to e.g. jump to the psw position the last real interruption set.
Setting the INTR exit reason ensures that no old psw data is swapped in on reentry.
--- arch/s390/kvm/kvm-s390.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/s390/kvm/kvm-s390.c +3 -1
@@ -527,8 +527,10 @@ rerun_vcpu:if (rc ==SIE_INTERCEPT_RERUNVCPU ) goto rerun_vcpu; -if (signal_pending (current) && !rc) +if (signal_pending (current) && !rc) { + kvm_run->exit_reason =KVM_EXIT_INTR ; rc = -EINTR ; + }if (rc == -ENOTSUPP ) {/* intercept cannot be handled in-kernel, prepare kvm-run */
Signature · 1 line
1.6.3.3
PATCH 16/48 KVM: s390: streamline memslot handling
In reply to Avi KivityFrom: Christian Ehrhardt <[email protected]>
This patch relocates the variables kvm-s390 uses to track guest mem addr/size. As discussed dropping the variables at struct kvm_arch level allows to use the common vcpu->request based mechanism to reload guest memory if e.g. changes via set_memory_region.
The kick mechanism introduced in this series is used to ensure running vcpus leave guest state to catch the update.
--- arch/s390/include/asm/kvm_host.h | 4 +-- arch/s390/kvm/gaccess.h | 23 +++++++++-------- arch/s390/kvm/intercept.c | 6 ++-- arch/s390/kvm/kvm-s390.c | 50 ++++++++++++------------------------- arch/s390/kvm/kvm-s390.h | 29 +++++++++++++++++++++- arch/s390/kvm/sigp.c | 4 +- 6 files changed, 62 insertions(+), 54 deletions(-)
arch/s390/include/asm/kvm_host.h +1 -3
@@ -1,7 +1,7 @@/* * asm-s390/kvm_host.h - definition for kernel virtual machines on s390 * -* Copyright IBM Corp. 2008 +* Copyright IBM Corp. 2008,2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2 only)
@@ -228,8 +228,6 @@ struct kvm_vm_stat { };struct kvm_arch { -unsigned long guest_origin; -unsigned long guest_memsize;struct sca_block *sca;debug_info_t *dbf;struct kvm_s390_float_interrupt float_int;
arch/s390/kvm/gaccess.h +12 -11
@@ -1,7 +1,7 @@/* * gaccess.h - access guest memory * -* Copyright IBM Corp. 2008 +* Copyright IBM Corp. 2008,2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2 only)
@@ -16,13 +16,14 @@#include <linux/compiler.h> #include <linux/kvm_host.h> #include <asm/uaccess.h> +#include "kvm-s390.h" static inline void __user *__guestaddr_to_user (struct kvm_vcpu *vcpu,unsigned long guestaddr) {unsigned long prefix = vcpu->arch.sie_block->prefix; -unsigned long origin = vcpu->kvm->arch.guest_origin; -unsigned long memsize = vcpu->kvm->arch.guest_memsize; +unsigned long origin = vcpu->arch.sie_block->gmsor; +unsigned long memsize =kvm_s390_vcpu_get_memsize (vcpu);if (guestaddr <2 *PAGE_SIZE ) guestaddr += prefix;
@@ -158,8 +159,8 @@ static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest, const void *from, unsigned long n) { unsigned long prefix = vcpu->arch.sie_block->prefix; -unsigned long origin = vcpu->kvm->arch.guest_origin; -unsigned long memsize = vcpu->kvm->arch.guest_memsize; +unsigned long origin = vcpu->arch.sie_block->gmsor; +unsigned long memsize =kvm_s390_vcpu_get_memsize (vcpu);if ((guestdest <2 *PAGE_SIZE ) && (guestdest + n >2 *PAGE_SIZE )) goto slowpath;
@@ -209,8 +210,8 @@ static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to, unsigned long guestsrc, unsigned long n) {unsigned long prefix = vcpu->arch.sie_block->prefix; -unsigned long origin = vcpu->kvm->arch.guest_origin; -unsigned long memsize = vcpu->kvm->arch.guest_memsize; +unsigned long origin = vcpu->arch.sie_block->gmsor; +unsigned long memsize =kvm_s390_vcpu_get_memsize (vcpu);if ((guestsrc <2 *PAGE_SIZE ) && (guestsrc + n >2 *PAGE_SIZE )) goto slowpath;
@@ -244,8 +245,8 @@ static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,unsigned long guestdest, const void *from, unsigned long n) { - unsigned long origin = vcpu->kvm->arch.guest_origin; -unsigned long memsize = vcpu->kvm->arch.guest_memsize; + unsigned long origin = vcpu->arch.sie_block->gmsor; +unsigned long memsize =kvm_s390_vcpu_get_memsize (vcpu);if (guestdest + n > memsize)return -EFAULT ;
@@ -262,8 +263,8 @@ static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to, unsigned long guestsrc, unsigned long n) { -unsigned long origin = vcpu->kvm->arch.guest_origin; -unsigned long memsize = vcpu->kvm->arch.guest_memsize; +unsigned long origin = vcpu->arch.sie_block->gmsor; +unsigned long memsize =kvm_s390_vcpu_get_memsize (vcpu);if (guestsrc + n > memsize)return -EFAULT ;
arch/s390/kvm/intercept.c +3 -3
@@ -1,7 +1,7 @@/* * intercept.c - in-kernel handling for sie intercepts * -* Copyright IBM Corp. 2008 +* Copyright IBM Corp. 2008,2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2 only)
@@ -164,9 +164,9 @@ static int handle_validity(struct kvm_vcpu *vcpu) vcpu->stat.exit_validity++;if ((viwhy ==0x37 ) && (vcpu->arch.sie_block->prefix - <= vcpu->kvm->arch.guest_memsize -2 *PAGE_SIZE )){ + <=kvm_s390_vcpu_get_memsize (vcpu) -2 *PAGE_SIZE )) { rc =fault_in_pages_writeable ((char __user *) - vcpu->kvm->arch.guest_origin + + vcpu->arch.sie_block->gmsor + vcpu->arch.sie_block->prefix,2 *PAGE_SIZE );if (rc)
arch/s390/kvm/kvm-s390.c +16 -34
97 lines not on this page · raw message
arch/s390/kvm/kvm-s390.h +28 -1
@@ -1,7 +1,7 @@/* * kvm_s390.h - definition for kvm on s390 * -* Copyright IBM Corp. 2008 +* Copyright IBM Corp. 2008,2009 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2 only)
@@ -9,6 +9,7 @@* * Author(s): Carsten Otte <[email protected]> * Christian Borntraeger <[email protected]> +* Christian Ehrhardt <[email protected]> */ #ifndef ARCH_S390_KVM_S390_H
@@ -18,6 +19,9 @@#include <linux/kvm.h> #include <linux/kvm_host.h> +/* The current code can have up to 256 pages for virtio */ +#define VIRTIODESCSPACE (256ul * 4096ul) +typedef int (*intercept_handler_t )(struct kvm_vcpu *vcpu);/* negativ values are error codes, positive values for internal conditions */
@@ -54,6 +58,29 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,int kvm_s390_inject_program_int (struct kvm_vcpu *vcpu,u16 code);int kvm_s390_inject_sigp_stop (struct kvm_vcpu *vcpu,int action); +static inline int kvm_s390_vcpu_get_memsize (struct kvm_vcpu *vcpu) +{ +return vcpu->arch.sie_block->gmslm + - vcpu->arch.sie_block->gmsor + -VIRTIODESCSPACE +1ul ; +} + +static inline void kvm_s390_vcpu_set_mem (struct kvm_vcpu *vcpu) +{ +struct kvm_memory_slot *mem; + +down_read (&vcpu->kvm->slots_lock); + mem = &vcpu->kvm->memslots[0 ]; + + vcpu->arch.sie_block->gmsor = mem->userspace_addr; + vcpu->arch.sie_block->gmslm = + mem->userspace_addr + + (mem->npages <<PAGE_SHIFT ) + +VIRTIODESCSPACE -1ul ; + +up_read (&vcpu->kvm->slots_lock); +} +/* implemented in priv.c */ int kvm_s390_handle_b2 (struct kvm_vcpu *vcpu);
arch/s390/kvm/sigp.c +2 -2
@@ -189,9 +189,9 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,/* make sure that the new value is valid memory */ address = address &0x7fffe000u ;if ((copy_from_guest (vcpu, &tmp, - (u64) (address + vcpu->kvm->arch.guest_origin) ,1 )) || + (u64) (address + vcpu->arch.sie_block->gmsor) ,1 )) || (copy_from_guest (vcpu, &tmp, (u64) (address + - vcpu->kvm->arch.guest_origin +PAGE_SIZE ),1 ))) { + vcpu->arch.sie_block->gmsor +PAGE_SIZE ),1 ))) { *reg |=SIGP_STAT_INVALID_PARAMETER ;return 1 ;/* invalid parameter */ }
Signature · 1 line
1.6.3.3
PATCH 17/48 KVM: Downsize max support MSI-X entry to 256
In reply to Avi KivityFrom: Sheng Yang <[email protected]>
We only trap one page for MSI-X entry now, so it's 4k/(128/8) = 256 entries at most.
--- include/linux/kvm.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/kvm.h +1 -1
@@ -676,7 +676,7 @@ struct kvm_assigned_msix_nr {__u16 padding; }; -#define KVM_MAX_MSIX_PER_DEV 512 +#define KVM_MAX_MSIX_PER_DEV 256struct kvm_assigned_msix_entry {__u32 assigned_dev_id;__u32 gsi;
Signature · 1 line
1.6.3.3
PATCH 18/48 KVM: SVM: use explicit 64bit storage for sysenter values
In reply to Avi KivityFrom: Andre Przywara <[email protected]>
Since AMD does not support sysenter in 64bit mode, the VMCB fields storing the MSRs are truncated to 32bit upon VMRUN/#VMEXIT. So store the values in a separate 64bit storage to avoid truncation.
--- arch/x86/kvm/kvm_svm.h | 3 +++ arch/x86/kvm/svm.c | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-)
arch/x86/kvm/kvm_svm.h +3 -0
@@ -27,6 +27,9 @@ struct vcpu_svm {unsigned long vmcb_pa;struct svm_cpu_data *svm_data;uint64_t asid_generation; +uint64_t sysenter_cs; +uint64_t sysenter_esp; +uint64_t sysenter_eip;u64 next_rip;
arch/x86/kvm/svm.c +6 -6
@@ -1978,13 +1978,13 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)break ;#endif case MSR_IA32_SYSENTER_CS : - *data = svm->vmcb->save.sysenter_cs; + *data = svm->sysenter_cs;break ;case MSR_IA32_SYSENTER_EIP : - *data = svm->vmcb->save.sysenter_eip; + *data = svm->sysenter_eip;break ;case MSR_IA32_SYSENTER_ESP : - *data = svm->vmcb->save.sysenter_esp; + *data = svm->sysenter_esp;break ;/* Nobody will change the following 5 values in the VMCB so we can safely return them on rdmsr. They will always be 0
@@ -2068,13 +2068,13 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)break ;#endif case MSR_IA32_SYSENTER_CS : - svm->vmcb->save.sysenter_cs = data; + svm->sysenter_cs = data;break ;case MSR_IA32_SYSENTER_EIP : - svm->vmcb->save.sysenter_eip = data; + svm->sysenter_eip = data;break ;case MSR_IA32_SYSENTER_ESP : - svm->vmcb->save.sysenter_esp = data; + svm->sysenter_esp = data;break ;case MSR_IA32_DEBUGCTLMSR :if (!svm_has (SVM_FEATURE_LBRV )) {
Signature · 1 line
1.6.3.3
PATCH 19/48 KVM: No disable_irq for MSI/MSI-X interrupt on device assignment
In reply to Avi KivityFrom: Sheng Yang <[email protected]>
Disable interrupt at interrupt handler and enable it when guest ack is for the level triggered interrupt, to prevent reinjected interrupt. MSI/MSI-X don't need it.
One possible problem is multiply same vector interrupt injected between irq handler and scheduled work handler would be merged as one for MSI/MSI-X. But AFAIK, the drivers handle it well.
The patch fixed the oplin card performance issue(MSI-X performance is half of MSI/INTx).
--- virt/kvm/kvm_main.c | 22 ++++++++-------------- 1 files changed, 8 insertions(+), 14 deletions(-)
virt/kvm/kvm_main.c +8 -14
@@ -120,7 +120,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work) {struct kvm_assigned_dev_kernel *assigned_dev;struct kvm *kvm; -int irq, i; +int i; assigned_dev = container_of(work, struct kvm_assigned_dev_kernel, interrupt_work);
@@ -143,20 +143,10 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)kvm_set_irq (assigned_dev->kvm, assigned_dev->irq_source_id, guest_entries[i].vector,1 ); - irq = assigned_dev->host_msix_entries[i].vector; -if (irq !=0 ) -enable_irq (irq); - assigned_dev->host_irq_disabled = false; } - }else { + }else kvm_set_irq (assigned_dev->kvm, assigned_dev->irq_source_id, assigned_dev->guest_irq,1 ); -if (assigned_dev->irq_requested_type & -KVM_DEV_IRQ_GUEST_MSI ) { -enable_irq (assigned_dev->host_irq); - assigned_dev->host_irq_disabled = false; - } - }spin_unlock_irq (&assigned_dev->assigned_dev_lock);mutex_unlock (&assigned_dev->kvm->lock);
@@ -179,8 +169,10 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)schedule_work (&assigned_dev->interrupt_work); -disable_irq_nosync (irq); - assigned_dev->host_irq_disabled = true; +if (assigned_dev->irq_requested_type &KVM_DEV_IRQ_GUEST_INTX ) { +disable_irq_nosync (irq); + assigned_dev->host_irq_disabled = true; + } out:spin_unlock_irqrestore (&assigned_dev->assigned_dev_lock, flags);
@@ -417,6 +409,7 @@ static int assigned_device_enable_guest_msi(struct kvm *kvm, { dev->guest_irq = irq->guest_irq; dev->ack_notifier.gsi =-1 ; + dev->host_irq_disabled = false;return 0 ; }#endif
@@ -427,6 +420,7 @@ static int assigned_device_enable_guest_msix(struct kvm *kvm, { dev->guest_irq = irq->guest_irq; dev->ack_notifier.gsi =-1 ; + dev->host_irq_disabled = false;return 0 ; }#endif
Signature · 1 line
1.6.3.3
PATCH 20/48 KVM: remove redundant declarations
In reply to Avi KivityFrom: Christian Ehrhardt <[email protected]>
Changing s390 code in kvm_arch_vcpu_load/put come across this header declarations. They are complete duplicates, not even useful forward declarations as nothing using it is in between (maybe it was that in the past).
This patch removes the two dispensable lines.
--- include/linux/kvm_host.h | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
include/linux/kvm_host.h +0 -2
@@ -249,8 +249,6 @@ long kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);long kvm_arch_vcpu_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg); -void kvm_arch_vcpu_load (struct kvm_vcpu *vcpu,int cpu); -void kvm_arch_vcpu_put (struct kvm_vcpu *vcpu);int kvm_dev_ioctl_check_extension (long ext);
Signature · 1 line
1.6.3.3
PATCH 21/48 KVM: SVM: Fold kvm_svm.h info svm.c
In reply to Avi Kivitykvm_svm.h is only included from svm.c, so fold it in.
--- arch/x86/kvm/kvm_svm.h | 54 ------------------------------------------------ arch/x86/kvm/svm.c | 42 ++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 55 deletions(-) delete mode 100644 arch/x86/kvm/kvm_svm.h
arch/x86/kvm/kvm_svm.h deleted +0 -54
@@ -1,54 +0,0 @@ -#ifndef __KVM_SVM_H -#define __KVM_SVM_H - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/list.h> -#include <linux/kvm_host.h> -#include <asm/msr.h> - -#include <asm/svm.h> - -static const u32 host_save_user_msrs[] = { -#ifdef CONFIG_X86_64 -MSR_STAR ,MSR_LSTAR ,MSR_CSTAR ,MSR_SYSCALL_MASK ,MSR_KERNEL_GS_BASE , -MSR_FS_BASE , -#endif -MSR_IA32_SYSENTER_CS ,MSR_IA32_SYSENTER_ESP ,MSR_IA32_SYSENTER_EIP , -}; - -#define NR_HOST_SAVE_USER_MSRS ARRAY_SIZE(host_save_user_msrs) - -struct kvm_vcpu ; - -struct vcpu_svm { -struct kvm_vcpu vcpu; -struct vmcb *vmcb; -unsigned long vmcb_pa; -struct svm_cpu_data *svm_data; -uint64_t asid_generation; -uint64_t sysenter_cs; -uint64_t sysenter_esp; -uint64_t sysenter_eip; - -u64 next_rip; - -u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS ]; -u64 host_gs_base; -unsigned long host_cr2; - -u32 *msrpm; -struct vmcb *hsave; -u64 hsave_msr; - -u64 nested_vmcb; - -/* These are the merged vectors */ -u32 *nested_msrpm; - -/* gpa pointers to the real vectors */ -u64 nested_vmcb_msrpm; -}; - -#endif -
arch/x86/kvm/svm.c +41 -1
54 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH 22/48 KVM: powerpc: fix some init/exit annotations
In reply to Avi KivityFrom: Stephen Rothwell <[email protected]>
Fixes a couple of warnings like this one:
WARNING: arch/powerpc/kvm/kvm-440.o(.text+0x1e8c): Section mismatch in reference from the function kvmppc_44x_exit() to the function .exit.text:kvmppc_booke_exit() The function kvmppc_44x_exit() references a function in an exit section.
Often the function kvmppc_booke_exit() has valid usage outside the exit section
and the fix is to remove the __exit annotation of kvmppc_booke_exit.
Also add some __init annotations on obvious routines.
--- arch/powerpc/kvm/44x.c | 4 ++-- arch/powerpc/kvm/booke.c | 2 +- arch/powerpc/kvm/e500.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-)
arch/powerpc/kvm/44x.c +2 -2
@@ -138,7 +138,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)kmem_cache_free (kvm_vcpu_cache, vcpu_44x); } -static int kvmppc_44x_init (void ) +static int __init kvmppc_44x_init (void ) {int r;
@@ -149,7 +149,7 @@ static int kvmppc_44x_init(void)return kvm_init (NULL ,sizeof (struct kvmppc_vcpu_44x ),THIS_MODULE ); } -static void kvmppc_44x_exit (void ) +static void __exit kvmppc_44x_exit(void) {kvmppc_booke_exit (); }
arch/powerpc/kvm/booke.c +1 -1
@@ -520,7 +520,7 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,return kvmppc_core_vcpu_translate (vcpu, tr); } -int kvmppc_booke_init (void ) +int __init kvmppc_booke_init (void ) {unsigned long ivor[16 ];unsigned long max_ivor =0 ;
arch/powerpc/kvm/e500.c +2 -2
@@ -132,7 +132,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)kmem_cache_free (kvm_vcpu_cache, vcpu_e500); } -static int kvmppc_e500_init (void ) +static int __init kvmppc_e500_init (void ) {int r, i;unsigned long ivor[3 ];
@@ -160,7 +160,7 @@ static int kvmppc_e500_init(void)return kvm_init (NULL ,sizeof (struct kvmppc_vcpu_e500 ),THIS_MODULE ); } -static void kvmppc_e500_exit (void ) +static void __init kvmppc_e500_exit (void ) {kvmppc_booke_exit (); }
Signature · 1 line
1.6.3.3
PATCH 23/48 KVM: Clean up coalesced_mmio destruction
In reply to Avi KivityFrom: Gregory Haskins <[email protected]>
We invoke kfree() on a data member instead of the structure. This works today because the kvm_io_device is the first element of the private structure, but this could change in the future, so lets clean this up.
--- virt/kvm/coalesced_mmio.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
virt/kvm/coalesced_mmio.c +4 -1
@@ -80,7 +80,10 @@ static void coalesced_mmio_write(struct kvm_io_device *this,static void coalesced_mmio_destructor (struct kvm_io_device *this) { -kfree (this); +struct kvm_coalesced_mmio_dev *dev = + (struct kvm_coalesced_mmio_dev *)this->private; + +kfree (dev); }int kvm_coalesced_mmio_init (struct kvm *kvm)
Signature · 1 line
1.6.3.3
PATCH 24/48 KVM: cleanup io_device code
In reply to Avi KivityFrom: Gregory Haskins <[email protected]>
We modernize the io_device code so that we use container_of() instead of dev->private, and move the vtable to a separate ops structure (theoretically allows better caching for multiple instances of the same ops structure)
--- arch/x86/kvm/i8254.c | 40 ++++++++++++++++++++++++++++------------ arch/x86/kvm/i8259.c | 20 ++++++++++++++------ arch/x86/kvm/lapic.c | 22 +++++++++++++++------- arch/x86/kvm/x86.c | 2 +- virt/kvm/coalesced_mmio.c | 25 +++++++++++++++---------- virt/kvm/ioapic.c | 22 +++++++++++++++------- virt/kvm/iodev.h | 29 ++++++++++++++++++++--------- virt/kvm/kvm_main.c | 2 +- 8 files changed, 109 insertions(+), 53 deletions(-)
arch/x86/kvm/i8254.c +28 -12
@@ -350,10 +350,20 @@ void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val)mutex_unlock (&kvm->arch.vpit->pit_state.lock); } +static inline struct kvm_pit *dev_to_pit (struct kvm_io_device *dev) +{ + return container_of(dev, struct kvm_pit, dev); +} + +static inline struct kvm_pit *speaker_to_pit (struct kvm_io_device *dev) +{ + return container_of(dev, struct kvm_pit, speaker_dev); +} +static void pit_ioport_write (struct kvm_io_device *this,gpa_t addr,int len,const void *data) { -struct kvm_pit *pit = (struct kvm_pit *)this->private; +struct kvm_pit *pit =dev_to_pit (this);struct kvm_kpit_state *pit_state = &pit->pit_state;struct kvm *kvm = pit->kvm;int channel, access;
@@ -426,7 +436,7 @@ static void pit_ioport_write(struct kvm_io_device *this,static void pit_ioport_read (struct kvm_io_device *this,gpa_t addr,int len,void *data) { -struct kvm_pit *pit = (struct kvm_pit *)this->private; +struct kvm_pit *pit =dev_to_pit (this);struct kvm_kpit_state *pit_state = &pit->pit_state;struct kvm *kvm = pit->kvm;int ret, count;
@@ -497,7 +507,7 @@ static int pit_in_range(struct kvm_io_device *this, gpa_t addr,static void speaker_ioport_write (struct kvm_io_device *this,gpa_t addr,int len,const void *data) { -struct kvm_pit *pit = (struct kvm_pit *)this->private; +struct kvm_pit *pit =speaker_to_pit (this);struct kvm_kpit_state *pit_state = &pit->pit_state;struct kvm *kvm = pit->kvm;u32 val = *(u32 *) data;
@@ -511,7 +521,7 @@ static void speaker_ioport_write(struct kvm_io_device *this,static void speaker_ioport_read (struct kvm_io_device *this,gpa_t addr,int len,void *data) { -struct kvm_pit *pit = (struct kvm_pit *)this->private; +struct kvm_pit *pit =speaker_to_pit (this);struct kvm_kpit_state *pit_state = &pit->pit_state;struct kvm *kvm = pit->kvm;unsigned int refresh_clock;
@@ -563,6 +573,18 @@ static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask) } } +static const struct kvm_io_device_ops pit_dev_ops = { + .read = pit_ioport_read, + .write = pit_ioport_write, + .in_range = pit_in_range, +}; + +static const struct kvm_io_device_ops speaker_dev_ops = { + .read = speaker_ioport_read, + .write = speaker_ioport_write, + .in_range = speaker_in_range, +}; +struct kvm_pit *kvm_create_pit (struct kvm *kvm,u32 flags) {struct kvm_pit *pit;
@@ -583,17 +605,11 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)spin_lock_init (&pit->pit_state.inject_lock);/* Initialize PIO device */ - pit->dev.read = pit_ioport_read; - pit->dev.write = pit_ioport_write; - pit->dev.in_range = pit_in_range; - pit->dev.private = pit; +kvm_iodevice_init (&pit->dev, &pit_dev_ops);kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev);if (flags &KVM_PIT_SPEAKER_DUMMY ) { - pit->speaker_dev.read = speaker_ioport_read; - pit->speaker_dev.write = speaker_ioport_write; - pit->speaker_dev.in_range = speaker_in_range; - pit->speaker_dev.private = pit; +kvm_iodevice_init (&pit->speaker_dev, &speaker_dev_ops);kvm_io_bus_register_dev (&kvm->pio_bus, &pit->speaker_dev); }
arch/x86/kvm/i8259.c +14 -6
@@ -444,10 +444,15 @@ static int picdev_in_range(struct kvm_io_device *this, gpa_t addr, } } +static inline struct kvm_pic *to_pic (struct kvm_io_device *dev) +{ + return container_of(dev, struct kvm_pic, dev); +} +static void picdev_write (struct kvm_io_device *this,gpa_t addr,int len,const void *val) { -struct kvm_pic *s = this->private; +struct kvm_pic *s =to_pic (this);unsigned char data = *(unsigned char *)val;if (len !=1 ) {
@@ -474,7 +479,7 @@ static void picdev_write(struct kvm_io_device *this,static void picdev_read (struct kvm_io_device *this,gpa_t addr,int len,void *val) { -struct kvm_pic *s = this->private; +struct kvm_pic *s =to_pic (this);unsigned char data =0 ;if (len !=1 ) {
@@ -516,6 +521,12 @@ static void pic_irq_request(void *opaque, int level) } } +static const struct kvm_io_device_ops picdev_ops = { + .read = picdev_read, + .write = picdev_write, + .in_range = picdev_in_range, +}; +struct kvm_pic *kvm_create_pic (struct kvm *kvm) {struct kvm_pic *s;
@@ -534,10 +545,7 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)/* * Initialize PIO device */ - s->dev.read = picdev_read; - s->dev.write = picdev_write; - s->dev.in_range = picdev_in_range; - s->dev.private = s; +kvm_iodevice_init (&s->dev, &picdev_ops);kvm_io_bus_register_dev (&kvm->pio_bus, &s->dev);return s; }
arch/x86/kvm/lapic.c +15 -7
@@ -522,10 +522,15 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)return val; } +static inline struct kvm_lapic *to_lapic (struct kvm_io_device *dev) +{ + return container_of(dev, struct kvm_lapic, dev); +} +static void apic_mmio_read (struct kvm_io_device *this,gpa_t address,int len,void *data) { -struct kvm_lapic *apic = (struct kvm_lapic *)this->private; +struct kvm_lapic *apic =to_lapic (this);unsigned int offset = address - apic->base_address;unsigned char alignment = offset &0xf ;u32 result;
@@ -606,7 +611,7 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)static void apic_mmio_write (struct kvm_io_device *this,gpa_t address,int len,const void *data) { -struct kvm_lapic *apic = (struct kvm_lapic *)this->private; +struct kvm_lapic *apic =to_lapic (this);unsigned int offset = address - apic->base_address;unsigned char alignment = offset &0xf ;u32 val;
@@ -723,7 +728,7 @@ static void apic_mmio_write(struct kvm_io_device *this,static int apic_mmio_range (struct kvm_io_device *this,gpa_t addr,int len,int size) { -struct kvm_lapic *apic = (struct kvm_lapic *)this->private; +struct kvm_lapic *apic =to_lapic (this);int ret =0 ;
@@ -917,6 +922,12 @@ static struct kvm_timer_ops lapic_timer_ops = { .is_periodic = lapic_is_periodic, }; +static const struct kvm_io_device_ops apic_mmio_ops = { + .read = apic_mmio_read, + .write = apic_mmio_write, + .in_range = apic_mmio_range, +}; +int kvm_create_lapic (struct kvm_vcpu *vcpu) {struct kvm_lapic *apic;
@@ -951,10 +962,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu) vcpu->arch.apic_base =APIC_DEFAULT_PHYS_BASE ;kvm_lapic_reset (vcpu); - apic->dev.read = apic_mmio_read; - apic->dev.write = apic_mmio_write; - apic->dev.in_range = apic_mmio_range; - apic->dev.private = apic; +kvm_iodevice_init (&apic->dev, &apic_mmio_ops);return 0 ; nomem_free_apic:
arch/x86/kvm/x86.c +1 -1
@@ -2264,7 +2264,7 @@ static struct kvm_io_device *vcpu_find_pervcpu_dev(struct kvm_vcpu *vcpu,if (vcpu->arch.apic) { dev = &vcpu->arch.apic->dev; -if (dev->in_range (dev, addr, len, is_write)) +if (kvm_iodevice_in_range (dev, addr, len, is_write))return dev; }return NULL ;
virt/kvm/coalesced_mmio.c +15 -10
@@ -14,11 +14,15 @@#include "coalesced_mmio.h" +static inline struct kvm_coalesced_mmio_dev *to_mmio (struct kvm_io_device *dev) +{ + return container_of(dev, struct kvm_coalesced_mmio_dev, dev); +} +static int coalesced_mmio_in_range (struct kvm_io_device *this,gpa_t addr,int len,int is_write) { -struct kvm_coalesced_mmio_dev *dev = - (struct kvm_coalesced_mmio_dev *)this->private; +struct kvm_coalesced_mmio_dev *dev =to_mmio (this);struct kvm_coalesced_mmio_zone *zone;int next;int i;
@@ -63,8 +67,7 @@ static int coalesced_mmio_in_range(struct kvm_io_device *this,static void coalesced_mmio_write (struct kvm_io_device *this,gpa_t addr,int len,const void *val) { -struct kvm_coalesced_mmio_dev *dev = - (struct kvm_coalesced_mmio_dev *)this->private; +struct kvm_coalesced_mmio_dev *dev =to_mmio (this);struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring;/* kvm->lock must be taken by caller before call to in_range()*/
@@ -80,12 +83,17 @@ static void coalesced_mmio_write(struct kvm_io_device *this,static void coalesced_mmio_destructor (struct kvm_io_device *this) { -struct kvm_coalesced_mmio_dev *dev = - (struct kvm_coalesced_mmio_dev *)this->private; +struct kvm_coalesced_mmio_dev *dev =to_mmio (this);kfree (dev); } +static const struct kvm_io_device_ops coalesced_mmio_ops = { + .write = coalesced_mmio_write, + .in_range = coalesced_mmio_in_range, + .destructor = coalesced_mmio_destructor, +}; +int kvm_coalesced_mmio_init (struct kvm *kvm) {struct kvm_coalesced_mmio_dev *dev;
@@ -93,10 +101,7 @@ int kvm_coalesced_mmio_init(struct kvm *kvm) dev =kzalloc (sizeof (struct kvm_coalesced_mmio_dev ),GFP_KERNEL );if (!dev)return -ENOMEM ; - dev->dev.write = coalesced_mmio_write; - dev->dev.in_range = coalesced_mmio_in_range; - dev->dev.destructor = coalesced_mmio_destructor; - dev->dev.private = dev; +kvm_iodevice_init (&dev->dev, &coalesced_mmio_ops); dev->kvm = kvm; kvm->coalesced_mmio_dev = dev;kvm_io_bus_register_dev (&kvm->mmio_bus, &dev->dev);
virt/kvm/ioapic.c +15 -7
@@ -220,10 +220,15 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode)__kvm_ioapic_update_eoi (ioapic, i, trigger_mode); } +static inline struct kvm_ioapic *to_ioapic (struct kvm_io_device *dev) +{ + return container_of(dev, struct kvm_ioapic, dev); +} +static int ioapic_in_range (struct kvm_io_device *this,gpa_t addr,int len,int is_write) { -struct kvm_ioapic *ioapic = (struct kvm_ioapic *)this->private; +struct kvm_ioapic *ioapic =to_ioapic (this);return ((addr >= ioapic->base_address && (addr < ioapic->base_address +IOAPIC_MEM_LENGTH )));
@@ -232,7 +237,7 @@ static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr,static void ioapic_mmio_read (struct kvm_io_device *this,gpa_t addr,int len,void *val) { -struct kvm_ioapic *ioapic = (struct kvm_ioapic *)this->private; +struct kvm_ioapic *ioapic =to_ioapic (this);u32 result;ioapic_debug ("addr %lx\n" , (unsigned long )addr);
@@ -269,7 +274,7 @@ static void ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,static void ioapic_mmio_write (struct kvm_io_device *this,gpa_t addr,int len,const void *val) { -struct kvm_ioapic *ioapic = (struct kvm_ioapic *)this->private; +struct kvm_ioapic *ioapic =to_ioapic (this);u32 data; ioapic_debug("ioapic_mmio_write addr=%p len=%d val=%p\n",
@@ -314,6 +319,12 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic) ioapic->id =0 ; } +static const struct kvm_io_device_ops ioapic_mmio_ops = { + .read = ioapic_mmio_read, + .write = ioapic_mmio_write, + .in_range = ioapic_in_range, +}; +int kvm_ioapic_init (struct kvm *kvm) {struct kvm_ioapic *ioapic;
@@ -323,10 +334,7 @@ int kvm_ioapic_init(struct kvm *kvm)return -ENOMEM ; kvm->arch.vioapic = ioapic;kvm_ioapic_reset (ioapic); - ioapic->dev.read = ioapic_mmio_read; - ioapic->dev.write = ioapic_mmio_write; - ioapic->dev.in_range = ioapic_in_range; - ioapic->dev.private = ioapic; +kvm_iodevice_init (&ioapic->dev, &ioapic_mmio_ops); ioapic->kvm = kvm;kvm_io_bus_register_dev (&kvm->mmio_bus, &ioapic->dev);return 0 ;
virt/kvm/iodev.h +20 -9
@@ -18,7 +18,9 @@#include <linux/kvm_types.h> -struct kvm_io_device { +struct kvm_io_device ; + +struct kvm_io_device_ops { void (*read)(struct kvm_io_device *this, gpa_t addr, int len,
@@ -30,16 +32,25 @@ struct kvm_io_device {int (*in_range)(struct kvm_io_device *this,gpa_t addr,int len,int is_write);void (*destructor)(struct kvm_io_device *this); +}; + -void *private; +struct kvm_io_device { +const struct kvm_io_device_ops *ops; }; +static inline void kvm_iodevice_init (struct kvm_io_device *dev, +const struct kvm_io_device_ops *ops) +{ + dev->ops = ops; +} +static inline void kvm_iodevice_read (struct kvm_io_device *dev,gpa_t addr,int len,void *val) { - dev->read (dev, addr, len, val); + dev->ops->read (dev, addr, len, val); } static inline void kvm_iodevice_write(struct kvm_io_device *dev,
@@ -47,19 +58,19 @@ static inline void kvm_iodevice_write(struct kvm_io_device *dev,int len, const void *val) { - dev->write(dev, addr, len, val); + dev->ops->write(dev, addr, len, val); } -static inline int kvm_iodevice_inrange (struct kvm_io_device *dev, -gpa_t addr,int len,int is_write) +static inline int kvm_iodevice_in_range (struct kvm_io_device *dev, +gpa_t addr,int len,int is_write) { -return dev->in_range (dev, addr, len, is_write); +return dev->ops->in_range (dev, addr, len, is_write); }static inline void kvm_iodevice_destructor (struct kvm_io_device *dev) { -if (dev->destructor) - dev->destructor (dev); +if (dev->ops->destructor) + dev->ops->destructor (dev); }#endif /* __KVM_IODEV_H__ */
virt/kvm/kvm_main.c +1 -1
@@ -2463,7 +2463,7 @@ struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus,for (i =0 ; i < bus->dev_count; i++) {struct kvm_io_device *pos = bus->devs[i]; -if (pos->in_range (pos, addr, len, is_write)) +if (kvm_iodevice_in_range (pos, addr, len, is_write))return pos; }
Signature · 1 line
1.6.3.3
PATCH 25/48 KVM: do not register i8254 PIO regions until we are initialized
In reply to Avi KivityFrom: Gregory Haskins <[email protected]>
We currently publish the i8254 resources to the pio_bus before the devices are fully initialized. Since we hold the pit_lock, its probably not a real issue. But lets clean this up anyway.
--- arch/x86/kvm/i8254.c | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-)
arch/x86/kvm/i8254.c +8 -9
@@ -604,15 +604,6 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)mutex_lock (&pit->pit_state.lock);spin_lock_init (&pit->pit_state.inject_lock); -/* Initialize PIO device */ -kvm_iodevice_init (&pit->dev, &pit_dev_ops); -kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); - -if (flags &KVM_PIT_SPEAKER_DUMMY ) { -kvm_iodevice_init (&pit->speaker_dev, &speaker_dev_ops); -kvm_io_bus_register_dev (&kvm->pio_bus, &pit->speaker_dev); - } - kvm->arch.vpit = pit; pit->kvm = kvm;
@@ -631,6 +622,14 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) pit->mask_notifier.func = pit_mask_notifer;kvm_register_irq_mask_notifier (kvm,0 , &pit->mask_notifier); +kvm_iodevice_init (&pit->dev, &pit_dev_ops); +kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); + +if (flags &KVM_PIT_SPEAKER_DUMMY ) { +kvm_iodevice_init (&pit->speaker_dev, &speaker_dev_ops); +kvm_io_bus_register_dev (&kvm->pio_bus, &pit->speaker_dev); + } +return pit; }
Signature · 1 line
1.6.3.3
PATCH 26/48 KVM: VMX: Avoid duplicate ept tlb flush when setting cr3
In reply to Avi Kivityvmx_set_cr3() will call vmx_tlb_flush(), which will flush the ept context. So there is no need to call ept_sync_context() explicitly.
--- arch/x86/kvm/vmx.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
arch/x86/kvm/vmx.c +0 -1
@@ -1651,7 +1651,6 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)if (enable_ept) { eptp =construct_eptp (cr3);vmcs_write64 (EPT_POINTER , eptp); -ept_sync_context (eptp);ept_load_pdptrs (vcpu); guest_cr3 =is_paging (vcpu) ? vcpu->arch.cr3 :VMX_EPT_IDENTITY_PAGETABLE_ADDR ;
Signature · 1 line
1.6.3.3
PATCH 27/48 KVM: VMX: Simplify pdptr and cr3 management
In reply to Avi KivityInstead of reading the PDPTRs from memory after every exit (which is slow and wrong, as the PDPTRs are stored on the cpu), sync the PDPTRs from memory to the VMCS before entry, and from the VMCS to memory after exit. Do the same for cr3.
--- arch/x86/kvm/vmx.c | 21 +++++++++++++++------ 1 files changed, 15 insertions(+), 6 deletions(-)
arch/x86/kvm/vmx.c +15 -6
@@ -1547,10 +1547,6 @@ static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)static void ept_load_pdptrs (struct kvm_vcpu *vcpu) {if (is_paging (vcpu) &&is_pae (vcpu) && !is_long_mode (vcpu)) { -if (!load_pdptrs (vcpu, vcpu->arch.cr3)) { -printk (KERN_ERR "EPT: Fail to load pdptrs!\n" ); -return ; - }vmcs_write64 (GUEST_PDPTR0 , vcpu->arch.pdptrs[0 ]);vmcs_write64 (GUEST_PDPTR1 , vcpu->arch.pdptrs[1 ]);vmcs_write64 (GUEST_PDPTR2 , vcpu->arch.pdptrs[2 ]);
@@ -1558,6 +1554,16 @@ static void ept_load_pdptrs(struct kvm_vcpu *vcpu) } } +static void ept_save_pdptrs (struct kvm_vcpu *vcpu) +{ +if (is_paging (vcpu) &&is_pae (vcpu) && !is_long_mode (vcpu)) { + vcpu->arch.pdptrs[0 ] =vmcs_read64 (GUEST_PDPTR0 ); + vcpu->arch.pdptrs[1 ] =vmcs_read64 (GUEST_PDPTR1 ); + vcpu->arch.pdptrs[2 ] =vmcs_read64 (GUEST_PDPTR2 ); + vcpu->arch.pdptrs[3 ] =vmcs_read64 (GUEST_PDPTR3 ); + } +} +static void vmx_set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4); static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
@@ -1651,7 +1657,6 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)if (enable_ept) { eptp =construct_eptp (cr3);vmcs_write64 (EPT_POINTER , eptp); -ept_load_pdptrs (vcpu); guest_cr3 =is_paging (vcpu) ? vcpu->arch.cr3 :VMX_EPT_IDENTITY_PAGETABLE_ADDR ; }
@@ -3252,7 +3257,7 @@ static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)* to sync with guest real CR3. */ if (enable_ept &&is_paging (vcpu)) { vcpu->arch.cr3 =vmcs_readl (GUEST_CR3 ); -ept_load_pdptrs (vcpu); +ept_save_pdptrs (vcpu); }if (unlikely (vmx->fail)) {
@@ -3437,6 +3442,10 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) {struct vcpu_vmx *vmx =to_vmx (vcpu); +if (enable_ept &&is_paging (vcpu)) { +vmcs_writel (GUEST_CR3 , vcpu->arch.cr3); +ept_load_pdptrs (vcpu); + }/* Record the guest's net vcpu time for enforced NMI injections. */ if (unlikely (!cpu_has_virtual_nmis () && vmx->soft_vnmi_blocked)) vmx->entry_time =ktime_get ();
Signature · 1 line
1.6.3.3
PATCH 28/48 KVM: Cache pdptrs
In reply to Avi KivityInstead of reloading the pdptrs on every entry and exit (vmcs writes on vmx, guest memory access on svm) extract them on demand.
--- arch/x86/include/asm/kvm_host.h | 4 ++++ arch/x86/kvm/kvm_cache_regs.h | 9 +++++++++ arch/x86/kvm/mmu.c | 7 +++++-- arch/x86/kvm/paging_tmpl.h | 2 +- arch/x86/kvm/svm.c | 24 ++++++++++++++++++------ arch/x86/kvm/vmx.c | 22 ++++++++++++++++++---- arch/x86/kvm/x86.c | 8 ++++++++ 7 files changed, 63 insertions(+), 13 deletions(-)
arch/x86/include/asm/kvm_host.h +4 -0
@@ -120,6 +120,10 @@ enum kvm_reg {NR_VCPU_REGS }; +enum kvm_reg_ex { +VCPU_EXREG_PDPTR =NR_VCPU_REGS , +}; +enum {VCPU_SREG_ES ,VCPU_SREG_CS ,
arch/x86/kvm/kvm_cache_regs.h +9 -0
@@ -29,4 +29,13 @@ static inline void kvm_rip_write(struct kvm_vcpu *vcpu, unsigned long val) kvm_register_write(vcpu, VCPU_REGS_RIP, val); } +static inline u64 kvm_pdptr_read (struct kvm_vcpu *vcpu,int index) +{ +if (!test_bit (VCPU_EXREG_PDPTR , + (unsigned long *)&vcpu->arch.regs_avail)) + kvm_x86_ops->cache_reg (vcpu,VCPU_EXREG_PDPTR ); + +return vcpu->arch.pdptrs[index]; +} +#endif
arch/x86/kvm/mmu.c +5 -2
@@ -18,6 +18,7 @@*/ #include "mmu.h" +#include "kvm_cache_regs.h" #include <linux/kvm_host.h> #include <linux/types.h>
@@ -1954,6 +1955,7 @@ static int mmu_alloc_roots(struct kvm_vcpu *vcpu)gfn_t root_gfn;struct kvm_mmu_page *sp;int direct =0 ; +u64 pdptr; root_gfn = vcpu->arch.cr3 >>PAGE_SHIFT ;
@@ -1981,11 +1983,12 @@ static int mmu_alloc_roots(struct kvm_vcpu *vcpu)ASSERT (!VALID_PAGE (root));if (vcpu->arch.mmu.root_level ==PT32E_ROOT_LEVEL ) { -if (!is_present_pte (vcpu->arch.pdptrs[i])) { + pdptr =kvm_pdptr_read (vcpu, i); +if (!is_present_pte (pdptr)) { vcpu->arch.mmu.pae_root[i] =0 ;continue ; } - root_gfn = vcpu->arch.pdptrs[i] >>PAGE_SHIFT ; + root_gfn = pdptr >>PAGE_SHIFT ; }else if (vcpu->arch.mmu.root_level ==0 ) root_gfn =0 ;if (mmu_check_root (vcpu, root_gfn))
arch/x86/kvm/paging_tmpl.h +1 -1
@@ -131,7 +131,7 @@ walk: pte = vcpu->arch.cr3;#if PTTYPE ==64 if (!is_long_mode (vcpu)) { - pte = vcpu->arch.pdptrs[(addr >>30 ) &3 ]; + pte =kvm_pdptr_read (vcpu, (addr >>30 ) &3 );if (!is_present_pte (pte)) goto not_present; --walker->level;
arch/x86/kvm/svm.c +18 -6
@@ -780,6 +780,18 @@ static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)to_svm (vcpu)->vmcb->save.rflags = rflags; } +static void svm_cache_reg (struct kvm_vcpu *vcpu,enum kvm_reg reg) +{ +switch (reg) { +case VCPU_EXREG_PDPTR : +BUG_ON (!npt_enabled); +load_pdptrs (vcpu, vcpu->arch.cr3); +break ; +default : +BUG (); + } +} +static void svm_set_vintr (struct vcpu_svm *svm) { svm->vmcb->control.intercept |=1ULL <<INTERCEPT_VINTR ;
@@ -2286,12 +2298,6 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) } vcpu->arch.cr0 = svm->vmcb->save.cr0; vcpu->arch.cr3 = svm->vmcb->save.cr3; -if (is_paging (vcpu) &&is_pae (vcpu) && !is_long_mode (vcpu)) { -if (!load_pdptrs (vcpu, vcpu->arch.cr3)) { -kvm_inject_gp (vcpu,0 ); -return 1 ; - } - }if (mmu_reload) {kvm_mmu_reset_context (vcpu);kvm_mmu_load (vcpu);
@@ -2642,6 +2648,11 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) svm->next_rip =0 ; +if (npt_enabled) { + vcpu->arch.regs_avail &= ~(1 <<VCPU_EXREG_PDPTR ); + vcpu->arch.regs_dirty &= ~(1 <<VCPU_EXREG_PDPTR ); + } +svm_complete_interrupts (svm); }
@@ -2750,6 +2761,7 @@ static struct kvm_x86_ops svm_x86_ops = { .set_gdt = svm_set_gdt, .get_dr = svm_get_dr, .set_dr = svm_set_dr, + .cache_reg = svm_cache_reg, .get_rflags = svm_get_rflags, .set_rflags = svm_set_rflags,
arch/x86/kvm/vmx.c +18 -4
@@ -161,6 +161,8 @@ static struct kvm_vmx_segment_field { VMX_SEGMENT_FIELD(LDTR), }; +static void ept_save_pdptrs (struct kvm_vcpu *vcpu); +/* * Keep MSR_K6_STAR at the end, as setup_msrs() will try to optimize it * away by decrementing the array size.
@@ -1047,6 +1049,10 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)case VCPU_REGS_RIP : vcpu->arch.regs[VCPU_REGS_RIP ] =vmcs_readl (GUEST_RIP );break ; +case VCPU_EXREG_PDPTR : +if (enable_ept) +ept_save_pdptrs (vcpu); +break ;default :break ; }
@@ -1546,6 +1552,10 @@ static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)static void ept_load_pdptrs (struct kvm_vcpu *vcpu) { +if (!test_bit (VCPU_EXREG_PDPTR , + (unsigned long *)&vcpu->arch.regs_dirty)) +return ; +if (is_paging (vcpu) &&is_pae (vcpu) && !is_long_mode (vcpu)) {vmcs_write64 (GUEST_PDPTR0 , vcpu->arch.pdptrs[0 ]);vmcs_write64 (GUEST_PDPTR1 , vcpu->arch.pdptrs[1 ]);
@@ -1562,6 +1572,11 @@ static void ept_save_pdptrs(struct kvm_vcpu *vcpu) vcpu->arch.pdptrs[2 ] =vmcs_read64 (GUEST_PDPTR2 ); vcpu->arch.pdptrs[3 ] =vmcs_read64 (GUEST_PDPTR3 ); } + +__set_bit (VCPU_EXREG_PDPTR , + (unsigned long *)&vcpu->arch.regs_avail); +__set_bit (VCPU_EXREG_PDPTR , + (unsigned long *)&vcpu->arch.regs_dirty); }static void vmx_set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4);
@@ -3255,10 +3270,8 @@ static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)/* Access CR3 don't cause VMExit in paging mode, so we need * to sync with guest real CR3. */ -if (enable_ept &&is_paging (vcpu)) { +if (enable_ept &&is_paging (vcpu)) vcpu->arch.cr3 =vmcs_readl (GUEST_CR3 ); -ept_save_pdptrs (vcpu); - }if (unlikely (vmx->fail)) { kvm_run->exit_reason =KVM_EXIT_FAIL_ENTRY ;
@@ -3567,7 +3580,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)#endif ); - vcpu->arch.regs_avail = ~((1 <<VCPU_REGS_RIP ) | (1 <<VCPU_REGS_RSP )); + vcpu->arch.regs_avail = ~((1 <<VCPU_REGS_RIP ) | (1 <<VCPU_REGS_RSP ) + | (1 <<VCPU_EXREG_PDPTR )); vcpu->arch.regs_dirty =0 ;get_debugreg (vcpu->arch.dr6,6 );
arch/x86/kvm/x86.c +8 -0
@@ -246,6 +246,10 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3) ret =1 ;memcpy (vcpu->arch.pdptrs, pdpte,sizeof (vcpu->arch.pdptrs)); +__set_bit (VCPU_EXREG_PDPTR , + (unsigned long *)&vcpu->arch.regs_avail); +__set_bit (VCPU_EXREG_PDPTR , + (unsigned long *)&vcpu->arch.regs_dirty); out:return ret;
@@ -261,6 +265,10 @@ static bool pdptrs_changed(struct kvm_vcpu *vcpu)if (is_long_mode (vcpu) || !is_pae (vcpu))return false; +if (!test_bit (VCPU_EXREG_PDPTR , + (unsigned long *)&vcpu->arch.regs_avail)) +return true; + r =kvm_read_guest (vcpu->kvm, vcpu->arch.cr3 & ~31u , pdpte,sizeof (pdpte));if (r <0 ) goto out;
Signature · 1 line
1.6.3.3
PATCH 29/48 KVM: VMX: Fix reporting of unhandled EPT violations
In reply to Avi KivityInstead of returning -ENOTSUPP, exit normally but indicate the hardware exit reason.
--- arch/x86/kvm/vmx.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kvm/vmx.c +2 -2
@@ -3153,8 +3153,8 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)printk (KERN_ERR "EPT: Exit qualification is 0x%lx\n" , (long unsigned int )exit_qualification); kvm_run->exit_reason =KVM_EXIT_UNKNOWN ; - kvm_run->hw.hardware_exit_reason =0 ; -return -ENOTSUPP ; + kvm_run->hw.hardware_exit_reason =EXIT_REASON_EPT_VIOLATION ; +return 0 ; } gpa =vmcs_read64 (GUEST_PHYSICAL_ADDRESS );
Signature · 1 line
1.6.3.3
PATCH 30/48 KVM: Calculate available entries in coalesced mmio ring
In reply to Avi KivityInstead of checking whether we'll wrap around, calculate how many entries are available, and check whether we have enough (just one) for the pending mmio.
By itself, this doesn't change anything, but it paves the way for making this function lockless.
--- virt/kvm/coalesced_mmio.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
virt/kvm/coalesced_mmio.c +5 -5
@@ -24,7 +24,8 @@ static int coalesced_mmio_in_range(struct kvm_io_device *this, {struct kvm_coalesced_mmio_dev *dev =to_mmio (this);struct kvm_coalesced_mmio_zone *zone; -int next; +struct kvm_coalesced_mmio_ring *ring; +unsigned avail;int i;if (!is_write)
@@ -40,10 +41,9 @@ static int coalesced_mmio_in_range(struct kvm_io_device *this,* check if we don't meet the first used entry * there is always one unused entry in the buffer */ - - next = (dev->kvm->coalesced_mmio_ring->last +1 ) % -KVM_COALESCED_MMIO_MAX ; -if (next == dev->kvm->coalesced_mmio_ring->first) { + ring = dev->kvm->coalesced_mmio_ring; + avail = (ring->first - ring->last -1 ) %KVM_COALESCED_MMIO_MAX ; +if (avail <1 ) {/* full */ return 0 ; }
Signature · 1 line
1.6.3.3
PATCH 31/48 KVM: ppc: e500: Move to Book-3e MMU definitions
In reply to Avi KivityFrom: Liu Yu <[email protected]>
According to commit 70fe3af8403f85196bb74f22ce4813db7dfedc1a.
--- arch/powerpc/kvm/e500_tlb.c | 10 +++++----- arch/powerpc/kvm/e500_tlb.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-)
arch/powerpc/kvm/e500_tlb.c +5 -5
@@ -269,7 +269,7 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu, tlbsel = (vcpu_e500->mas4 >>28 ) &0x1 ; victim = (tlbsel ==0 ) ?tlb0_get_next_victim (vcpu_e500) :0 ; pidsel = (vcpu_e500->mas4 >>16 ) &0xf ; - tsized = (vcpu_e500->mas4 >>8 ) &0xf ; + tsized = (vcpu_e500->mas4 >>7 ) &0x1f ; vcpu_e500->mas0 =MAS0_TLBSEL (tlbsel) |MAS0_ESEL (victim) |MAS0_NV (vcpu_e500->guest_tlb_nv[tlbsel]);
@@ -309,7 +309,7 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, vcpu_e500->shadow_pages[tlbsel][esel] = new_page;/* Force TS=1 IPROT=0 TSIZE=4KB for all guest mappings. */ - stlbe->mas1 =MAS1_TSIZE (BOOKE_PAGESZ_4K ) + stlbe->mas1 =MAS1_TSIZE (BOOK3E_PAGESZ_4K ) |MAS1_TID (get_tlb_tid (gtlbe)) |MAS1_TS |MAS1_VALID ; stlbe->mas2 = (gvaddr &MAS2_EPN ) | e500_shadow_mas2_attrib(gtlbe->mas2,
@@ -545,7 +545,7 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)case 0 :/* TLB0 */ gtlbe->mas1 &= ~MAS1_TSIZE (~0 ); - gtlbe->mas1 |=MAS1_TSIZE (BOOKE_PAGESZ_4K ); + gtlbe->mas1 |=MAS1_TSIZE (BOOK3E_PAGESZ_4K ); stlbsel =0 ; sesel =kvmppc_e500_stlbe_map (vcpu_e500,0 , esel);
@@ -679,14 +679,14 @@ void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500)/* Insert large initial mapping for guest. */ tlbe = &vcpu_e500->guest_tlb[1 ][0 ]; - tlbe->mas1 =MAS1_VALID |MAS1_TSIZE (BOOKE_PAGESZ_256M ); + tlbe->mas1 =MAS1_VALID |MAS1_TSIZE (BOOK3E_PAGESZ_256M ); tlbe->mas2 =0 ; tlbe->mas3 =E500_TLB_SUPER_PERM_MASK ; tlbe->mas7 =0 ;/* 4K map for serial output. Used by kernel wrapper. */ tlbe = &vcpu_e500->guest_tlb[1 ][1 ]; - tlbe->mas1 =MAS1_VALID |MAS1_TSIZE (BOOKE_PAGESZ_4K ); + tlbe->mas1 =MAS1_VALID |MAS1_TSIZE (BOOK3E_PAGESZ_4K ); tlbe->mas2 = (0xe0004500 &0xFFFFF000 ) |MAS2_I |MAS2_G ; tlbe->mas3 = (0xe0004500 &0xFFFFF000 ) |E500_TLB_SUPER_PERM_MASK ; tlbe->mas7 =0 ;
arch/powerpc/kvm/e500_tlb.h +3 -3
@@ -16,7 +16,7 @@#define __KVM_E500_TLB_H__#include <linux/kvm_host.h> -#include <asm/mmu-fsl-booke.h> +#include <asm/mmu-book3e.h> #include <asm/tlb.h> #include <asm/kvm_e500.h>
@@ -59,7 +59,7 @@ extern void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *);/* TLB helper functions */ static inline unsigned int get_tlb_size (const struct tlbe *tlbe) { -return (tlbe->mas1 >>8 ) &0xf ; +return (tlbe->mas1 >>7 ) &0x1f ; }static inline gva_t get_tlb_eaddr (const struct tlbe *tlbe)
@@ -70,7 +70,7 @@ static inline gva_t get_tlb_eaddr(const struct tlbe *tlbe)static inline u64 get_tlb_bytes (const struct tlbe *tlbe) {unsigned int pgsize =get_tlb_size (tlbe); -return 1ULL <<10 << (pgsize <<1 ); +return 1ULL <<10 << pgsize; }static inline gva_t get_tlb_end (const struct tlbe *tlbe)
Signature · 1 line
1.6.3.3
PATCH 32/48 KVM: ppc: e500: Directly pass pvr to guest
In reply to Avi KivityFrom: Liu Yu <[email protected]>
--- arch/powerpc/include/asm/kvm_host.h | 1 - arch/powerpc/kvm/e500.c | 3 --- arch/powerpc/kvm/emulate.c | 2 +- 3 files changed, 1 insertions(+), 5 deletions(-)
arch/powerpc/include/asm/kvm_host.h +0 -1
@@ -153,7 +153,6 @@ struct kvm_vcpu_arch {u32 pid;u32 swap_pid; -u32 pvr;u32 ccr0;u32 ccr1;u32 dbcr0;
arch/powerpc/kvm/e500.c +0 -3
@@ -60,9 +60,6 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)kvmppc_e500_tlb_setup (vcpu_e500); -/* Use the same core vertion as host's */ - vcpu->arch.pvr =mfspr (SPRN_PVR ); -return 0 ; }
arch/powerpc/kvm/emulate.c +1 -1
@@ -187,7 +187,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)case SPRN_SRR1 : vcpu->arch.gpr[rt] = vcpu->arch.srr1;break ;case SPRN_PVR : - vcpu->arch.gpr[rt] = vcpu->arch.pvr;break ; + vcpu->arch.gpr[rt] =mfspr (SPRN_PVR );break ;/* Note: mftb and TBRL/TBWL are user-accessible, so * the guest can always access the real TB anyways.
Signature · 1 line
1.6.3.3
PATCH 33/48 KVM: ppc: e500: Add MMUCFG and PVR emulation
In reply to Avi KivityFrom: Liu Yu <[email protected]>
Latest kernel started to use these two registers.
--- arch/powerpc/kvm/e500_emulate.c | 3 +++ arch/powerpc/kvm/emulate.c | 2 ++ 2 files changed, 5 insertions(+), 0 deletions(-)
arch/powerpc/kvm/e500_emulate.c +3 -0
@@ -180,6 +180,9 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)case SPRN_MMUCSR0 : vcpu->arch.gpr[rt] =0 ;break ; +case SPRN_MMUCFG : + vcpu->arch.gpr[rt] =mfspr (SPRN_MMUCFG );break ; +/* extra exceptions */ case SPRN_IVOR32 : vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL ];
arch/powerpc/kvm/emulate.c +2 -0
@@ -188,6 +188,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) vcpu->arch.gpr[rt] = vcpu->arch.srr1;break ;case SPRN_PVR : vcpu->arch.gpr[rt] =mfspr (SPRN_PVR );break ; +case SPRN_PIR : + vcpu->arch.gpr[rt] =mfspr (SPRN_PIR );break ;/* Note: mftb and TBRL/TBWL are user-accessible, so * the guest can always access the real TB anyways.
Signature · 1 line
1.6.3.3
PATCH 34/48 KVM: Cleanup LAPIC interface
In reply to Avi KivityFrom: Jan Kiszka <[email protected]>
None of the interface services the LAPIC emulation provides need to be exported to modules, and kvm_lapic_get_base is even totally unused today.
--- arch/x86/kvm/lapic.c | 12 ------------ 1 files changed, 0 insertions(+), 12 deletions(-)
arch/x86/kvm/lapic.c +0 -12
@@ -194,7 +194,6 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)return highest_irr; } -EXPORT_SYMBOL_GPL (kvm_lapic_find_highest_irr);static int __apic_accept_irq (struct kvm_lapic *apic,int delivery_mode,int vector,int level,int trig_mode);
@@ -768,7 +767,6 @@ void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)apic_set_tpr (apic, ((cr8 &0x0f ) <<4 ) | (apic_get_reg (apic,APIC_TASKPRI ) &4 )); } -EXPORT_SYMBOL_GPL (kvm_lapic_set_tpr);u64 kvm_lapic_get_cr8 (struct kvm_vcpu *vcpu) {
@@ -781,7 +779,6 @@ 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) {
@@ -805,12 +802,6 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value) } -u64 kvm_lapic_get_base (struct kvm_vcpu *vcpu) -{ -return vcpu->arch.apic_base; -} -EXPORT_SYMBOL_GPL (kvm_lapic_get_base); -void kvm_lapic_reset (struct kvm_vcpu *vcpu) {struct kvm_lapic *apic;
@@ -860,7 +851,6 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) vcpu,kvm_apic_id (apic), vcpu->arch.apic_base, apic->base_address); } -EXPORT_SYMBOL_GPL (kvm_lapic_reset);bool kvm_apic_present (struct kvm_vcpu *vcpu) {
@@ -871,7 +861,6 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu) {return kvm_apic_present (vcpu) &&apic_sw_enabled (vcpu->arch.apic); } -EXPORT_SYMBOL_GPL (kvm_lapic_enabled);/* *----------------------------------------------------------------------
@@ -970,7 +959,6 @@ nomem_free_apic: nomem:return -ENOMEM ; } -EXPORT_SYMBOL_GPL (kvm_create_lapic);int kvm_apic_has_interrupt (struct kvm_vcpu *vcpu) {
Signature · 1 line
1.6.3.3
PATCH 35/48 KVM: Grab pic lock in kvm_pic_clear_isr_ack
In reply to Avi KivityFrom: Marcelo Tosatti <[email protected]>
isr_ack is protected by kvm_pic->lock.
--- arch/x86/kvm/i8259.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/x86/kvm/i8259.c +2 -0
@@ -72,8 +72,10 @@ static void pic_clear_isr(struct kvm_kpic_state *s, int irq)void kvm_pic_clear_isr_ack (struct kvm *kvm) {struct kvm_pic *s =pic_irqchip (kvm); +pic_lock (s); s->pics[0 ].isr_ack =0xff ; s->pics[1 ].isr_ack =0xff ; +pic_unlock (s); }/*
Signature · 1 line
1.6.3.3
PATCH 36/48 KVM: move coalesced_mmio locking to its own device
In reply to Avi KivityFrom: Marcelo Tosatti <[email protected]>
Move coalesced_mmio locking to its own device, instead of relying on kvm->lock.
--- virt/kvm/coalesced_mmio.c | 10 ++++------ virt/kvm/coalesced_mmio.h | 1 + 2 files changed, 5 insertions(+), 6 deletions(-)
virt/kvm/coalesced_mmio.c +4 -6
@@ -31,10 +31,6 @@ static int coalesced_mmio_in_range(struct kvm_io_device *this,if (!is_write)return 0 ; -/* kvm->lock is taken by the caller and must be not released before -* dev.read/write -*/ -/* Are we able to batch it ? */ /* last is the first free entry
@@ -43,7 +39,7 @@ static int coalesced_mmio_in_range(struct kvm_io_device *this,*/ ring = dev->kvm->coalesced_mmio_ring; avail = (ring->first - ring->last -1 ) %KVM_COALESCED_MMIO_MAX ; -if (avail <1 ) { +if (avail <KVM_MAX_VCPUS ) {/* full */ return 0 ; }
@@ -70,7 +66,7 @@ static void coalesced_mmio_write(struct kvm_io_device *this,struct kvm_coalesced_mmio_dev *dev =to_mmio (this);struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring; -/* kvm->lock must be taken by caller before call to in_range()*/ +spin_lock (&dev->lock);/* copy data in first free entry of the ring */
@@ -79,6 +75,7 @@ static void coalesced_mmio_write(struct kvm_io_device *this,memcpy (ring->coalesced_mmio[ring->last].data, val, len);smp_wmb (); ring->last = (ring->last +1 ) %KVM_COALESCED_MMIO_MAX ; +spin_unlock (&dev->lock); }static void coalesced_mmio_destructor (struct kvm_io_device *this)
@@ -101,6 +98,7 @@ int kvm_coalesced_mmio_init(struct kvm *kvm) dev =kzalloc (sizeof (struct kvm_coalesced_mmio_dev ),GFP_KERNEL );if (!dev)return -ENOMEM ; +spin_lock_init (&dev->lock);kvm_iodevice_init (&dev->dev, &coalesced_mmio_ops); dev->kvm = kvm; kvm->coalesced_mmio_dev = dev;
virt/kvm/coalesced_mmio.h +1 -0
@@ -12,6 +12,7 @@struct kvm_coalesced_mmio_dev {struct kvm_io_device dev;struct kvm *kvm; +spinlock_t lock;int nb_zones;struct kvm_coalesced_mmio_zone zone[KVM_COALESCED_MMIO_ZONE_MAX ]; };
Signature · 1 line
1.6.3.3
PATCH 37/48 KVM: introduce irq_lock, use it to protect ioapic
In reply to Avi KivityFrom: Marcelo Tosatti <[email protected]>
Introduce irq_lock, and use to protect ioapic data structures.
--- include/linux/kvm_host.h | 3 ++- virt/kvm/ioapic.c | 5 +++++ virt/kvm/kvm_main.c | 1 + 3 files changed, 8 insertions(+), 1 deletions(-)
include/linux/kvm_host.h +2 -1
@@ -124,7 +124,6 @@ struct kvm_kernel_irq_routing_entry { };struct kvm { -struct mutex lock;/* protects the vcpus array and APIC accesses */ spinlock_t mmu_lock;spinlock_t requests_lock;struct rw_semaphore slots_lock;
@@ -134,6 +133,7 @@ struct kvm { KVM_PRIVATE_MEM_SLOTS];struct kvm_vcpu *vcpus[KVM_MAX_VCPUS ];struct list_head vm_list; +struct mutex lock;struct kvm_io_bus mmio_bus;struct kvm_io_bus pio_bus;#ifdef CONFIG_HAVE_KVM_EVENTFD
@@ -150,6 +150,7 @@ struct kvm {struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;#endif +struct mutex irq_lock;#ifdef CONFIG_HAVE_KVM_IRQCHIP struct list_head irq_routing;/* of kvm_kernel_irq_routing_entry */ struct hlist_head mask_notifier_list;
virt/kvm/ioapic.c +5 -0
@@ -243,6 +243,7 @@ static void ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,ioapic_debug ("addr %lx\n" , (unsigned long )addr);ASSERT (!(addr &0xf ));/* check alignment */ +mutex_lock (&ioapic->kvm->irq_lock); addr &=0xff ;switch (addr) {case IOAPIC_REG_SELECT :
@@ -269,6 +270,7 @@ static void ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,default :printk (KERN_WARNING "ioapic: wrong length %d\n" , len); } +mutex_unlock (&ioapic->kvm->irq_lock); } static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,
@@ -280,6 +282,8 @@ static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,ioapic_debug ("ioapic_mmio_write addr=%p len=%d val=%p\n" , (void *)addr, len, val);ASSERT (!(addr &0xf ));/* check alignment */ + +mutex_lock (&ioapic->kvm->irq_lock);if (len ==4 || len ==8 ) data = *(u32 *) val;else {
@@ -305,6 +309,7 @@ static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,default :break ; } +mutex_unlock (&ioapic->kvm->irq_lock); }void kvm_ioapic_reset (struct kvm_ioapic *ioapic)
virt/kvm/kvm_main.c +1 -0
@@ -982,6 +982,7 @@ static struct kvm *kvm_create_vm(void)kvm_io_bus_init (&kvm->pio_bus);kvm_irqfd_init (kvm);mutex_init (&kvm->lock); +mutex_init (&kvm->irq_lock);kvm_io_bus_init (&kvm->mmio_bus);init_rwsem (&kvm->slots_lock);atomic_set (&kvm->users_count,1 );
Signature · 1 line
1.6.3.3
PATCH 38/48 KVM: switch irq injection/acking data structures to irq_lock
In reply to Avi KivityFrom: Marcelo Tosatti <[email protected]>
Protect irq injection/acking data structures with a separate irq_lock mutex. This fixes the following deadlock:
CPU A CPU Bkvm_vm_ioctl_deassign_dev_irq()
mutex_lock(&kvm->lock); worker_thread()
-> kvm_deassign_irq() -> kvm_assigned_dev_interrupt_work_handler()
-> deassign_host_irq() mutex_lock(&kvm->lock);
-> cancel_work_sync() [blocked][gleb: fix ia64 path]
--- arch/ia64/kvm/kvm-ia64.c | 4 ++-- arch/x86/kvm/i8254.c | 4 ++-- arch/x86/kvm/lapic.c | 4 ++++ arch/x86/kvm/x86.c | 19 +++++++++---------- include/linux/kvm_host.h | 3 ++- virt/kvm/eventfd.c | 4 ++-- virt/kvm/irq_comm.c | 34 ++++++++++++++++++++++++++++------ virt/kvm/kvm_main.c | 16 +++++++++------- 8 files changed, 58 insertions(+), 30 deletions(-)
arch/ia64/kvm/kvm-ia64.c +2 -2
@@ -1000,10 +1000,10 @@ long kvm_arch_vm_ioctl(struct file *filp, goto out;if (irqchip_in_kernel (kvm)) {__s32 status; -mutex_lock (&kvm->lock); +mutex_lock (&kvm->irq_lock); status =kvm_set_irq (kvm,KVM_USERSPACE_IRQ_SOURCE_ID , irq_event.irq, irq_event.level); -mutex_unlock (&kvm->lock); +mutex_unlock (&kvm->irq_lock);if (ioctl ==KVM_IRQ_LINE_STATUS ) { irq_event.status = status; if (copy_to_user(argp, &irq_event,
arch/x86/kvm/i8254.c +2 -2
@@ -654,10 +654,10 @@ static void __inject_pit_timer_intr(struct kvm *kvm)struct kvm_vcpu *vcpu;int i; -mutex_lock (&kvm->lock); +mutex_lock (&kvm->irq_lock);kvm_set_irq (kvm, kvm->arch.vpit->irq_source_id,0 ,1 );kvm_set_irq (kvm, kvm->arch.vpit->irq_source_id,0 ,0 ); -mutex_unlock (&kvm->lock); +mutex_unlock (&kvm->irq_lock);/* * Provides NMI watchdog support via Virtual Wire mode.
arch/x86/kvm/lapic.c +4 -0
@@ -424,7 +424,9 @@ static void apic_set_eoi(struct kvm_lapic *apic) trigger_mode =IOAPIC_LEVEL_TRIG ; else trigger_mode =IOAPIC_EDGE_TRIG ; +mutex_lock (&apic->vcpu->kvm->irq_lock);kvm_ioapic_update_eoi (apic->vcpu->kvm, vector, trigger_mode); +mutex_unlock (&apic->vcpu->kvm->irq_lock); }static void apic_send_ipi (struct kvm_lapic *apic)
@@ -448,7 +450,9 @@ static void apic_send_ipi(struct kvm_lapic *apic) irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode, irq.vector); +mutex_lock (&apic->vcpu->kvm->irq_lock);kvm_irq_delivery_to_apic (apic->vcpu->kvm, apic, &irq); +mutex_unlock (&apic->vcpu->kvm->irq_lock); }static u32 apic_get_tmcct (struct kvm_lapic *apic)
arch/x86/kvm/x86.c +9 -10
@@ -2136,10 +2136,10 @@ long kvm_arch_vm_ioctl(struct file *filp, goto out;if (irqchip_in_kernel (kvm)) {__s32 status; -mutex_lock (&kvm->lock); +mutex_lock (&kvm->irq_lock); status =kvm_set_irq (kvm,KVM_USERSPACE_IRQ_SOURCE_ID , irq_event.irq, irq_event.level); -mutex_unlock (&kvm->lock); +mutex_unlock (&kvm->irq_lock);if (ioctl ==KVM_IRQ_LINE_STATUS ) { irq_event.status = status; if (copy_to_user(argp, &irq_event,
@@ -2385,12 +2385,11 @@ mmio:*/ mutex_lock (&vcpu->kvm->lock); mmio_dev =vcpu_find_mmio_dev (vcpu, gpa, bytes,0 ); +mutex_unlock (&vcpu->kvm->lock);if (mmio_dev) {kvm_iodevice_read (mmio_dev, gpa, bytes, val); -mutex_unlock (&vcpu->kvm->lock);return X86EMUL_CONTINUE ; } -mutex_unlock (&vcpu->kvm->lock); vcpu->mmio_needed =1 ; vcpu->mmio_phys_addr = gpa;
@@ -2440,12 +2439,11 @@ mmio:*/ mutex_lock (&vcpu->kvm->lock); mmio_dev =vcpu_find_mmio_dev (vcpu, gpa, bytes,1 ); +mutex_unlock (&vcpu->kvm->lock);if (mmio_dev) {kvm_iodevice_write (mmio_dev, gpa, bytes, val); -mutex_unlock (&vcpu->kvm->lock);return X86EMUL_CONTINUE ; } -mutex_unlock (&vcpu->kvm->lock); vcpu->mmio_needed =1 ; vcpu->mmio_phys_addr = gpa;
@@ -2768,7 +2766,6 @@ 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->arch.pio.in) kvm_iodevice_read(pio_dev, vcpu->arch.pio.port, vcpu->arch.pio.size,
@@ -2777,7 +2774,6 @@ static void kernel_pio(struct kvm_io_device *pio_dev,kvm_iodevice_write (pio_dev, vcpu->arch.pio.port, vcpu->arch.pio.size, pd); -mutex_unlock (&vcpu->kvm->lock); } static void pio_string_write(struct kvm_io_device *pio_dev,
@@ -2787,14 +2783,12 @@ static void pio_string_write(struct kvm_io_device *pio_dev,void *pd = vcpu->arch.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); } static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu,
@@ -2831,7 +2825,9 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, val =kvm_register_read (vcpu,VCPU_REGS_RAX );memcpy (vcpu->arch.pio_data, &val,4 ); +mutex_lock (&vcpu->kvm->lock); pio_dev =vcpu_find_pio_dev (vcpu, port, size, !in); +mutex_unlock (&vcpu->kvm->lock);if (pio_dev) {kernel_pio (pio_dev, vcpu, vcpu->arch.pio_data);complete_pio (vcpu);
@@ -2895,9 +2891,12 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, vcpu->arch.pio.guest_gva = address; +mutex_lock (&vcpu->kvm->lock); pio_dev =vcpu_find_pio_dev (vcpu, port, vcpu->arch.pio.cur_count, !vcpu->arch.pio.in); +mutex_unlock (&vcpu->kvm->lock); +if (!vcpu->arch.pio.in) {/* string PIO write */ ret =pio_copy_data (vcpu);
include/linux/kvm_host.h +2 -1
@@ -371,7 +371,8 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);void kvm_notify_acked_irq (struct kvm *kvm,unsigned irqchip,unsigned pin);void kvm_register_irq_ack_notifier (struct kvm *kvm,struct kvm_irq_ack_notifier *kian); -void kvm_unregister_irq_ack_notifier (struct kvm_irq_ack_notifier *kian); +void kvm_unregister_irq_ack_notifier (struct kvm *kvm, +struct kvm_irq_ack_notifier *kian);int kvm_request_irq_source_id (struct kvm *kvm);void kvm_free_irq_source_id (struct kvm *kvm,int irq_source_id);
virt/kvm/eventfd.c +2 -2
@@ -57,10 +57,10 @@ irqfd_inject(struct work_struct *work) struct _irqfd *irqfd = container_of(work, struct _irqfd, inject);struct kvm *kvm = irqfd->kvm; -mutex_lock (&kvm->lock); +mutex_lock (&kvm->irq_lock);kvm_set_irq (kvm,KVM_USERSPACE_IRQ_SOURCE_ID , irqfd->gsi,1 );kvm_set_irq (kvm,KVM_USERSPACE_IRQ_SOURCE_ID , irqfd->gsi,0 ); -mutex_unlock (&kvm->lock); +mutex_unlock (&kvm->irq_lock); }/*
virt/kvm/irq_comm.c +28 -6
@@ -62,6 +62,8 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,int i, r =-1 ;struct kvm_vcpu *vcpu, *lowest =NULL ; +WARN_ON (!mutex_is_locked (&kvm->irq_lock)); +if (irq->dest_mode ==0 && irq->dest_id ==0xff &&kvm_is_dm_lowest_prio (irq))printk (KERN_INFO "kvm: apic: phys broadcast and lowest prio\n" );
@@ -113,7 +115,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,return kvm_irq_delivery_to_apic (kvm,NULL , &irq); } -/* This should be called with the kvm->lock mutex held +/* This should be called with the kvm->irq_lock mutex held * Return value: * < 0 Interrupt was ignored (masked or not delivered for other reasons) * = 0 Interrupt was coalesced (previous irq is still pending)
@@ -125,6 +127,8 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)unsigned long *irq_state, sig_level;int ret =-1 ; +WARN_ON (!mutex_is_locked (&kvm->irq_lock)); +if (irq <KVM_IOAPIC_NUM_PINS ) { irq_state = (unsigned long *)&kvm->arch.irq_states[irq];
@@ -175,19 +179,26 @@ void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)void kvm_register_irq_ack_notifier (struct kvm *kvm,struct kvm_irq_ack_notifier *kian) { +mutex_lock (&kvm->irq_lock);hlist_add_head (&kian->link, &kvm->arch.irq_ack_notifier_list); +mutex_unlock (&kvm->irq_lock); } -void kvm_unregister_irq_ack_notifier (struct kvm_irq_ack_notifier *kian) +void kvm_unregister_irq_ack_notifier (struct kvm *kvm, +struct kvm_irq_ack_notifier *kian) { +mutex_lock (&kvm->irq_lock);hlist_del_init (&kian->link); +mutex_unlock (&kvm->irq_lock); } -/* The caller must hold kvm->lock mutex */ int kvm_request_irq_source_id (struct kvm *kvm) {unsigned long *bitmap = &kvm->arch.irq_sources_bitmap; -int irq_source_id =find_first_zero_bit (bitmap, +int irq_source_id; + +mutex_lock (&kvm->irq_lock); + irq_source_id =find_first_zero_bit (bitmap,sizeof (kvm->arch.irq_sources_bitmap));if (irq_source_id >=sizeof (kvm->arch.irq_sources_bitmap)) {
@@ -197,6 +208,7 @@ int kvm_request_irq_source_id(struct kvm *kvm)ASSERT (irq_source_id !=KVM_USERSPACE_IRQ_SOURCE_ID );set_bit (irq_source_id, bitmap); +mutex_unlock (&kvm->irq_lock);return irq_source_id; }
@@ -207,6 +219,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id)ASSERT (irq_source_id !=KVM_USERSPACE_IRQ_SOURCE_ID ); +mutex_lock (&kvm->irq_lock);if (irq_source_id <0 || irq_source_id >=sizeof (kvm->arch.irq_sources_bitmap)) {printk (KERN_ERR "kvm: IRQ source ID out of range!\n" );
@@ -215,19 +228,24 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id)for (i =0 ; i <KVM_IOAPIC_NUM_PINS ; i++)clear_bit (irq_source_id, &kvm->arch.irq_states[i]);clear_bit (irq_source_id, &kvm->arch.irq_sources_bitmap); +mutex_unlock (&kvm->irq_lock); }void kvm_register_irq_mask_notifier (struct kvm *kvm,int irq,struct kvm_irq_mask_notifier *kimn) { +mutex_lock (&kvm->irq_lock); kimn->irq = irq;hlist_add_head (&kimn->link, &kvm->mask_notifier_list); +mutex_unlock (&kvm->irq_lock); }void kvm_unregister_irq_mask_notifier (struct kvm *kvm,int irq,struct kvm_irq_mask_notifier *kimn) { +mutex_lock (&kvm->irq_lock);hlist_del (&kimn->link); +mutex_unlock (&kvm->irq_lock); }void kvm_fire_mask_notifiers (struct kvm *kvm,int irq,bool mask)
@@ -235,6 +253,8 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask)struct kvm_irq_mask_notifier *kimn;struct hlist_node *n; +WARN_ON (!mutex_is_locked (&kvm->irq_lock)); +hlist_for_each_entry (kimn, n, &kvm->mask_notifier_list, link)if (kimn->irq == irq) kimn->func (kimn, mask);
@@ -250,7 +270,9 @@ static void __kvm_free_irq_routing(struct list_head *irq_routing)void kvm_free_irq_routing (struct kvm *kvm) { +mutex_lock (&kvm->irq_lock);__kvm_free_irq_routing (&kvm->irq_routing); +mutex_unlock (&kvm->irq_lock); } static int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e,
@@ -325,13 +347,13 @@ int kvm_set_irq_routing(struct kvm *kvm, e =NULL ; } -mutex_lock (&kvm->lock); +mutex_lock (&kvm->irq_lock);list_splice (&kvm->irq_routing, &tmp);INIT_LIST_HEAD (&kvm->irq_routing);list_splice (&irq_list, &kvm->irq_routing);INIT_LIST_HEAD (&irq_list);list_splice (&tmp, &irq_list); -mutex_unlock (&kvm->lock); +mutex_unlock (&kvm->irq_lock); r =0 ;
virt/kvm/kvm_main.c +9 -7
@@ -62,6 +62,12 @@MODULE_AUTHOR ("Qumranet" );MODULE_LICENSE ("GPL" ); +/* +* Ordering of locks: +* +* kvm->lock --> kvm->irq_lock +*/ +DEFINE_SPINLOCK (kvm_lock);LIST_HEAD (vm_list);
@@ -126,11 +132,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work) interrupt_work); kvm = assigned_dev->kvm; -/* This is taken to safely inject irq inside the guest. When -* the interrupt injection (or the ioapic code) uses a -* finer-grained lock, update this -*/ -mutex_lock (&kvm->lock); +mutex_lock (&kvm->irq_lock);spin_lock_irq (&assigned_dev->assigned_dev_lock);if (assigned_dev->irq_requested_type &KVM_DEV_IRQ_HOST_MSIX ) { struct kvm_guest_msix_entry *guest_entries =
@@ -149,7 +151,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work) assigned_dev->guest_irq, 1);spin_unlock_irq (&assigned_dev->assigned_dev_lock); -mutex_unlock (&assigned_dev->kvm->lock); +mutex_unlock (&assigned_dev->kvm->irq_lock); }static irqreturn_t kvm_assigned_dev_intr (int irq,void *dev_id)
@@ -207,7 +209,7 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)static void deassign_guest_irq (struct kvm *kvm,struct kvm_assigned_dev_kernel *assigned_dev) { -kvm_unregister_irq_ack_notifier (&assigned_dev->ack_notifier); +kvm_unregister_irq_ack_notifier (kvm, &assigned_dev->ack_notifier); assigned_dev->ack_notifier.gsi =-1 ;if (assigned_dev->irq_source_id !=-1 )
Signature · 1 line
1.6.3.3
PATCH 39/48 KVM: VMX: Support Unrestricted Guest feature
In reply to Avi KivityFrom: Nitin A Kamble <[email protected]>
"Unrestricted Guest" feature is added in the VMX specification. Intel Westmere and onwards processors will support this feature.
It allows kvm guests to run real mode and unpaged mode
code natively in the VMX mode when EPT is turned on. With the unrestricted guest there is no need to emulate the guest real mode code in the vm86 container or in the emulator. Also the guest big real mode code works like native.
The attached patch enhances KVM to use the unrestricted guest feature
if available on the processor. It also adds a new kernel/module parameter to disable the unrestricted guest feature at the boot time.
--- arch/x86/include/asm/kvm_host.h | 12 ++++--- arch/x86/include/asm/vmx.h | 1 + arch/x86/kvm/vmx.c | 60 +++++++++++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 11 deletions(-)
arch/x86/include/asm/kvm_host.h +7 -5
@@ -37,12 +37,14 @@#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS | \ 0xFFFFFF0000000000ULL) -#define KVM_GUEST_CR0_MASK \ - (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE \ - | X86_CR0_NW | X86_CR0_CD) +#define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST \ + (X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD) +#define KVM_GUEST_CR0_MASK \ + (KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE) +#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST \ + (X86_CR0_WP | X86_CR0_NE | X86_CR0_TS | X86_CR0_MP)#define KVM_VM_CR0_ALWAYS_ON \ - (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE | X86_CR0_TS \ - | X86_CR0_MP) + (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE)#define KVM_GUEST_CR4_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)
arch/x86/include/asm/vmx.h +1 -0
@@ -55,6 +55,7 @@#define SECONDARY_EXEC_ENABLE_EPT 0x00000002#define SECONDARY_EXEC_ENABLE_VPID 0x00000020#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040 +#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080#define PIN_BASED_EXT_INTR_MASK 0x00000001
arch/x86/kvm/vmx.c +54 -6
125 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH 40/48 KVM: Reorder ioctls in kvm.h
In reply to Avi KivitySomehow the VM ioctls got unsorted; resort.
--- include/linux/kvm.h | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
include/linux/kvm.h +5 -5
@@ -495,11 +495,6 @@ struct kvm_irqfd {* ioctls for VM fds */ #define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region) -#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44) -#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45) -#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46,\ - struct kvm_userspace_memory_region) -#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)/* * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns * a vcpu fd.
@@ -507,6 +502,11 @@ struct kvm_irqfd {#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) +#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44) +#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45) +#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46,\ + struct kvm_userspace_memory_region) +#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)/* Device model IOC */ #define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
Signature · 1 line
1.6.3.3
PATCH 41/48 KVM: VMX: Move rmode structure to vmx-specific code
In reply to Avi Kivityrmode is only used in vmx, so move it to vmx.c
--- arch/x86/include/asm/kvm_host.h | 10 ----- arch/x86/kvm/vmx.c | 78 ++++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 44 deletions(-)
arch/x86/include/asm/kvm_host.h +0 -10
@@ -340,16 +340,6 @@ struct kvm_vcpu_arch {u8 nr; } interrupt; -struct { -int vm86_active; -u8 save_iopl; -struct kvm_save_segment { -u16 selector; -unsigned long base; -u32 limit; -u32 ar; - } tr, es, ds, fs, gs; - } rmode;int halt_request;/* real mode on Intel only */ int cpuid_nent;
arch/x86/kvm/vmx.c +44 -34
196 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH 42/48 KVM: MMU: Fix is_dirty_pte()
In reply to Avi Kivityis_dirty_pte() is used on guest ptes, not shadow ptes, so it needs to avoid shadow_dirty_mask and use PT_DIRTY_MASK instead.
Misdetecting dirty pages could lead to unnecessarily setting the dirty bit under EPT.
--- arch/x86/kvm/mmu.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kvm/mmu.c +1 -1
@@ -242,7 +242,7 @@ static int is_writeble_pte(unsigned long pte)static int is_dirty_pte (unsigned long pte) { -return pte & shadow_dirty_mask; +return pte &PT_DIRTY_MASK ; }static int is_rmap_pte (u64 pte)
Signature · 1 line
1.6.3.3
PATCH 43/48 KVM: MMU: Adjust pte accessors to explicitly indicate guest or shadow pte
In reply to Avi KivitySince the guest and host ptes can have wildly different format, adjust the pte accessor names to indicate on which type of pte they operate on.
No functional changes.
--- arch/x86/kvm/mmu.c | 16 ++++++++-------- arch/x86/kvm/mmu.h | 2 +- arch/x86/kvm/paging_tmpl.h | 22 +++++++++++----------- arch/x86/kvm/x86.c | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-)
arch/x86/kvm/mmu.c +8 -8
@@ -240,12 +240,12 @@ static int is_writeble_pte(unsigned long pte)return pte &PT_WRITABLE_MASK ; } -static int is_dirty_pte (unsigned long pte) +static int is_dirty_gpte (unsigned long pte) {return pte &PT_DIRTY_MASK ; } -static int is_rmap_pte (u64 pte) +static int is_rmap_spte (u64 pte) {return is_shadow_present_pte (pte); }
@@ -502,7 +502,7 @@ static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)unsigned long *rmapp;int i, count =0 ; -if (!is_rmap_pte (*spte)) +if (!is_rmap_spte (*spte))return count; gfn =unalias_gfn (vcpu->kvm, gfn); sp =page_header (__pa (spte));
@@ -567,7 +567,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)unsigned long *rmapp;int i; -if (!is_rmap_pte (*spte)) +if (!is_rmap_spte (*spte))return ; sp =page_header (__pa (spte)); pfn =spte_to_pfn (*spte);
@@ -1769,7 +1769,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, __func__, *shadow_pte, pt_access, write_fault, user_fault, gfn); -if (is_rmap_pte (*shadow_pte)) { +if (is_rmap_spte (*shadow_pte)) {/* * If we overwrite a PTE page pointer with a 2MB PMD, unlink * the parent of the now unreachable PTE.
@@ -1805,7 +1805,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,page_header_update_slot (vcpu->kvm, shadow_pte, gfn);if (!was_rmapped) { rmap_count =rmap_add (vcpu, shadow_pte, gfn, largepage); -if (!is_rmap_pte (*shadow_pte)) +if (!is_rmap_spte (*shadow_pte))kvm_release_pfn_clean (pfn);if (rmap_count >RMAP_RECYCLE_THRESHOLD )rmap_recycle (vcpu, gfn, largepage);
@@ -1984,7 +1984,7 @@ static int mmu_alloc_roots(struct kvm_vcpu *vcpu)ASSERT (!VALID_PAGE (root));if (vcpu->arch.mmu.root_level ==PT32E_ROOT_LEVEL ) { pdptr =kvm_pdptr_read (vcpu, i); -if (!is_present_pte (pdptr)) { +if (!is_present_gpte (pdptr)) { vcpu->arch.mmu.pae_root[i] =0 ;continue ; }
@@ -2475,7 +2475,7 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,if ((bytes ==4 ) && (gpa %4 ==0 ))memcpy ((void *)&gpte, new,4 ); } -if (!is_present_pte (gpte)) +if (!is_present_gpte (gpte))return ; gfn = (gpte &PT64_BASE_ADDR_MASK ) >>PAGE_SHIFT ;
arch/x86/kvm/mmu.h +1 -1
@@ -75,7 +75,7 @@ static inline int is_paging(struct kvm_vcpu *vcpu)return vcpu->arch.cr0 &X86_CR0_PG ; } -static inline int is_present_pte (unsigned long pte) +static inline int is_present_gpte (unsigned long pte) {return pte &PT_PRESENT_MASK ; }
arch/x86/kvm/paging_tmpl.h +11 -11
@@ -132,7 +132,7 @@ walk:#if PTTYPE ==64 if (!is_long_mode (vcpu)) { pte =kvm_pdptr_read (vcpu, (addr >>30 ) &3 ); -if (!is_present_pte (pte)) +if (!is_present_gpte (pte)) goto not_present; --walker->level; }
@@ -155,7 +155,7 @@ walk:kvm_read_guest (vcpu->kvm, pte_gpa, &pte,sizeof (pte)); -if (!is_present_pte (pte)) +if (!is_present_gpte (pte)) goto not_present; rsvd_fault =is_rsvd_bits_set (vcpu, pte, walker->level);
@@ -205,7 +205,7 @@ walk: --walker->level; } -if (write_fault && !is_dirty_pte (pte)) { +if (write_fault && !is_dirty_gpte (pte)) {bool ret;mark_page_dirty (vcpu->kvm, table_gfn);
@@ -252,7 +252,7 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page, gpte = *(const pt_element_t *)pte;if (~gpte & (PT_PRESENT_MASK |PT_ACCESSED_MASK )) { -if (!is_present_pte (gpte)) +if (!is_present_gpte (gpte))set_shadow_pte (spte, shadow_notrap_nonpresent_pte);return ; }
@@ -289,7 +289,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,pt_element_t curr_pte;struct kvm_shadow_walk_iterator iterator; -if (!is_present_pte (gw->ptes[gw->level -1 ])) +if (!is_present_gpte (gw->ptes[gw->level -1 ]))return NULL ;for_each_shadow_entry (vcpu, addr, iterator) {
@@ -318,7 +318,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,if (level ==PT_DIRECTORY_LEVEL && gw->level ==PT_DIRECTORY_LEVEL ) { direct =1 ; -if (!is_dirty_pte (gw->ptes[level -1 ])) +if (!is_dirty_gpte (gw->ptes[level -1 ])) access &= ~ACC_WRITE_MASK ; table_gfn =gpte_to_gfn (gw->ptes[level -1 ]); }else {
@@ -489,7 +489,7 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)if (kvm_read_guest_atomic (vcpu->kvm, pte_gpa, &gpte,sizeof (pt_element_t)))return ; -if (is_present_pte (gpte) && (gpte &PT_ACCESSED_MASK )) { +if (is_present_gpte (gpte) && (gpte &PT_ACCESSED_MASK )) {if (mmu_topup_memory_caches (vcpu))return ; kvm_mmu_pte_write(vcpu, pte_gpa, (const u8 *)&gpte,
@@ -536,7 +536,7 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu, r =kvm_read_guest_atomic (vcpu->kvm, pte_gpa, pt,sizeof pt); pte_gpa +=ARRAY_SIZE (pt) *sizeof (pt_element_t);for (j =0 ; j <ARRAY_SIZE (pt); ++j) -if (r ||is_present_pte (pt[j])) +if (r ||is_present_gpte (pt[j])) sp->spt[i+j] = shadow_trap_nonpresent_pte;else sp->spt[i+j] = shadow_notrap_nonpresent_pte;
@@ -574,12 +574,12 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) sizeof(pt_element_t)))return -EINVAL ; -if (gpte_to_gfn (gpte) != gfn || !is_present_pte (gpte) || +if (gpte_to_gfn (gpte) != gfn || !is_present_gpte (gpte) || !(gpte &PT_ACCESSED_MASK )) {u64 nonpresent;rmap_remove (vcpu->kvm, &sp->spt[i]); -if (is_present_pte (gpte)) +if (is_present_gpte (gpte)) nonpresent = shadow_trap_nonpresent_pte;else nonpresent = shadow_notrap_nonpresent_pte;
@@ -590,7 +590,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) nr_present++; pte_access = sp->role.access &FNAME (gpte_access)(vcpu, gpte);set_spte (vcpu, &sp->spt[i], pte_access,0 ,0 , -is_dirty_pte (gpte),0 , gfn, +is_dirty_gpte (gpte),0 , gfn,spte_to_pfn (sp->spt[i]), true, false); }
arch/x86/kvm/x86.c +1 -1
@@ -237,7 +237,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3) goto out; }for (i =0 ; i <ARRAY_SIZE (pdpte); ++i) { -if (is_present_pte (pdpte[i]) && +if (is_present_gpte (pdpte[i]) && (pdpte[i] & vcpu->arch.mmu.rsvd_bits_mask[0 ][2 ])) { ret =0 ; goto out;
Signature · 1 line
1.6.3.3
PATCH 44/48 KVM: MMU: s/shadow_pte/spte/
In reply to Avi KivityWe use shadow_pte and spte inconsistently, switch to the shorter spelling.
Rename set_shadow_pte() to __set_spte() to avoid a conflict with the existing set_spte(), and to indicate its lowlevelness.
--- arch/x86/kvm/mmu.c | 102 ++++++++++++++++++++++---------------------- arch/x86/kvm/paging_tmpl.h | 16 +++--- 2 files changed, 59 insertions(+), 59 deletions(-)
arch/x86/kvm/mmu.c +51 -51
@@ -143,7 +143,7 @@ module_param(oos_shadow, bool, 0644);#define SHADOW_PT_INDEX (addr, level) PT64_INDEX(addr, level)struct kvm_rmap_desc { -u64 *shadow_ptes[RMAP_EXT ]; +u64 *sptes[RMAP_EXT ];struct kvm_rmap_desc *more; };
@@ -262,7 +262,7 @@ static gfn_t pse36_gfn_delta(u32 gpte)return (gpte &PT32_DIR_PSE36_MASK ) << shift; } -static void set_shadow_pte (u64 *sptep,u64 spte) +static void __set_spte (u64 *sptep,u64 spte) {#ifdef CONFIG_X86_64 set_64bit ((unsigned long *)sptep, spte);
@@ -514,23 +514,23 @@ static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage) }else if (!(*rmapp &1 )) {rmap_printk ("rmap_add: %p %llx 1->many\n" , spte, *spte); desc =mmu_alloc_rmap_desc (vcpu); - desc->shadow_ptes[0 ] = (u64 *)*rmapp; - desc->shadow_ptes[1 ] = spte; + desc->sptes[0 ] = (u64 *)*rmapp; + desc->sptes[1 ] = spte; *rmapp = (unsigned long )desc |1 ; }else {rmap_printk ("rmap_add: %p %llx many->many\n" , spte, *spte); desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul ); -while (desc->shadow_ptes[RMAP_EXT -1 ] && desc->more) { +while (desc->sptes[RMAP_EXT -1 ] && desc->more) { desc = desc->more; count +=RMAP_EXT ; } -if (desc->shadow_ptes[RMAP_EXT -1 ]) { +if (desc->sptes[RMAP_EXT -1 ]) { desc->more =mmu_alloc_rmap_desc (vcpu); desc = desc->more; } -for (i =0 ; desc->shadow_ptes[i]; ++i) +for (i =0 ; desc->sptes[i]; ++i) ; - desc->shadow_ptes[i] = spte; + desc->sptes[i] = spte; }return count; }
@@ -542,14 +542,14 @@ static void rmap_desc_remove_entry(unsigned long *rmapp, {int j; -for (j =RMAP_EXT -1 ; !desc->shadow_ptes[j] && j > i; --j) +for (j =RMAP_EXT -1 ; !desc->sptes[j] && j > i; --j) ; - desc->shadow_ptes[i] = desc->shadow_ptes[j]; - desc->shadow_ptes[j] =NULL ; + desc->sptes[i] = desc->sptes[j]; + desc->sptes[j] =NULL ;if (j !=0 )return ;if (!prev_desc && !desc->more) - *rmapp = (unsigned long )desc->shadow_ptes[0 ]; + *rmapp = (unsigned long )desc->sptes[0 ];else if (prev_desc) prev_desc->more = desc->more;
@@ -594,8 +594,8 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul ); prev_desc =NULL ;while (desc) { -for (i =0 ; i <RMAP_EXT && desc->shadow_ptes[i]; ++i) -if (desc->shadow_ptes[i] == spte) { +for (i =0 ; i <RMAP_EXT && desc->sptes[i]; ++i) +if (desc->sptes[i] == spte) {rmap_desc_remove_entry (rmapp, desc, i, prev_desc);
@@ -626,10 +626,10 @@ static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte) prev_desc =NULL ; prev_spte =NULL ;while (desc) { -for (i =0 ; i <RMAP_EXT && desc->shadow_ptes[i]; ++i) { +for (i =0 ; i <RMAP_EXT && desc->sptes[i]; ++i) {if (prev_spte == spte) -return desc->shadow_ptes[i]; - prev_spte = desc->shadow_ptes[i]; +return desc->sptes[i]; + prev_spte = desc->sptes[i]; } desc = desc->more; }
@@ -651,7 +651,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn)BUG_ON (!(*spte &PT_PRESENT_MASK ));rmap_printk ("rmap_write_protect: spte %p %llx\n" , spte, *spte);if (is_writeble_pte (*spte)) { -set_shadow_pte (spte, *spte & ~PT_WRITABLE_MASK ); +__set_spte (spte, *spte & ~PT_WRITABLE_MASK ); write_protected =1 ; } spte =rmap_next (kvm, rmapp, spte);
@@ -675,7 +675,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn)if (is_writeble_pte (*spte)) {rmap_remove (kvm, spte); --kvm->stat.lpages; -set_shadow_pte (spte, shadow_trap_nonpresent_pte); +__set_spte (spte, shadow_trap_nonpresent_pte); spte =NULL ; write_protected =1 ; }
@@ -694,7 +694,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp)BUG_ON (!(*spte &PT_PRESENT_MASK ));rmap_printk ("kvm_rmap_unmap_hva: spte %p %llx\n" , spte, *spte);rmap_remove (kvm, spte); -set_shadow_pte (spte, shadow_trap_nonpresent_pte); +__set_spte (spte, shadow_trap_nonpresent_pte); need_tlb_flush =1 ; }return need_tlb_flush;
@@ -1369,7 +1369,7 @@ static void kvm_mmu_unlink_parents(struct kvm *kvm, struct kvm_mmu_page *sp) }BUG_ON (!parent_pte);kvm_mmu_put_page (sp, parent_pte); -set_shadow_pte (parent_pte, shadow_trap_nonpresent_pte); +__set_spte (parent_pte, shadow_trap_nonpresent_pte); } }
@@ -1517,7 +1517,7 @@ static void mmu_convert_notrap(struct kvm_mmu_page *sp)for (i =0 ; i <PT64_ENT_PER_PAGE ; ++i) {if (pt[i] == shadow_notrap_nonpresent_pte) -set_shadow_pte (&pt[i], shadow_trap_nonpresent_pte); +__set_spte (&pt[i], shadow_trap_nonpresent_pte); } }
@@ -1683,7 +1683,7 @@ static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn,return 0 ; } -static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, +static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pte_access, int user_fault, int write_fault, int dirty, int largepage, gfn_t gfn, pfn_t pfn, bool speculative,
@@ -1733,7 +1733,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,* is responsibility of mmu_get_page / kvm_sync_page. * Same reasoning can be applied to dirty page accounting. */ -if (!can_unsync &&is_writeble_pte (*shadow_pte)) +if (!can_unsync &&is_writeble_pte (*sptep)) goto set_pte;if (mmu_need_write_protect (vcpu, gfn, can_unsync)) {
@@ -1750,62 +1750,62 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,mark_page_dirty (vcpu->kvm, gfn); set_pte: -set_shadow_pte (shadow_pte, spte); +__set_spte (sptep, spte);return ret; } -static void mmu_set_spte (struct kvm_vcpu *vcpu,u64 *shadow_pte, +static void mmu_set_spte (struct kvm_vcpu *vcpu,u64 *sptep,unsigned pt_access,unsigned pte_access,int user_fault,int write_fault,int dirty,int *ptwrite,int largepage,gfn_t gfn,pfn_t pfn,bool speculative) {int was_rmapped =0 ; -int was_writeble =is_writeble_pte (*shadow_pte); +int was_writeble =is_writeble_pte (*sptep);int rmap_count;pgprintk ("%s: spte %llx access %x write_fault %d" " user_fault %d gfn %lx\n" , - __func__, *shadow_pte, pt_access, + __func__, *sptep, pt_access, write_fault, user_fault, gfn); -if (is_rmap_spte (*shadow_pte)) { +if (is_rmap_spte (*sptep)) {/* * If we overwrite a PTE page pointer with a 2MB PMD, unlink * the parent of the now unreachable PTE. */ -if (largepage && !is_large_pte (*shadow_pte)) { +if (largepage && !is_large_pte (*sptep)) {struct kvm_mmu_page *child; -u64 pte = *shadow_pte; +u64 pte = *sptep; child =page_header (pte &PT64_BASE_ADDR_MASK ); -mmu_page_remove_parent_pte (child, shadow_pte); - }else if (pfn !=spte_to_pfn (*shadow_pte)) { +mmu_page_remove_parent_pte (child, sptep); + }else if (pfn !=spte_to_pfn (*sptep)) {pgprintk ("hfn old %lx new %lx\n" , -spte_to_pfn (*shadow_pte), pfn); -rmap_remove (vcpu->kvm, shadow_pte); +spte_to_pfn (*sptep), pfn); +rmap_remove (vcpu->kvm, sptep); }else was_rmapped =1 ; } -if (set_spte (vcpu, shadow_pte, pte_access, user_fault, write_fault, +if (set_spte (vcpu, sptep, pte_access, user_fault, write_fault, dirty, largepage, gfn, pfn, speculative, true)) {if (write_fault) *ptwrite =1 ; kvm_x86_ops->tlb_flush (vcpu); } -pgprintk ("%s: setting spte %llx\n" , __func__, *shadow_pte); +pgprintk ("%s: setting spte %llx\n" , __func__, *sptep);pgprintk ("instantiating %s PTE (%s) at %ld (%llx) addr %p\n" , -is_large_pte (*shadow_pte)?"2MB" :"4kB" , -is_present_pte (*shadow_pte)?"RW" :"R" , gfn, - *shadow_pte, shadow_pte); -if (!was_rmapped &&is_large_pte (*shadow_pte)) +is_large_pte (*sptep)?"2MB" :"4kB" , +is_present_pte (*sptep)?"RW" :"R" , gfn, + *shadow_pte, sptep); +if (!was_rmapped &&is_large_pte (*sptep)) ++vcpu->kvm->stat.lpages; -page_header_update_slot (vcpu->kvm, shadow_pte, gfn); +page_header_update_slot (vcpu->kvm, sptep, gfn);if (!was_rmapped) { - rmap_count =rmap_add (vcpu, shadow_pte, gfn, largepage); -if (!is_rmap_spte (*shadow_pte)) + rmap_count =rmap_add (vcpu, sptep, gfn, largepage); +if (!is_rmap_spte (*sptep))kvm_release_pfn_clean (pfn);if (rmap_count >RMAP_RECYCLE_THRESHOLD )rmap_recycle (vcpu, gfn, largepage);
@@ -1816,7 +1816,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,kvm_release_pfn_clean (pfn); }if (speculative) { - vcpu->arch.last_pte_updated = shadow_pte; + vcpu->arch.last_pte_updated = sptep; vcpu->arch.last_pte_gfn = gfn; } }
@@ -1854,10 +1854,10 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,return -ENOMEM ; } -set_shadow_pte (iterator.sptep, -__pa (sp->spt) - |PT_PRESENT_MASK |PT_WRITABLE_MASK - | shadow_user_mask | shadow_x_mask); +__set_spte (iterator.sptep, +__pa (sp->spt) + |PT_PRESENT_MASK |PT_WRITABLE_MASK + | shadow_user_mask | shadow_x_mask); } }return pt_write;
@@ -2389,7 +2389,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,mmu_page_remove_parent_pte (child, spte); } } -set_shadow_pte (spte, shadow_trap_nonpresent_pte); +__set_spte (spte, shadow_trap_nonpresent_pte);if (is_large_pte (pte)) --vcpu->kvm->stat.lpages; }
@@ -3125,7 +3125,7 @@ static int count_rmaps(struct kvm_vcpu *vcpu) d = (struct kvm_rmap_desc *)(*rmapp & ~1ul );while (d) {for (k =0 ; k <RMAP_EXT ; ++k) -if (d->shadow_ptes[k]) +if (d->sptes[k]) ++nmaps;else break ;
arch/x86/kvm/paging_tmpl.h +8 -8
@@ -253,7 +253,7 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page, gpte = *(const pt_element_t *)pte;if (~gpte & (PT_PRESENT_MASK |PT_ACCESSED_MASK )) {if (!is_present_gpte (gpte)) -set_shadow_pte (spte, shadow_notrap_nonpresent_pte); +__set_spte (spte, shadow_notrap_nonpresent_pte);return ; }pgprintk ("%s: gpte %llx spte %p\n" , __func__, (u64 )gpte, spte);
@@ -311,7 +311,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,if (is_large_pte (*sptep)) {rmap_remove (vcpu->kvm, sptep); -set_shadow_pte (sptep, shadow_trap_nonpresent_pte); +__set_spte (sptep, shadow_trap_nonpresent_pte);kvm_flush_remote_tlbs (vcpu->kvm); }
@@ -369,7 +369,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,int user_fault = error_code &PFERR_USER_MASK ;int fetch_fault = error_code &PFERR_FETCH_MASK ;struct guest_walker walker; -u64 *shadow_pte; +u64 *sptep;int write_pt =0 ;int r;pfn_t pfn;
@@ -422,11 +422,11 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,if (mmu_notifier_retry (vcpu, mmu_seq)) goto out_unlock;kvm_mmu_free_some_pages (vcpu); - shadow_pte =FNAME (fetch)(vcpu, addr, &walker, user_fault, write_fault, - largepage, &write_pt, pfn); + sptep =FNAME (fetch)(vcpu, addr, &walker, user_fault, write_fault, + largepage, &write_pt, pfn);pgprintk ("%s: shadow pte %p %llx ptwrite %d\n" , __func__, - shadow_pte, *shadow_pte, write_pt); + sptep, *sptep, write_pt);if (!write_pt) vcpu->arch.last_pt_write_count =0 ;/* reset fork detector */
@@ -472,7 +472,7 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) --vcpu->kvm->stat.lpages; need_flush =1 ; } -set_shadow_pte (sptep, shadow_trap_nonpresent_pte); +__set_spte (sptep, shadow_trap_nonpresent_pte);break ; }
@@ -583,7 +583,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) nonpresent = shadow_trap_nonpresent_pte; else nonpresent = shadow_notrap_nonpresent_pte; -set_shadow_pte (&sp->spt[i], nonpresent); +__set_spte (&sp->spt[i], nonpresent);continue ; }
Signature · 1 line
1.6.3.3
PATCH 45/48 KVM: Introduce kvm_vcpu_is_bsp() function.
In reply to Avi KivityFrom: Gleb Natapov <[email protected]>
Use it instead of open code "vcpu_id zero is BSP" assumption.
--- arch/ia64/kvm/kvm-ia64.c | 2 +- arch/ia64/kvm/vcpu.c | 2 +- arch/x86/kvm/i8254.c | 4 ++-- arch/x86/kvm/i8259.c | 6 +++--- arch/x86/kvm/lapic.c | 7 ++++--- arch/x86/kvm/svm.c | 4 ++-- arch/x86/kvm/vmx.c | 6 +++--- arch/x86/kvm/x86.c | 4 ++-- include/linux/kvm_host.h | 5 +++++ virt/kvm/ioapic.c | 4 +++- virt/kvm/kvm_main.c | 2 ++ 11 files changed, 28 insertions(+), 18 deletions(-)
arch/ia64/kvm/kvm-ia64.c +1 -1
@@ -1216,7 +1216,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)if (IS_ERR (vmm_vcpu))return PTR_ERR (vmm_vcpu); -if (vcpu->vcpu_id ==0 ) { +if (kvm_vcpu_is_bsp (vcpu)) { vcpu->arch.mp_state =KVM_MP_STATE_RUNNABLE ;/*Set entry address for first run.*/
arch/ia64/kvm/vcpu.c +1 -1
@@ -830,7 +830,7 @@ static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val) kvm = (struct kvm *)KVM_VM_BASE ; -if (vcpu->vcpu_id ==0 ) { +if (kvm_vcpu_is_bsp (vcpu)) {for (i =0 ; i < kvm->arch.online_vcpus; i++) { v = (struct kvm_vcpu *)((char *)vcpu +sizeof (struct kvm_vcpu_data ) * i);
arch/x86/kvm/i8254.c +2 -2
@@ -231,7 +231,7 @@ int pit_has_pending_timer(struct kvm_vcpu *vcpu) {struct kvm_pit *pit = vcpu->kvm->arch.vpit; -if (pit && vcpu->vcpu_id ==0 && pit->pit_state.irq_ack) +if (pit &&kvm_vcpu_is_bsp (vcpu) && pit->pit_state.irq_ack)return atomic_read (&pit->pit_state.pit_timer.pending);return 0 ; }
@@ -252,7 +252,7 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)struct kvm_pit *pit = vcpu->kvm->arch.vpit;struct hrtimer *timer; -if (vcpu->vcpu_id !=0 || !pit) +if (!kvm_vcpu_is_bsp (vcpu) || !pit)return ; timer = &pit->pit_state.pit_timer.timer;
arch/x86/kvm/i8259.c +3 -3
@@ -57,7 +57,7 @@ static void pic_unlock(struct kvm_pic *s) }if (wakeup) { - vcpu = s->kvm->vcpus[0 ]; + vcpu = s->kvm->bsp_vcpu;if (vcpu)kvm_vcpu_kick (vcpu); }
@@ -254,7 +254,7 @@ void kvm_pic_reset(struct kvm_kpic_state *s) {int irq, irqbase, n;struct kvm *kvm = s->pics_state->irq_request_opaque; -struct kvm_vcpu *vcpu0 = kvm->vcpus[0 ]; +struct kvm_vcpu *vcpu0 = kvm->bsp_vcpu;if (s == &s->pics_state->pics[0 ]) irqbase =0 ;
@@ -512,7 +512,7 @@ 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 ]; +struct kvm_vcpu *vcpu = kvm->bsp_vcpu;struct kvm_pic *s =pic_irqchip (kvm);int irq =pic_get_irq (&s->pics[0 ]);
arch/x86/kvm/lapic.c +4 -3
@@ -793,7 +793,8 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value) vcpu->arch.apic_base = value;return ; } -if (apic->vcpu->vcpu_id) + +if (!kvm_vcpu_is_bsp (apic->vcpu)) value &= ~MSR_IA32_APICBASE_BSP ; vcpu->arch.apic_base = value;
@@ -844,7 +845,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) }update_divide_count (apic);atomic_set (&apic->lapic_timer.pending,0 ); -if (vcpu->vcpu_id ==0 ) +if (kvm_vcpu_is_bsp (vcpu)) vcpu->arch.apic_base |=MSR_IA32_APICBASE_BSP ;apic_update_ppr (apic);
@@ -985,7 +986,7 @@ int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu)u32 lvt0 =apic_get_reg (vcpu->arch.apic,APIC_LVT0 );int r =0 ; -if (vcpu->vcpu_id ==0 ) { +if (kvm_vcpu_is_bsp (vcpu)) {if (!apic_hw_enabled (vcpu->arch.apic)) r =1 ; if ((lvt0 & APIC_LVT_MASKED) == 0 &&
arch/x86/kvm/svm.c +2 -2
@@ -645,7 +645,7 @@ static int svm_vcpu_reset(struct kvm_vcpu *vcpu)init_vmcb (svm); -if (vcpu->vcpu_id !=0 ) { +if (!kvm_vcpu_is_bsp (vcpu)) {kvm_rip_write (vcpu,0 ); svm->vmcb->save.cs.base = svm->vcpu.arch.sipi_vector <<12 ; svm->vmcb->save.cs.selector = svm->vcpu.arch.sipi_vector <<8 ;
@@ -709,7 +709,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)fx_init (&svm->vcpu); svm->vcpu.fpu_active =1 ; svm->vcpu.arch.apic_base =0xfee00000 |MSR_IA32_APICBASE_ENABLE ; -if (svm->vcpu.vcpu_id ==0 ) +if (kvm_vcpu_is_bsp (&svm->vcpu)) svm->vcpu.arch.apic_base |=MSR_IA32_APICBASE_BSP ;return &svm->vcpu;
arch/x86/kvm/vmx.c +3 -3
@@ -2411,7 +2411,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) vmx->vcpu.arch.regs[VCPU_REGS_RDX ] =get_rdx_init_val ();kvm_set_cr8 (&vmx->vcpu,0 ); msr =0xfee00000 |MSR_IA32_APICBASE_ENABLE ; -if (vmx->vcpu.vcpu_id ==0 ) +if (kvm_vcpu_is_bsp (&vmx->vcpu)) msr |=MSR_IA32_APICBASE_BSP ;kvm_set_apic_base (&vmx->vcpu, msr);
@@ -2422,7 +2422,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)* GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4. Sigh. */ -if (vmx->vcpu.vcpu_id ==0 ) { +if (kvm_vcpu_is_bsp (&vmx->vcpu)) {vmcs_write16 (GUEST_CS_SELECTOR ,0xf000 );vmcs_writel (GUEST_CS_BASE ,0x000f0000 ); }else {
@@ -2451,7 +2451,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)vmcs_writel (GUEST_SYSENTER_EIP ,0 );vmcs_writel (GUEST_RFLAGS ,0x02 ); -if (vmx->vcpu.vcpu_id ==0 ) +if (kvm_vcpu_is_bsp (&vmx->vcpu))kvm_rip_write (vcpu,0xfff0 );else kvm_rip_write (vcpu,0 );
arch/x86/kvm/x86.c +2 -2
@@ -4330,7 +4330,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,kvm_set_segment (vcpu, &sregs->ldt,VCPU_SREG_LDTR );/* Older userspace won't unhalt the vcpu on reset. */ -if (vcpu->vcpu_id ==0 &&kvm_rip_read (vcpu) ==0xfff0 && +if (kvm_vcpu_is_bsp (vcpu) &&kvm_rip_read (vcpu) ==0xfff0 && sregs->cs.selector ==0xf000 && sregs->cs.base ==0xffff0000 && !(vcpu->arch.cr0 &X86_CR0_PE )) vcpu->arch.mp_state =KVM_MP_STATE_RUNNABLE ;
@@ -4601,7 +4601,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) kvm = vcpu->kvm; vcpu->arch.mmu.root_hpa =INVALID_PAGE ; -if (!irqchip_in_kernel (kvm) || vcpu->vcpu_id ==0 ) +if (!irqchip_in_kernel (kvm) ||kvm_vcpu_is_bsp (vcpu)) vcpu->arch.mp_state =KVM_MP_STATE_RUNNABLE ;else vcpu->arch.mp_state =KVM_MP_STATE_UNINITIALIZED ;
include/linux/kvm_host.h +5 -0
@@ -131,6 +131,7 @@ struct kvm {int nmemslots;struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS +KVM_PRIVATE_MEM_SLOTS ]; +struct kvm_vcpu *bsp_vcpu;struct kvm_vcpu *vcpus[KVM_MAX_VCPUS ];struct list_head vm_list;struct mutex lock;
@@ -549,4 +550,8 @@ static inline void kvm_irqfd_release(struct kvm *kvm) {}#endif /* CONFIG_HAVE_KVM_EVENTFD */ +static inline bool kvm_vcpu_is_bsp (struct kvm_vcpu *vcpu) +{ +return vcpu->kvm->bsp_vcpu == vcpu; +}#endif
virt/kvm/ioapic.c +3 -1
@@ -164,7 +164,9 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)/* Always delivery PIT interrupt to vcpu 0 */ if (irq ==0 ) { irqe.dest_mode =0 ;/* Physical mode. */ - irqe.dest_id = ioapic->kvm->vcpus[0 ]->vcpu_id; +/* need to read apic_id from apic regiest since +* it can be rewritten */ + irqe.dest_id = ioapic->kvm->bsp_vcpu->vcpu_id; }#endif return kvm_irq_delivery_to_apic (ioapic->kvm,NULL , &irqe);
virt/kvm/kvm_main.c +2 -0
@@ -1747,6 +1747,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n) goto vcpu_destroy; } kvm->vcpus[n] = vcpu; +if (n ==0 ) + kvm->bsp_vcpu = vcpu;mutex_unlock (&kvm->lock);/* Now it's all set up, let userspace reach it */
Signature · 1 line
1.6.3.3
PATCH 46/48 KVM: Use pointer to vcpu instead of vcpu_id in timer code.
In reply to Avi KivityFrom: Gleb Natapov <[email protected]>
--- arch/x86/kvm/i8254.c | 2 +- arch/x86/kvm/kvm_timer.h | 2 +- arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/timer.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
arch/x86/kvm/i8254.c +1 -1
@@ -294,7 +294,7 @@ static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) pt->timer.function = kvm_timer_fn; pt->t_ops = &kpit_ops; pt->kvm = ps->pit->kvm; - pt->vcpu_id =0 ; + pt->vcpu = pt->kvm->bsp_vcpu;atomic_set (&pt->pending,0 ); ps->irq_ack =1 ;
arch/x86/kvm/kvm_timer.h +1 -1
@@ -6,7 +6,7 @@ struct kvm_timer {bool reinject;struct kvm_timer_ops *t_ops;struct kvm *kvm; -int vcpu_id; +struct kvm_vcpu *vcpu; };struct kvm_timer_ops {
arch/x86/kvm/lapic.c +1 -1
@@ -950,7 +950,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu) apic->lapic_timer.timer.function = kvm_timer_fn; apic->lapic_timer.t_ops = &lapic_timer_ops; apic->lapic_timer.kvm = vcpu->kvm; - apic->lapic_timer.vcpu_id = vcpu->vcpu_id; + apic->lapic_timer.vcpu = vcpu; apic->base_address =APIC_DEFAULT_PHYS_BASE ; vcpu->arch.apic_base =APIC_DEFAULT_PHYS_BASE ;
arch/x86/kvm/timer.c +1 -1
@@ -33,7 +33,7 @@ enum hrtimer_restart kvm_timer_fn(struct hrtimer *data)struct kvm_vcpu *vcpu; struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer); - vcpu = ktimer->kvm->vcpus[ktimer->vcpu_id]; + vcpu = ktimer->vcpu;if (!vcpu)return HRTIMER_NORESTART ;
Signature · 1 line
1.6.3.3
PATCH 47/48 KVM: Break dependency between vcpu index in vcpus array and vcpu_id.
In reply to Avi KivityFrom: Gleb Natapov <[email protected]>
Archs are free to use vcpu_id as they see fit. For x86 it is used as vcpu's apic id. New ioctl is added to configure boot vcpu id that was assumed to be 0 till now.
--- arch/ia64/include/asm/kvm_host.h | 1 - arch/ia64/kvm/Kconfig | 1 + arch/ia64/kvm/kvm-ia64.c | 8 +--- arch/ia64/kvm/vcpu.c | 2 +- arch/x86/kvm/Kconfig | 1 + include/linux/kvm.h | 2 + include/linux/kvm_host.h | 6 +++ virt/kvm/Kconfig | 3 ++ virt/kvm/kvm_main.c | 64 +++++++++++++++++++++++--------------- 9 files changed, 55 insertions(+), 33 deletions(-)
arch/ia64/include/asm/kvm_host.h +0 -1
@@ -465,7 +465,6 @@ struct kvm_arch {unsigned long metaphysical_rr4;unsigned long vmm_init_rr; -int online_vcpus;int is_sn2;struct kvm_ioapic *vioapic;
arch/ia64/kvm/Kconfig +1 -0
@@ -25,6 +25,7 @@ config KVM select PREEMPT_NOTIFIERS select ANON_INODES select HAVE_KVM_IRQCHIP + select KVM_APIC_ARCHITECTURE ---help--- Support hosting fully virtualized guest machines using hardware virtualization extensions. You will need a fairly recent
arch/ia64/kvm/kvm-ia64.c +2 -6
@@ -338,7 +338,7 @@ static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,union ia64_lid lid;int i; -for (i =0 ; i < kvm->arch.online_vcpus; i++) { +for (i =0 ; i <atomic_read (&kvm->online_vcpus); i++) {if (kvm->vcpus[i]) { lid.val =VCPU_LID (kvm->vcpus[i]);if (lid.id == id && lid.eid == eid)
@@ -412,7 +412,7 @@ static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) call_data.ptc_g_data = p->u.ptc_g_data; -for (i =0 ; i < kvm->arch.online_vcpus; i++) { +for (i =0 ; i <atomic_read (&kvm->online_vcpus); i++) {if (!kvm->vcpus[i] || kvm->vcpus[i]->arch.mp_state ==KVM_MP_STATE_UNINITIALIZED || vcpu == kvm->vcpus[i])
@@ -852,8 +852,6 @@ struct kvm *kvm_arch_create_vm(void)kvm_init_vm (kvm); - kvm->arch.online_vcpus =0 ; -return kvm; }
@@ -1356,8 +1354,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, goto fail; } - kvm->arch.online_vcpus++; -return vcpu; fail:return ERR_PTR (r);
arch/ia64/kvm/vcpu.c +1 -1
@@ -831,7 +831,7 @@ static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val) kvm = (struct kvm *)KVM_VM_BASE ;if (kvm_vcpu_is_bsp (vcpu)) { -for (i =0 ; i < kvm->arch.online_vcpus; i++) { +for (i =0 ; i <atomic_read (&kvm->online_vcpus); i++) { v = (struct kvm_vcpu *)((char *)vcpu +sizeof (struct kvm_vcpu_data ) * i);VMX (v, itc_offset) = itc_offset;
arch/x86/kvm/Kconfig +1 -0
@@ -27,6 +27,7 @@ config KVM select ANON_INODES select HAVE_KVM_IRQCHIP select HAVE_KVM_EVENTFD + select KVM_APIC_ARCHITECTURE ---help--- Support hosting fully virtualized guest machines using hardware virtualization extensions. You will need a fairly recent
include/linux/kvm.h +2 -0
@@ -430,6 +430,7 @@ struct kvm_trace_rec {#ifdef __KVM_HAVE_PIT#define KVM_CAP_PIT2 33#endif +#define KVM_CAP_SET_BOOT_CPU_ID 34#ifdef KVM_CAP_IRQ_ROUTING
@@ -537,6 +538,7 @@ struct kvm_irqfd {#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config) +#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)/* * ioctls for vcpu fds
include/linux/kvm_host.h +6 -0
@@ -131,8 +131,12 @@ struct kvm {int nmemslots;struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS +KVM_PRIVATE_MEM_SLOTS ]; +#ifdef CONFIG_KVM_APIC_ARCHITECTURE +u32 bsp_vcpu_id;struct kvm_vcpu *bsp_vcpu; +#endif struct kvm_vcpu *vcpus[KVM_MAX_VCPUS ]; +atomic_t online_vcpus;struct list_head vm_list;struct mutex lock;struct kvm_io_bus mmio_bus;
@@ -550,8 +554,10 @@ static inline void kvm_irqfd_release(struct kvm *kvm) {}#endif /* CONFIG_HAVE_KVM_EVENTFD */ +#ifdef CONFIG_KVM_APIC_ARCHITECTURE static inline bool kvm_vcpu_is_bsp (struct kvm_vcpu *vcpu) {return vcpu->kvm->bsp_vcpu == vcpu; }#endif +#endif
virt/kvm/Kconfig +3 -0
@@ -9,3 +9,6 @@ config HAVE_KVM_IRQCHIP config HAVE_KVM_EVENTFD bool select EVENTFD + +config KVM_APIC_ARCHITECTURE + bool
virt/kvm/kvm_main.c +39 -25
111 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH 48/48 KVM: Use macro to iterate over vcpus.
In reply to Avi KivityFrom: Gleb Natapov <[email protected]>
--- arch/ia64/kvm/kvm-ia64.c | 29 ++++++++++++++--------------- arch/powerpc/kvm/powerpc.c | 16 ++++++++++------ arch/s390/kvm/kvm-s390.c | 33 ++++++++++++++++----------------- arch/x86/kvm/i8254.c | 7 ++----- arch/x86/kvm/mmu.c | 6 +++--- arch/x86/kvm/x86.c | 25 ++++++++++++------------- include/linux/kvm_host.h | 11 +++++++++++ virt/kvm/irq_comm.c | 6 ++---- virt/kvm/kvm_main.c | 19 +++++++------------ 9 files changed, 77 insertions(+), 75 deletions(-)
arch/ia64/kvm/kvm-ia64.c +14 -15
@@ -337,13 +337,12 @@ static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id, {union ia64_lid lid;int i; +struct kvm_vcpu *vcpu; -for (i =0 ; i <atomic_read (&kvm->online_vcpus); i++) { -if (kvm->vcpus[i]) { - lid.val =VCPU_LID (kvm->vcpus[i]); -if (lid.id == id && lid.eid == eid) -return kvm->vcpus[i]; - } +kvm_for_each_vcpu (i, vcpu, kvm) { + lid.val =VCPU_LID (vcpu); +if (lid.id == id && lid.eid == eid) +return vcpu; }return NULL ;
@@ -409,21 +408,21 @@ static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)struct kvm *kvm = vcpu->kvm;struct call_data call_data;int i; +struct kvm_vcpu *vcpui; call_data.ptc_g_data = p->u.ptc_g_data; -for (i =0 ; i <atomic_read (&kvm->online_vcpus); i++) { -if (!kvm->vcpus[i] || kvm->vcpus[i]->arch.mp_state == -KVM_MP_STATE_UNINITIALIZED || - vcpu == kvm->vcpus[i]) +kvm_for_each_vcpu (i, vcpui, kvm) { +if (vcpui->arch.mp_state ==KVM_MP_STATE_UNINITIALIZED || + vcpu == vcpui)continue ; -if (waitqueue_active (&kvm->vcpus[i]->wq)) -wake_up_interruptible (&kvm->vcpus[i]->wq); +if (waitqueue_active (&vcpui->wq)) +wake_up_interruptible (&vcpui->wq); -if (kvm->vcpus[i]->cpu !=-1 ) { - call_data.vcpu = kvm->vcpus[i]; -smp_call_function_single (kvm->vcpus[i]->cpu, +if (vcpui->cpu !=-1 ) { + call_data.vcpu = vcpui; +smp_call_function_single (vcpui->cpu, vcpu_global_purge, &call_data,1 ); }else printk (KERN_WARNING "kvm: Uninit vcpu received ipi!\n" );
arch/powerpc/kvm/powerpc.c +10 -6
@@ -122,13 +122,17 @@ struct kvm *kvm_arch_create_vm(void)static void kvmppc_free_vcpus (struct kvm *kvm) {unsigned int i; +struct kvm_vcpu *vcpu; -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) { -if (kvm->vcpus[i]) { -kvm_arch_vcpu_free (kvm->vcpus[i]); - kvm->vcpus[i] =NULL ; - } - } +kvm_for_each_vcpu (i, vcpu, kvm) +kvm_arch_vcpu_free (vcpu); + +mutex_lock (&kvm->lock); +for (i =0 ; i <atomic_read (&kvm->online_vcpus); i++) + kvm->vcpus[i] =NULL ; + +atomic_set (&kvm->online_vcpus,0 ); +mutex_unlock (&kvm->lock); }void kvm_arch_sync_events (struct kvm *kvm)
arch/s390/kvm/kvm-s390.c +16 -17
@@ -211,13 +211,17 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)static void kvm_free_vcpus (struct kvm *kvm) {unsigned int i; +struct kvm_vcpu *vcpu; -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) { -if (kvm->vcpus[i]) { -kvm_arch_vcpu_destroy (kvm->vcpus[i]); - kvm->vcpus[i] =NULL ; - } - } +kvm_for_each_vcpu (i, vcpu, kvm) +kvm_arch_vcpu_destroy (vcpu); + +mutex_lock (&kvm->lock); +for (i =0 ; i <atomic_read (&kvm->online_vcpus); i++) + kvm->vcpus[i] =NULL ; + +atomic_set (&kvm->online_vcpus,0 ); +mutex_unlock (&kvm->lock); }void kvm_arch_sync_events (struct kvm *kvm)
@@ -314,8 +318,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,BUG_ON (!kvm->arch.sca);if (!kvm->arch.sca->cpu[id].sda) kvm->arch.sca->cpu[id].sda = (__u64 ) vcpu->arch.sie_block; -else -BUG_ON (!kvm->vcpus[id]);/* vcpu does already exist */ vcpu->arch.sie_block->scaoh = (__u32)(((__u64 )kvm->arch.sca) >>32 ); vcpu->arch.sie_block->scaol = (__u32 )(__u64 )kvm->arch.sca;
@@ -682,7 +684,8 @@ int kvm_arch_set_memory_region(struct kvm *kvm,struct kvm_memory_slot old, int user_alloc) { -int i; + int i, j = 0, r = -EINVAL; +struct kvm_vcpu *vcpu;/* A few sanity checks. We can have exactly one memory slot which has to start at guest virtual zero and which has to be located at a
@@ -707,14 +710,10 @@ int kvm_arch_set_memory_region(struct kvm *kvm,return -EINVAL ;/* request update of sie control block for all available vcpus */ -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) { -if (kvm->vcpus[i]) { -if (test_and_set_bit (KVM_REQ_MMU_RELOAD , - &kvm->vcpus[i]->requests)) -continue ; -kvm_s390_inject_sigp_stop (kvm->vcpus[i], -ACTION_RELOADVCPU_ON_STOP ); - } +kvm_for_each_vcpu (i, vcpu, kvm) { +if (test_and_set_bit (KVM_REQ_MMU_RELOAD , &vcpu->requests)) +continue ; +kvm_s390_inject_sigp_stop (vcpu,ACTION_RELOADVCPU_ON_STOP ); }return 0 ;
arch/x86/kvm/i8254.c +2 -5
@@ -669,11 +669,8 @@ static void __inject_pit_timer_intr(struct kvm *kvm)* VCPU0, and only if its LVT0 is in EXTINT mode. */ if (kvm->arch.vapics_in_nmi_mode >0 ) -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) { - vcpu = kvm->vcpus[i]; -if (vcpu) -kvm_apic_nmi_wd_deliver (vcpu); - } +kvm_for_each_vcpu (i, vcpu, kvm) +kvm_apic_nmi_wd_deliver (vcpu); }void kvm_inject_pit_timer_irqs (struct kvm_vcpu *vcpu)
arch/x86/kvm/mmu.c +3 -3
@@ -1347,10 +1347,10 @@ static void kvm_mmu_put_page(struct kvm_mmu_page *sp, u64 *parent_pte)static void kvm_mmu_reset_last_pte_updated (struct kvm *kvm) {int i; +struct kvm_vcpu *vcpu; -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) -if (kvm->vcpus[i]) - kvm->vcpus[i]->arch.last_pte_updated =NULL ; +kvm_for_each_vcpu (i, vcpu, kvm) + vcpu->arch.last_pte_updated =NULL ; }static void kvm_mmu_unlink_parents (struct kvm *kvm,struct kvm_mmu_page *sp)
arch/x86/kvm/x86.c +12 -13
@@ -2946,10 +2946,7 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long vaspin_lock (&kvm_lock);list_for_each_entry (kvm, &vm_list, vm_list) { -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) { - vcpu = kvm->vcpus[i]; -if (!vcpu) -continue ; +kvm_for_each_vcpu (i, vcpu, kvm) {if (vcpu->cpu != freq->cpu)continue ;if (!kvm_request_guest_time_update (vcpu))
@@ -4678,20 +4675,22 @@ static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)static void kvm_free_vcpus (struct kvm *kvm) {unsigned int i; +struct kvm_vcpu *vcpu;/* * Unpin any mmu pages first. */ -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) -if (kvm->vcpus[i]) -kvm_unload_vcpu_mmu (kvm->vcpus[i]); -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) { -if (kvm->vcpus[i]) { -kvm_arch_vcpu_free (kvm->vcpus[i]); - kvm->vcpus[i] =NULL ; - } - } +kvm_for_each_vcpu (i, vcpu, kvm) +kvm_unload_vcpu_mmu (vcpu); +kvm_for_each_vcpu (i, vcpu, kvm) +kvm_arch_vcpu_free (vcpu); + +mutex_lock (&kvm->lock); +for (i =0 ; i <atomic_read (&kvm->online_vcpus); i++) + kvm->vcpus[i] =NULL ; +atomic_set (&kvm->online_vcpus,0 ); +mutex_unlock (&kvm->lock); }void kvm_arch_sync_events (struct kvm *kvm)
include/linux/kvm_host.h +11 -0
@@ -179,6 +179,17 @@ struct kvm { #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) #define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt) +static inline struct kvm_vcpu *kvm_get_vcpu (struct kvm *kvm,int i) +{ +smp_rmb (); +return kvm->vcpus[i]; +} + +#define kvm_for_each_vcpu (idx, vcpup, kvm) \ + for (idx = 0, vcpup = kvm_get_vcpu(kvm, idx); \ + idx < atomic_read(&kvm->online_vcpus) && vcpup; \ + vcpup = kvm_get_vcpu(kvm, ++idx)) +int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id);void kvm_vcpu_uninit (struct kvm_vcpu *vcpu);
virt/kvm/irq_comm.c +2 -4
@@ -68,10 +68,8 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, kvm_is_dm_lowest_prio(irq))printk (KERN_INFO "kvm: apic: phys broadcast and lowest prio\n" ); - for (i = 0; i < KVM_MAX_VCPUS; i++) { - vcpu = kvm->vcpus[i]; - - if (!vcpu || !kvm_apic_present(vcpu)) + kvm_for_each_vcpu(i, vcpu, kvm) { + if (!kvm_apic_present(vcpu)) continue; if (!kvm_apic_match_dest(vcpu, src, irq->shorthand,
virt/kvm/kvm_main.c +7 -12
@@ -738,10 +738,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) me =get_cpu ();spin_lock (&kvm->requests_lock); -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) { - vcpu = kvm->vcpus[i]; -if (!vcpu) -continue ; +kvm_for_each_vcpu (i, vcpu, kvm) {if (test_and_set_bit (req, &vcpu->requests))continue ; cpu = vcpu->cpu;
@@ -1718,7 +1715,7 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu)static int kvm_vm_ioctl_create_vcpu (struct kvm *kvm,u32 id) {int r; -struct kvm_vcpu *vcpu; +struct kvm_vcpu *vcpu, *v; vcpu =kvm_arch_vcpu_create (kvm, id);if (IS_ERR (vcpu))
@@ -1736,8 +1733,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) goto vcpu_destroy; } -for (r =0 ; r <atomic_read (&kvm->online_vcpus); r++) -if (kvm->vcpus[r]->vcpu_id == id) { +kvm_for_each_vcpu (r, v, kvm) +if (v->vcpu_id == id) { r = -EEXIST ; goto vcpu_destroy; }
@@ -2526,11 +2523,9 @@ static int vcpu_stat_get(void *_offset, u64 *val) *val =0 ;spin_lock (&kvm_lock);list_for_each_entry (kvm, &vm_list, vm_list) -for (i =0 ; i <KVM_MAX_VCPUS ; ++i) { - vcpu = kvm->vcpus[i]; -if (vcpu) - *val += *(u32 *)((void *)vcpu + offset); - } +kvm_for_each_vcpu (i, vcpu, kvm) + *val += *(u32 *)((void *)vcpu + offset); +spin_unlock (&kvm_lock);return 0 ; }
Signature · 1 line
1.6.3.3