Commit 6245242d authored by Paolo Bonzini's avatar Paolo Bonzini

Merge tag 'kvmarm-fixes-for-5.1-2' of...

Merge tag 'kvmarm-fixes-for-5.1-2' of git://git.kernel.org/pub/scm/linux/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
parents eba3afde 6bc21000
...@@ -507,6 +507,14 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu) ...@@ -507,6 +507,14 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_context *vtimer = vcpu_vtimer(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 * When using a userspace irqchip with the architected timers and a
* host interrupt controller that doesn't support an active state, we * host interrupt controller that doesn't support an active state, we
...@@ -730,7 +738,6 @@ static void kvm_timer_init_interrupt(void *info) ...@@ -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) int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
{ {
struct arch_timer_context *timer; struct arch_timer_context *timer;
bool level;
switch (regid) { switch (regid) {
case KVM_REG_ARM_TIMER_CTL: case KVM_REG_ARM_TIMER_CTL:
...@@ -758,10 +765,6 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) ...@@ -758,10 +765,6 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
return -1; return -1;
} }
level = kvm_timer_should_fire(timer);
kvm_timer_update_irq(vcpu, level, timer);
timer_emulate(timer);
return 0; return 0;
} }
...@@ -812,7 +815,7 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, ...@@ -812,7 +815,7 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
switch (treg) { switch (treg) {
case TIMER_REG_TVAL: 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; break;
case TIMER_REG_CTL: case TIMER_REG_CTL:
...@@ -858,7 +861,7 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu, ...@@ -858,7 +861,7 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
{ {
switch (treg) { switch (treg) {
case TIMER_REG_TVAL: 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; break;
case TIMER_REG_CTL: case TIMER_REG_CTL:
......
...@@ -934,7 +934,7 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, ...@@ -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, static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
const struct kvm_vcpu_init *init) const struct kvm_vcpu_init *init)
{ {
unsigned int i; unsigned int i, ret;
int phys_target = kvm_target_cpu(); int phys_target = kvm_target_cpu();
if (init->target != phys_target) if (init->target != phys_target)
...@@ -969,9 +969,14 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, ...@@ -969,9 +969,14 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
vcpu->arch.target = phys_target; vcpu->arch.target = phys_target;
/* Now we know what it is, we can reset it. */ /* 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, static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
struct kvm_vcpu_init *init) struct kvm_vcpu_init *init)
......
...@@ -1781,8 +1781,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, ...@@ -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 * Only PMD_SIZE transparent hugepages(THP) are
* currently supported. This code will need to be * currently supported. This code will need to be
* updated to support other THP sizes. * 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; vma_pagesize = PMD_SIZE;
} }
......
...@@ -200,6 +200,9 @@ static void vgic_mmio_write_v3r_ctlr(struct kvm_vcpu *vcpu, ...@@ -200,6 +200,9 @@ static void vgic_mmio_write_v3r_ctlr(struct kvm_vcpu *vcpu,
vgic_cpu->lpis_enabled = val & GICR_CTLR_ENABLE_LPIS; 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) if (!was_enabled && vgic_cpu->lpis_enabled)
vgic_enable_lpis(vcpu); vgic_enable_lpis(vcpu);
} }
......
...@@ -151,6 +151,27 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) ...@@ -151,6 +151,27 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
kfree(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) void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending)
{ {
WARN_ON(irq_set_irqchip_state(irq->host_irq, WARN_ON(irq_set_irqchip_state(irq->host_irq,
......
...@@ -238,6 +238,7 @@ void vgic_v3_put(struct kvm_vcpu *vcpu); ...@@ -238,6 +238,7 @@ void vgic_v3_put(struct kvm_vcpu *vcpu);
bool vgic_has_its(struct kvm *kvm); bool vgic_has_its(struct kvm *kvm);
int kvm_vgic_register_its_device(void); int kvm_vgic_register_its_device(void);
void vgic_enable_lpis(struct kvm_vcpu *vcpu); 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_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_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write, int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
......
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