forked from Minki/linux
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 -----BEGIN PGP SIGNATURE----- iQJJBAABCgAzFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAlzBuBEVHG1hcmMuenlu Z2llckBhcm0uY29tAAoJECPQ0LrRPXpDM8MP/2bpQQCNTZNzEiVUDLk49ADKslHX TGo3QA8hCCeZLcjgqe+Qu4GsskaP11Ci2AU8qEzlj2nPFVGos1FV1FpVy9eGh8y/ dEl0IN3gKBTSpNDM2rBPbdh3UBNU5YA6t59/GMzo1LHu5jU6FOFMKs3eGgpl4Nt6 d47jIvMLEictoShbZe0s9S6m2MNfg+hP0d44XI6wssF8fSme2xHDXUI3sk96zQlj QmI+orDLBIcZLCGfielCEk3f//ZADmsQ2voIxetBWp4lsA8buZNcsMW1rTWdrd1S /UMvBBot57qITJV5xDHnU4wcgaAxOp46148jRRF8u3qd5VER9idDWRz/mNayfCsL 0+KGY4eF8X8K600IuOrKjjKd6Wq1t2+qYbg7GKgxRaVJX6PQ+2T0IyehyvXCyXWB s4o2F1NDmJhnLpcep73gjNWa/WUvrMDkj8pnn+Bo3A9516Q7b0/KxPgMFHSLlje5 dvUqqVCUFi8xqnSzA5fGwx0amUomYHD2YRDUZpX8MjaPaptVzQHeMT60S14Z3pP7 dvRS5cNI6PLpM9/o/gsM4o3PVF+7z6HPJf93y5tU8yUSPyWp4e7VLPckt+wJyEbo EGIVsxEBpOyLo4ByXnrId2d0IE90cXVtA2W8j8H1lIlmmzN57O6k+nm0K1x4bh/i qCTV8pngeLtmpLVD =Orvj -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
6245242d91
@ -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
|
||||
@ -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:
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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:
|
||||
@ -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:
|
||||
|
@ -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)
|
||||
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user