mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 05:04:09 +08:00
RISC-V: KVM: Fix kvm_riscv_vcpu_timer_pending() for Sstc
The kvm_riscv_vcpu_timer_pending() checks per-VCPU next_cycles
and per-VCPU software injected VS timer interrupt. This function
returns incorrect value when Sstc is available because the per-VCPU
next_cycles are only updated by kvm_riscv_vcpu_timer_save() called
from kvm_arch_vcpu_put(). As a result, when Sstc is available the
VCPU does not block properly upon WFI traps.
To fix the above issue, we introduce kvm_riscv_vcpu_timer_sync()
which will update per-VCPU next_cycles upon every VM exit instead
of kvm_riscv_vcpu_timer_save().
Fixes: 8f5cb44b1b
("RISC-V: KVM: Support sstc extension")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
parent
5c20a3a9df
commit
cea8896bd9
@ -45,6 +45,7 @@ int kvm_riscv_vcpu_timer_deinit(struct kvm_vcpu *vcpu);
|
||||
int kvm_riscv_vcpu_timer_reset(struct kvm_vcpu *vcpu);
|
||||
void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu);
|
||||
void kvm_riscv_guest_timer_init(struct kvm *kvm);
|
||||
void kvm_riscv_vcpu_timer_sync(struct kvm_vcpu *vcpu);
|
||||
void kvm_riscv_vcpu_timer_save(struct kvm_vcpu *vcpu);
|
||||
bool kvm_riscv_vcpu_timer_pending(struct kvm_vcpu *vcpu);
|
||||
|
||||
|
@ -708,6 +708,9 @@ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
|
||||
clear_bit(IRQ_VS_SOFT, &v->irqs_pending);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sync-up timer CSRs */
|
||||
kvm_riscv_vcpu_timer_sync(vcpu);
|
||||
}
|
||||
|
||||
int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
|
||||
|
@ -320,6 +320,21 @@ void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
|
||||
kvm_riscv_vcpu_timer_unblocking(vcpu);
|
||||
}
|
||||
|
||||
void kvm_riscv_vcpu_timer_sync(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_timer *t = &vcpu->arch.timer;
|
||||
|
||||
if (!t->sstc_enabled)
|
||||
return;
|
||||
|
||||
#if defined(CONFIG_32BIT)
|
||||
t->next_cycles = csr_read(CSR_VSTIMECMP);
|
||||
t->next_cycles |= (u64)csr_read(CSR_VSTIMECMPH) << 32;
|
||||
#else
|
||||
t->next_cycles = csr_read(CSR_VSTIMECMP);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kvm_riscv_vcpu_timer_save(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_timer *t = &vcpu->arch.timer;
|
||||
@ -327,13 +342,11 @@ void kvm_riscv_vcpu_timer_save(struct kvm_vcpu *vcpu)
|
||||
if (!t->sstc_enabled)
|
||||
return;
|
||||
|
||||
t = &vcpu->arch.timer;
|
||||
#if defined(CONFIG_32BIT)
|
||||
t->next_cycles = csr_read(CSR_VSTIMECMP);
|
||||
t->next_cycles |= (u64)csr_read(CSR_VSTIMECMPH) << 32;
|
||||
#else
|
||||
t->next_cycles = csr_read(CSR_VSTIMECMP);
|
||||
#endif
|
||||
/*
|
||||
* The vstimecmp CSRs are saved by kvm_riscv_vcpu_timer_sync()
|
||||
* upon every VM exit so no need to save here.
|
||||
*/
|
||||
|
||||
/* timer should be enabled for the remaining operations */
|
||||
if (unlikely(!t->init_done))
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user