mirror of
https://github.com/torvalds/linux.git
synced 2024-11-19 18:41:48 +00:00
- 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!) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJXYrXKAAoJEL/70l94x66D1MUH/i9kPqfDq+XveHyiY4ovI2Vl lD1P0dJoXPRjrJJ/LRulr3TiGDVsW6QZ8SnA5QNQvxDdlc7CzS8ZgqaiLPUh8TKJ OofVUaFgm77MDvGJuJOOJ159ghO+7KwPsq1P05xpO2HRxAD+q1/u1yjfOz7fIEqC iMne68rfv0OeiMlBOo8G2e1Xmtk1GKNBhmRItUgOF/jVtP2RSvV5o+2rcQ5LS3g6 KV/fpWtRumd3R+TdRvacjADgvWrSokDfph+Ha9qp7sBjkVGLLZ/hdHzTzIimXKF6 x4muv1HYzKSGaCJB2yMLYuy/KJ8zbsk7co0bjn1SmzrSweJxMkDGwLp1Ffau6iM= =N4kr -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
2668bc77a1
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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[];
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user