Commit 2668bc77 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull KVM fixes from Paolo Bonzini:

 - miscellaneous fixes for MIPS and s390

 - one new kvm_stat for s390

 - correctly disable VT-d posted interrupts with the rest of posted
   interrupts

 - "make randconfig" fix for x86 AMD

 - off-by-one in irq route check (the "good" kind that errors out a bit
   too early!)

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  kvm: vmx: check apicv is active before using VT-d posted interrupt
  kvm: Fix irq route entries exceeding KVM_MAX_IRQ_ROUTES
  kvm: svm: Do not support AVIC if not CONFIG_X86_LOCAL_APIC
  kvm: svm: Fix implicit declaration for __default_cpu_present_to_apicid()
  MIPS: KVM: Fix CACHE triggered exception emulation
  MIPS: KVM: Don't unwind PC when emulating CACHE
  MIPS: KVM: Include bit 31 in segment matches
  MIPS: KVM: Fix modular KVM under QEMU
  KVM: s390: Add stats for PEI events
  KVM: s390: ignore IBC if zero
parents 41ef7218 a0052191
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
#define KVM_GUEST_KUSEG 0x00000000UL #define KVM_GUEST_KUSEG 0x00000000UL
#define KVM_GUEST_KSEG0 0x40000000UL #define KVM_GUEST_KSEG0 0x40000000UL
#define KVM_GUEST_KSEG23 0x60000000UL #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_CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff)
#define KVM_GUEST_CKSEG0ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0) #define KVM_GUEST_CKSEG0ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0)
...@@ -338,6 +338,7 @@ struct kvm_mips_tlb { ...@@ -338,6 +338,7 @@ struct kvm_mips_tlb {
#define KVM_MIPS_GUEST_TLB_SIZE 64 #define KVM_MIPS_GUEST_TLB_SIZE 64
struct kvm_vcpu_arch { struct kvm_vcpu_arch {
void *host_ebase, *guest_ebase; void *host_ebase, *guest_ebase;
int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu);
unsigned long host_stack; unsigned long host_stack;
unsigned long host_gp; unsigned long host_gp;
......
...@@ -1636,6 +1636,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, ...@@ -1636,6 +1636,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
if (index < 0) { if (index < 0) {
vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK); vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
vcpu->arch.host_cp0_badvaddr = va; vcpu->arch.host_cp0_badvaddr = va;
vcpu->arch.pc = curr_pc;
er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run, er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
vcpu); vcpu);
preempt_enable(); preempt_enable();
...@@ -1647,6 +1648,8 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, ...@@ -1647,6 +1648,8 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
* invalid exception to the guest * invalid exception to the guest
*/ */
if (!TLB_IS_VALID(*tlb, va)) { 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, er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
run, vcpu); run, vcpu);
preempt_enable(); preempt_enable();
...@@ -1666,7 +1669,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, ...@@ -1666,7 +1669,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
cache, op, base, arch->gprs[base], offset); cache, op, base, arch->gprs[base], offset);
er = EMULATE_FAIL; er = EMULATE_FAIL;
preempt_enable(); preempt_enable();
goto dont_update_pc; goto done;
} }
...@@ -1694,16 +1697,20 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, ...@@ -1694,16 +1697,20 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n", kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
cache, op, base, arch->gprs[base], offset); cache, op, base, arch->gprs[base], offset);
er = EMULATE_FAIL; er = EMULATE_FAIL;
preempt_enable();
goto dont_update_pc;
} }
preempt_enable(); preempt_enable();
done:
/* Rollback PC only if emulation was unsuccessful */
if (er == EMULATE_FAIL)
vcpu->arch.pc = curr_pc;
dont_update_pc: dont_update_pc:
/* Rollback PC */ /*
vcpu->arch.pc = curr_pc; * This is for exceptions whose emulation updates the PC, so do not
done: * overwrite the PC under any circumstances
*/
return er; return er;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define MIPS_EXC_MAX 12 #define MIPS_EXC_MAX 12
/* XXXSL More to follow */ /* XXXSL More to follow */
extern char __kvm_mips_vcpu_run_end[];
extern char mips32_exception[], mips32_exceptionEnd[]; extern char mips32_exception[], mips32_exceptionEnd[];
extern char mips32_GuestException[], mips32_GuestExceptionEnd[]; extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
......
...@@ -202,6 +202,7 @@ FEXPORT(__kvm_mips_load_k0k1) ...@@ -202,6 +202,7 @@ FEXPORT(__kvm_mips_load_k0k1)
/* Jump to guest */ /* Jump to guest */
eret eret
EXPORT(__kvm_mips_vcpu_run_end)
VECTOR(MIPSX(exception), unknown) VECTOR(MIPSX(exception), unknown)
/* Find out what mode we came from and jump to the proper handler. */ /* Find out what mode we came from and jump to the proper handler. */
......
...@@ -315,6 +315,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) ...@@ -315,6 +315,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
memcpy(gebase + offset, mips32_GuestException, memcpy(gebase + offset, mips32_GuestException,
mips32_GuestExceptionEnd - 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 */ /* Invalidate the icache for these ranges */
local_flush_icache_range((unsigned long)gebase, local_flush_icache_range((unsigned long)gebase,
(unsigned long)gebase + ALIGN(size, PAGE_SIZE)); (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) ...@@ -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 */ /* Disable hardware page table walking while in guest */
htw_stop(); htw_stop();
r = __kvm_mips_vcpu_run(run, vcpu); r = vcpu->arch.vcpu_run(run, vcpu);
/* Re-enable HTW before enabling interrupts */ /* Re-enable HTW before enabling interrupts */
htw_start(); htw_start();
......
...@@ -245,6 +245,7 @@ struct kvm_vcpu_stat { ...@@ -245,6 +245,7 @@ struct kvm_vcpu_stat {
u32 exit_stop_request; u32 exit_stop_request;
u32 exit_validity; u32 exit_validity;
u32 exit_instruction; u32 exit_instruction;
u32 exit_pei;
u32 halt_successful_poll; u32 halt_successful_poll;
u32 halt_attempted_poll; u32 halt_attempted_poll;
u32 halt_poll_invalid; u32 halt_poll_invalid;
......
...@@ -341,6 +341,8 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu) ...@@ -341,6 +341,8 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
static int handle_partial_execution(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 */ if (vcpu->arch.sie_block->ipa == 0xb254) /* MVPG */
return handle_mvpg_pei(vcpu); return handle_mvpg_pei(vcpu);
if (vcpu->arch.sie_block->ipa >> 8 == 0xae) /* SIGP */ if (vcpu->arch.sie_block->ipa >> 8 == 0xae) /* SIGP */
......
...@@ -61,6 +61,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { ...@@ -61,6 +61,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "exit_external_request", VCPU_STAT(exit_external_request) }, { "exit_external_request", VCPU_STAT(exit_external_request) },
{ "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) }, { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
{ "exit_instruction", VCPU_STAT(exit_instruction) }, { "exit_instruction", VCPU_STAT(exit_instruction) },
{ "exit_pei", VCPU_STAT(exit_pei) },
{ "exit_program_interruption", VCPU_STAT(exit_program_interruption) }, { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
{ "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) }, { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
{ "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, { "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) ...@@ -657,7 +658,7 @@ static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)
kvm->arch.model.cpuid = proc->cpuid; kvm->arch.model.cpuid = proc->cpuid;
lowest_ibc = sclp.ibc >> 16 & 0xfff; lowest_ibc = sclp.ibc >> 16 & 0xfff;
unblocked_ibc = sclp.ibc & 0xfff; unblocked_ibc = sclp.ibc & 0xfff;
if (lowest_ibc) { if (lowest_ibc && proc->ibc) {
if (proc->ibc > unblocked_ibc) if (proc->ibc > unblocked_ibc)
kvm->arch.model.ibc = unblocked_ibc; kvm->arch.model.ibc = unblocked_ibc;
else if (proc->ibc < lowest_ibc) else if (proc->ibc < lowest_ibc)
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/irqbypass.h> #include <linux/irqbypass.h>
#include <linux/hyperv.h> #include <linux/hyperv.h>
#include <asm/apic.h>
#include <asm/pvclock-abi.h> #include <asm/pvclock-abi.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
...@@ -1368,4 +1369,14 @@ static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) ...@@ -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 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 */ #endif /* _ASM_X86_KVM_HOST_H */
...@@ -238,7 +238,9 @@ module_param(nested, int, S_IRUGO); ...@@ -238,7 +238,9 @@ module_param(nested, int, S_IRUGO);
/* enable / disable AVIC */ /* enable / disable AVIC */
static int avic; static int avic;
#ifdef CONFIG_X86_LOCAL_APIC
module_param(avic, int, S_IRUGO); module_param(avic, int, S_IRUGO);
#endif
static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
static void svm_flush_tlb(struct kvm_vcpu *vcpu); static void svm_flush_tlb(struct kvm_vcpu *vcpu);
...@@ -981,11 +983,14 @@ static __init int svm_hardware_setup(void) ...@@ -981,11 +983,14 @@ static __init int svm_hardware_setup(void)
} else } else
kvm_disable_tdp(); kvm_disable_tdp();
if (avic && (!npt_enabled || !boot_cpu_has(X86_FEATURE_AVIC))) if (avic) {
avic = false; if (!npt_enabled ||
!boot_cpu_has(X86_FEATURE_AVIC) ||
if (avic) !IS_ENABLED(CONFIG_X86_LOCAL_APIC))
pr_info("AVIC enabled\n"); avic = false;
else
pr_info("AVIC enabled\n");
}
return 0; return 0;
...@@ -1324,7 +1329,7 @@ static int avic_vm_init(struct kvm *kvm) ...@@ -1324,7 +1329,7 @@ static int avic_vm_init(struct kvm *kvm)
static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run) static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
{ {
u64 entry; 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); struct vcpu_svm *svm = to_svm(vcpu);
if (!kvm_vcpu_apicv_active(vcpu)) if (!kvm_vcpu_apicv_active(vcpu))
...@@ -1349,7 +1354,7 @@ static void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu) ...@@ -1349,7 +1354,7 @@ static void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{ {
u64 entry; u64 entry;
/* ID = 0xff (broadcast), ID > 0xff (reserved) */ /* 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); struct vcpu_svm *svm = to_svm(vcpu);
if (!kvm_vcpu_apicv_active(vcpu)) if (!kvm_vcpu_apicv_active(vcpu))
...@@ -4236,7 +4241,7 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec) ...@@ -4236,7 +4241,7 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
if (avic_vcpu_is_running(vcpu)) if (avic_vcpu_is_running(vcpu))
wrmsrl(SVM_AVIC_DOORBELL, wrmsrl(SVM_AVIC_DOORBELL,
__default_cpu_present_to_apicid(vcpu->cpu)); kvm_cpu_get_apicid(vcpu->cpu));
else else
kvm_vcpu_wake_up(vcpu); kvm_vcpu_wake_up(vcpu);
} }
......
...@@ -2072,7 +2072,8 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu) ...@@ -2072,7 +2072,8 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
unsigned int dest; unsigned int dest;
if (!kvm_arch_has_assigned_device(vcpu->kvm) || 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; return;
do { do {
...@@ -2180,7 +2181,8 @@ static void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu) ...@@ -2180,7 +2181,8 @@ static void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
if (!kvm_arch_has_assigned_device(vcpu->kvm) || 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; return;
/* Set SN when the vCPU is preempted */ /* Set SN when the vCPU is preempted */
...@@ -10714,7 +10716,8 @@ static int vmx_pre_block(struct kvm_vcpu *vcpu) ...@@ -10714,7 +10716,8 @@ static int vmx_pre_block(struct kvm_vcpu *vcpu)
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
if (!kvm_arch_has_assigned_device(vcpu->kvm) || 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; return 0;
vcpu->pre_pcpu = vcpu->cpu; vcpu->pre_pcpu = vcpu->cpu;
...@@ -10780,7 +10783,8 @@ static void vmx_post_block(struct kvm_vcpu *vcpu) ...@@ -10780,7 +10783,8 @@ static void vmx_post_block(struct kvm_vcpu *vcpu)
unsigned long flags; unsigned long flags;
if (!kvm_arch_has_assigned_device(vcpu->kvm) || 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; return;
do { do {
...@@ -10833,7 +10837,8 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq, ...@@ -10833,7 +10837,8 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
int idx, ret = -EINVAL; int idx, ret = -EINVAL;
if (!kvm_arch_has_assigned_device(kvm) || 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; return 0;
idx = srcu_read_lock(&kvm->irq_srcu); idx = srcu_read_lock(&kvm->irq_srcu);
......
...@@ -2941,7 +2941,7 @@ static long kvm_vm_ioctl(struct file *filp, ...@@ -2941,7 +2941,7 @@ static long kvm_vm_ioctl(struct file *filp,
if (copy_from_user(&routing, argp, sizeof(routing))) if (copy_from_user(&routing, argp, sizeof(routing)))
goto out; goto out;
r = -EINVAL; r = -EINVAL;
if (routing.nr >= KVM_MAX_IRQ_ROUTES) if (routing.nr > KVM_MAX_IRQ_ROUTES)
goto out; goto out;
if (routing.flags) if (routing.flags)
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment