Skip to content

Commit

Permalink
Merge tag 'kvmarm-fixes-for-5.1-2' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/kvmarm/kvmarm into kvm-master

KVM/ARM fixes for 5.1, take #2:

- Don't try to emulate timers on userspace access
- Fix unaligned huge mappings, again
- Properly reset a vcpu that fails to reset(!)
- Properly retire pending LPIs on reset
- Fix computation of emulated CNTP_TVAL
  • Loading branch information
bonzini committed Apr 30, 2019
2 parents eba3afd + 6bc2100 commit 6245242
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 11 deletions.
17 changes: 10 additions & 7 deletions virt/kvm/arm/arch_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,14 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
{
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);

/*
* Update the timer output so that it is likely to match the
* state we're about to restore. If the timer expires between
* this point and the register restoration, we'll take the
* interrupt anyway.
*/
kvm_timer_update_irq(vcpu, kvm_timer_should_fire(vtimer), vtimer);

/*
* When using a userspace irqchip with the architected timers and a
* host interrupt controller that doesn't support an active state, we
Expand Down Expand Up @@ -730,7 +738,6 @@ static void kvm_timer_init_interrupt(void *info)
int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
{
struct arch_timer_context *timer;
bool level;

switch (regid) {
case KVM_REG_ARM_TIMER_CTL:
Expand Down Expand Up @@ -758,10 +765,6 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
return -1;
}

level = kvm_timer_should_fire(timer);
kvm_timer_update_irq(vcpu, level, timer);
timer_emulate(timer);

return 0;
}

Expand Down Expand Up @@ -812,7 +815,7 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,

switch (treg) {
case TIMER_REG_TVAL:
val = kvm_phys_timer_read() - timer->cntvoff - timer->cnt_cval;
val = timer->cnt_cval - kvm_phys_timer_read() + timer->cntvoff;
break;

case TIMER_REG_CTL:
Expand Down Expand Up @@ -858,7 +861,7 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
{
switch (treg) {
case TIMER_REG_TVAL:
timer->cnt_cval = val - kvm_phys_timer_read() - timer->cntvoff;
timer->cnt_cval = kvm_phys_timer_read() - timer->cntvoff + val;
break;

case TIMER_REG_CTL:
Expand Down
11 changes: 8 additions & 3 deletions virt/kvm/arm/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -934,7 +934,7 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
const struct kvm_vcpu_init *init)
{
unsigned int i;
unsigned int i, ret;
int phys_target = kvm_target_cpu();

if (init->target != phys_target)
Expand Down Expand Up @@ -969,9 +969,14 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
vcpu->arch.target = phys_target;

/* Now we know what it is, we can reset it. */
return kvm_reset_vcpu(vcpu);
}
ret = kvm_reset_vcpu(vcpu);
if (ret) {
vcpu->arch.target = -1;
bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
}

return ret;
}

static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
struct kvm_vcpu_init *init)
Expand Down
6 changes: 5 additions & 1 deletion virt/kvm/arm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1781,8 +1781,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
* Only PMD_SIZE transparent hugepages(THP) are
* currently supported. This code will need to be
* updated to support other THP sizes.
*
* Make sure the host VA and the guest IPA are sufficiently
* aligned and that the block is contained within the memslot.
*/
if (transparent_hugepage_adjust(&pfn, &fault_ipa))
if (fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE) &&
transparent_hugepage_adjust(&pfn, &fault_ipa))
vma_pagesize = PMD_SIZE;
}

Expand Down
3 changes: 3 additions & 0 deletions virt/kvm/arm/vgic/vgic-mmio-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ static void vgic_mmio_write_v3r_ctlr(struct kvm_vcpu *vcpu,

vgic_cpu->lpis_enabled = val & GICR_CTLR_ENABLE_LPIS;

if (was_enabled && !vgic_cpu->lpis_enabled)
vgic_flush_pending_lpis(vcpu);

if (!was_enabled && vgic_cpu->lpis_enabled)
vgic_enable_lpis(vcpu);
}
Expand Down
21 changes: 21 additions & 0 deletions virt/kvm/arm/vgic/vgic.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,27 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
kfree(irq);
}

void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)
{
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_irq *irq, *tmp;
unsigned long flags;

raw_spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);

list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
if (irq->intid >= VGIC_MIN_LPI) {
raw_spin_lock(&irq->irq_lock);
list_del(&irq->ap_list);
irq->vcpu = NULL;
raw_spin_unlock(&irq->irq_lock);
vgic_put_irq(vcpu->kvm, irq);
}
}

raw_spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
}

void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending)
{
WARN_ON(irq_set_irqchip_state(irq->host_irq,
Expand Down
1 change: 1 addition & 0 deletions virt/kvm/arm/vgic/vgic.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ void vgic_v3_put(struct kvm_vcpu *vcpu);
bool vgic_has_its(struct kvm *kvm);
int kvm_vgic_register_its_device(void);
void vgic_enable_lpis(struct kvm_vcpu *vcpu);
void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu);
int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
Expand Down

0 comments on commit 6245242

Please sign in to comment.