diff options
| -rw-r--r-- | arch/mips/include/asm/kvm_host.h | 3 | ||||
| -rw-r--r-- | arch/mips/kvm/emulate.c | 19 | ||||
| -rw-r--r-- | arch/mips/kvm/interrupt.h | 1 | ||||
| -rw-r--r-- | arch/mips/kvm/locore.S | 1 | ||||
| -rw-r--r-- | arch/mips/kvm/mips.c | 11 | ||||
| -rw-r--r-- | arch/s390/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/s390/kvm/intercept.c | 2 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 3 | ||||
| -rw-r--r-- | arch/x86/include/asm/kvm_host.h | 11 | ||||
| -rw-r--r-- | arch/x86/kvm/svm.c | 21 | ||||
| -rw-r--r-- | arch/x86/kvm/vmx.c | 15 | ||||
| -rw-r--r-- | virt/kvm/kvm_main.c | 2 | 
12 files changed, 67 insertions, 23 deletions
| diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 6733ac575da4..36a391d289aa 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -74,7 +74,7 @@  #define KVM_GUEST_KUSEG			0x00000000UL  #define KVM_GUEST_KSEG0			0x40000000UL  #define KVM_GUEST_KSEG23		0x60000000UL -#define KVM_GUEST_KSEGX(a)		((_ACAST32_(a)) & 0x60000000) +#define KVM_GUEST_KSEGX(a)		((_ACAST32_(a)) & 0xe0000000)  #define KVM_GUEST_CPHYSADDR(a)		((_ACAST32_(a)) & 0x1fffffff)  #define KVM_GUEST_CKSEG0ADDR(a)		(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0) @@ -338,6 +338,7 @@ struct kvm_mips_tlb {  #define KVM_MIPS_GUEST_TLB_SIZE	64  struct kvm_vcpu_arch {  	void *host_ebase, *guest_ebase; +	int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu);  	unsigned long host_stack;  	unsigned long host_gp; diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index 396df6eb0a12..645c8a1982a7 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -1636,6 +1636,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,  		if (index < 0) {  			vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);  			vcpu->arch.host_cp0_badvaddr = va; +			vcpu->arch.pc = curr_pc;  			er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,  							 vcpu);  			preempt_enable(); @@ -1647,6 +1648,8 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,  			 * invalid exception to the guest  			 */  			if (!TLB_IS_VALID(*tlb, va)) { +				vcpu->arch.host_cp0_badvaddr = va; +				vcpu->arch.pc = curr_pc;  				er = kvm_mips_emulate_tlbinv_ld(cause, NULL,  								run, vcpu);  				preempt_enable(); @@ -1666,7 +1669,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,  			cache, op, base, arch->gprs[base], offset);  		er = EMULATE_FAIL;  		preempt_enable(); -		goto dont_update_pc; +		goto done;  	} @@ -1694,16 +1697,20 @@ skip_fault:  		kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",  			cache, op, base, arch->gprs[base], offset);  		er = EMULATE_FAIL; -		preempt_enable(); -		goto dont_update_pc;  	}  	preempt_enable(); +done: +	/* Rollback PC only if emulation was unsuccessful */ +	if (er == EMULATE_FAIL) +		vcpu->arch.pc = curr_pc;  dont_update_pc: -	/* Rollback PC */ -	vcpu->arch.pc = curr_pc; -done: +	/* +	 * This is for exceptions whose emulation updates the PC, so do not +	 * overwrite the PC under any circumstances +	 */ +  	return er;  } diff --git a/arch/mips/kvm/interrupt.h b/arch/mips/kvm/interrupt.h index 4ab4bdfad703..2143884709e4 100644 --- a/arch/mips/kvm/interrupt.h +++ b/arch/mips/kvm/interrupt.h @@ -28,6 +28,7 @@  #define MIPS_EXC_MAX                12  /* XXXSL More to follow */ +extern char __kvm_mips_vcpu_run_end[];  extern char mips32_exception[], mips32_exceptionEnd[];  extern char mips32_GuestException[], mips32_GuestExceptionEnd[]; diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index 3ef03009de5f..828fcfc1cd7f 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -202,6 +202,7 @@ FEXPORT(__kvm_mips_load_k0k1)  	/* Jump to guest */  	eret +EXPORT(__kvm_mips_vcpu_run_end)  VECTOR(MIPSX(exception), unknown)  /* Find out what mode we came from and jump to the proper handler. */ diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index dc052fb5c7a2..44da5259f390 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -315,6 +315,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)  	memcpy(gebase + offset, mips32_GuestException,  	       mips32_GuestExceptionEnd - mips32_GuestException); +#ifdef MODULE +	offset += mips32_GuestExceptionEnd - mips32_GuestException; +	memcpy(gebase + offset, (char *)__kvm_mips_vcpu_run, +	       __kvm_mips_vcpu_run_end - (char *)__kvm_mips_vcpu_run); +	vcpu->arch.vcpu_run = gebase + offset; +#else +	vcpu->arch.vcpu_run = __kvm_mips_vcpu_run; +#endif +  	/* Invalidate the icache for these ranges */  	local_flush_icache_range((unsigned long)gebase,  				(unsigned long)gebase + ALIGN(size, PAGE_SIZE)); @@ -404,7 +413,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)  	/* Disable hardware page table walking while in guest */  	htw_stop(); -	r = __kvm_mips_vcpu_run(run, vcpu); +	r = vcpu->arch.vcpu_run(run, vcpu);  	/* Re-enable HTW before enabling interrupts */  	htw_start(); diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 37b9017c6a96..ac82e8eb936d 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -245,6 +245,7 @@ struct kvm_vcpu_stat {  	u32 exit_stop_request;  	u32 exit_validity;  	u32 exit_instruction; +	u32 exit_pei;  	u32 halt_successful_poll;  	u32 halt_attempted_poll;  	u32 halt_poll_invalid; diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 2e6b54e4d3f9..252157181302 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -341,6 +341,8 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)  static int handle_partial_execution(struct kvm_vcpu *vcpu)  { +	vcpu->stat.exit_pei++; +  	if (vcpu->arch.sie_block->ipa == 0xb254)	/* MVPG */  		return handle_mvpg_pei(vcpu);  	if (vcpu->arch.sie_block->ipa >> 8 == 0xae)	/* SIGP */ diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 6d8ec3ac9dd8..43f2a2b80490 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -61,6 +61,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {  	{ "exit_external_request", VCPU_STAT(exit_external_request) },  	{ "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },  	{ "exit_instruction", VCPU_STAT(exit_instruction) }, +	{ "exit_pei", VCPU_STAT(exit_pei) },  	{ "exit_program_interruption", VCPU_STAT(exit_program_interruption) },  	{ "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },  	{ "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, @@ -657,7 +658,7 @@ static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)  		kvm->arch.model.cpuid = proc->cpuid;  		lowest_ibc = sclp.ibc >> 16 & 0xfff;  		unblocked_ibc = sclp.ibc & 0xfff; -		if (lowest_ibc) { +		if (lowest_ibc && proc->ibc) {  			if (proc->ibc > unblocked_ibc)  				kvm->arch.model.ibc = unblocked_ibc;  			else if (proc->ibc < lowest_ibc) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index e0fbe7e70dc1..69e62862b622 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -27,6 +27,7 @@  #include <linux/irqbypass.h>  #include <linux/hyperv.h> +#include <asm/apic.h>  #include <asm/pvclock-abi.h>  #include <asm/desc.h>  #include <asm/mtrr.h> @@ -1368,4 +1369,14 @@ static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)  static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {} +static inline int kvm_cpu_get_apicid(int mps_cpu) +{ +#ifdef CONFIG_X86_LOCAL_APIC +	return __default_cpu_present_to_apicid(mps_cpu); +#else +	WARN_ON_ONCE(1); +	return BAD_APICID; +#endif +} +  #endif /* _ASM_X86_KVM_HOST_H */ diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 1163e8173e5a..16ef31b87452 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -238,7 +238,9 @@ module_param(nested, int, S_IRUGO);  /* enable / disable AVIC */  static int avic; +#ifdef CONFIG_X86_LOCAL_APIC  module_param(avic, int, S_IRUGO); +#endif  static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);  static void svm_flush_tlb(struct kvm_vcpu *vcpu); @@ -981,11 +983,14 @@ static __init int svm_hardware_setup(void)  	} else  		kvm_disable_tdp(); -	if (avic && (!npt_enabled || !boot_cpu_has(X86_FEATURE_AVIC))) -		avic = false; - -	if (avic) -		pr_info("AVIC enabled\n"); +	if (avic) { +		if (!npt_enabled || +		    !boot_cpu_has(X86_FEATURE_AVIC) || +		    !IS_ENABLED(CONFIG_X86_LOCAL_APIC)) +			avic = false; +		else +			pr_info("AVIC enabled\n"); +	}  	return 0; @@ -1324,7 +1329,7 @@ free_avic:  static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run)  {  	u64 entry; -	int h_physical_id = __default_cpu_present_to_apicid(vcpu->cpu); +	int h_physical_id = kvm_cpu_get_apicid(vcpu->cpu);  	struct vcpu_svm *svm = to_svm(vcpu);  	if (!kvm_vcpu_apicv_active(vcpu)) @@ -1349,7 +1354,7 @@ static void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)  {  	u64 entry;  	/* ID = 0xff (broadcast), ID > 0xff (reserved) */ -	int h_physical_id = __default_cpu_present_to_apicid(cpu); +	int h_physical_id = kvm_cpu_get_apicid(cpu);  	struct vcpu_svm *svm = to_svm(vcpu);  	if (!kvm_vcpu_apicv_active(vcpu)) @@ -4236,7 +4241,7 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)  	if (avic_vcpu_is_running(vcpu))  		wrmsrl(SVM_AVIC_DOORBELL, -		       __default_cpu_present_to_apicid(vcpu->cpu)); +		       kvm_cpu_get_apicid(vcpu->cpu));  	else  		kvm_vcpu_wake_up(vcpu);  } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index fb93010beaa4..003618e324ce 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2072,7 +2072,8 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)  	unsigned int dest;  	if (!kvm_arch_has_assigned_device(vcpu->kvm) || -		!irq_remapping_cap(IRQ_POSTING_CAP)) +		!irq_remapping_cap(IRQ_POSTING_CAP)  || +		!kvm_vcpu_apicv_active(vcpu))  		return;  	do { @@ -2180,7 +2181,8 @@ static void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)  	struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);  	if (!kvm_arch_has_assigned_device(vcpu->kvm) || -		!irq_remapping_cap(IRQ_POSTING_CAP)) +		!irq_remapping_cap(IRQ_POSTING_CAP)  || +		!kvm_vcpu_apicv_active(vcpu))  		return;  	/* Set SN when the vCPU is preempted */ @@ -10714,7 +10716,8 @@ static int vmx_pre_block(struct kvm_vcpu *vcpu)  	struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);  	if (!kvm_arch_has_assigned_device(vcpu->kvm) || -		!irq_remapping_cap(IRQ_POSTING_CAP)) +		!irq_remapping_cap(IRQ_POSTING_CAP)  || +		!kvm_vcpu_apicv_active(vcpu))  		return 0;  	vcpu->pre_pcpu = vcpu->cpu; @@ -10780,7 +10783,8 @@ static void vmx_post_block(struct kvm_vcpu *vcpu)  	unsigned long flags;  	if (!kvm_arch_has_assigned_device(vcpu->kvm) || -		!irq_remapping_cap(IRQ_POSTING_CAP)) +		!irq_remapping_cap(IRQ_POSTING_CAP)  || +		!kvm_vcpu_apicv_active(vcpu))  		return;  	do { @@ -10833,7 +10837,8 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq,  	int idx, ret = -EINVAL;  	if (!kvm_arch_has_assigned_device(kvm) || -		!irq_remapping_cap(IRQ_POSTING_CAP)) +		!irq_remapping_cap(IRQ_POSTING_CAP) || +		!kvm_vcpu_apicv_active(kvm->vcpus[0]))  		return 0;  	idx = srcu_read_lock(&kvm->irq_srcu); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 02e98f3131bd..48bd520fc702 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2941,7 +2941,7 @@ static long kvm_vm_ioctl(struct file *filp,  		if (copy_from_user(&routing, argp, sizeof(routing)))  			goto out;  		r = -EINVAL; -		if (routing.nr >= KVM_MAX_IRQ_ROUTES) +		if (routing.nr > KVM_MAX_IRQ_ROUTES)  			goto out;  		if (routing.flags)  			goto out; | 
