Skip to content

Commit

Permalink
Merge tag 'kvmarm-fixes-for-5.2-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 HEAD

KVM/arm fixes for 5.2, take #2

- SVE cleanup killing a warning with ancient GCC versions
- Don't report non-existent system registers to userspace
- Fix memory leak when freeing the vgic ITS
- Properly lower the interrupt on the emulated physical timer
  • Loading branch information
bonzini committed Jun 20, 2019
2 parents 9fd5887 + e4e5a86 commit b21e31b
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 24 deletions.
65 changes: 43 additions & 22 deletions arch/arm64/kvm/guest.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ static u64 core_reg_offset_from_id(u64 id)
return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE);
}

static int validate_core_offset(const struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg)
static int core_reg_size_from_offset(const struct kvm_vcpu *vcpu, u64 off)
{
u64 off = core_reg_offset_from_id(reg->id);
int size;

switch (off) {
Expand Down Expand Up @@ -103,8 +101,7 @@ static int validate_core_offset(const struct kvm_vcpu *vcpu,
return -EINVAL;
}

if (KVM_REG_SIZE(reg->id) != size ||
!IS_ALIGNED(off, size / sizeof(__u32)))
if (!IS_ALIGNED(off, size / sizeof(__u32)))
return -EINVAL;

/*
Expand All @@ -115,6 +112,21 @@ static int validate_core_offset(const struct kvm_vcpu *vcpu,
if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(off))
return -EINVAL;

return size;
}

static int validate_core_offset(const struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg)
{
u64 off = core_reg_offset_from_id(reg->id);
int size = core_reg_size_from_offset(vcpu, off);

if (size < 0)
return -EINVAL;

if (KVM_REG_SIZE(reg->id) != size)
return -EINVAL;

return 0;
}

Expand Down Expand Up @@ -207,13 +219,7 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)

#define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64)
#define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64)

static bool vq_present(
const u64 (*const vqs)[KVM_ARM64_SVE_VLS_WORDS],
unsigned int vq)
{
return (*vqs)[vq_word(vq)] & vq_mask(vq);
}
#define vq_present(vqs, vq) ((vqs)[vq_word(vq)] & vq_mask(vq))

static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
{
Expand Down Expand Up @@ -258,7 +264,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)

max_vq = 0;
for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
if (vq_present(&vqs, vq))
if (vq_present(vqs, vq))
max_vq = vq;

if (max_vq > sve_vq_from_vl(kvm_sve_max_vl))
Expand All @@ -272,7 +278,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
* maximum:
*/
for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
if (vq_present(&vqs, vq) != sve_vq_available(vq))
if (vq_present(vqs, vq) != sve_vq_available(vq))
return -EINVAL;

/* Can't run with no vector lengths at all: */
Expand Down Expand Up @@ -453,19 +459,34 @@ static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
{
unsigned int i;
int n = 0;
const u64 core_reg = KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE;

for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) {
/*
* The KVM_REG_ARM64_SVE regs must be used instead of
* KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
* SVE-enabled vcpus:
*/
if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(i))
u64 reg = KVM_REG_ARM64 | KVM_REG_ARM_CORE | i;
int size = core_reg_size_from_offset(vcpu, i);

if (size < 0)
continue;

switch (size) {
case sizeof(__u32):
reg |= KVM_REG_SIZE_U32;
break;

case sizeof(__u64):
reg |= KVM_REG_SIZE_U64;
break;

case sizeof(__uint128_t):
reg |= KVM_REG_SIZE_U128;
break;

default:
WARN_ON(1);
continue;
}

if (uindices) {
if (put_user(core_reg | i, uindices))
if (put_user(reg, uindices))
return -EFAULT;
uindices++;
}
Expand Down
5 changes: 3 additions & 2 deletions virt/kvm/arm/arch_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,15 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
}
}

/* Only called for a fully emulated timer */
static void timer_emulate(struct arch_timer_context *ctx)
{
bool should_fire = kvm_timer_should_fire(ctx);

trace_kvm_timer_emulate(ctx, should_fire);

if (should_fire) {
kvm_timer_update_irq(ctx->vcpu, true, ctx);
if (should_fire != ctx->irq.level) {
kvm_timer_update_irq(ctx->vcpu, should_fire, ctx);
return;
}

Expand Down
1 change: 1 addition & 0 deletions virt/kvm/arm/vgic/vgic-its.c
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,7 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)

mutex_unlock(&its->its_lock);
kfree(its);
kfree(kvm_dev);/* alloc by kvm_ioctl_create_device, free by .destroy */
}

static int vgic_its_has_attr_regs(struct kvm_device *dev,
Expand Down

0 comments on commit b21e31b

Please sign in to comment.