diff options
| -rw-r--r-- | arch/arm64/kvm/guest.c | 65 | ||||
| -rw-r--r-- | virt/kvm/arm/arch_timer.c | 5 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-its.c | 1 |
3 files changed, 47 insertions, 24 deletions
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 3ae2f82fca46..c8aa00179363 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c | |||
| @@ -70,10 +70,8 @@ static u64 core_reg_offset_from_id(u64 id) | |||
| 70 | return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE); | 70 | return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static int validate_core_offset(const struct kvm_vcpu *vcpu, | 73 | static int core_reg_size_from_offset(const struct kvm_vcpu *vcpu, u64 off) |
| 74 | const struct kvm_one_reg *reg) | ||
| 75 | { | 74 | { |
| 76 | u64 off = core_reg_offset_from_id(reg->id); | ||
| 77 | int size; | 75 | int size; |
| 78 | 76 | ||
| 79 | switch (off) { | 77 | switch (off) { |
| @@ -103,8 +101,7 @@ static int validate_core_offset(const struct kvm_vcpu *vcpu, | |||
| 103 | return -EINVAL; | 101 | return -EINVAL; |
| 104 | } | 102 | } |
| 105 | 103 | ||
| 106 | if (KVM_REG_SIZE(reg->id) != size || | 104 | if (!IS_ALIGNED(off, size / sizeof(__u32))) |
| 107 | !IS_ALIGNED(off, size / sizeof(__u32))) | ||
| 108 | return -EINVAL; | 105 | return -EINVAL; |
| 109 | 106 | ||
| 110 | /* | 107 | /* |
| @@ -115,6 +112,21 @@ static int validate_core_offset(const struct kvm_vcpu *vcpu, | |||
| 115 | if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(off)) | 112 | if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(off)) |
| 116 | return -EINVAL; | 113 | return -EINVAL; |
| 117 | 114 | ||
| 115 | return size; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int validate_core_offset(const struct kvm_vcpu *vcpu, | ||
| 119 | const struct kvm_one_reg *reg) | ||
| 120 | { | ||
| 121 | u64 off = core_reg_offset_from_id(reg->id); | ||
| 122 | int size = core_reg_size_from_offset(vcpu, off); | ||
| 123 | |||
| 124 | if (size < 0) | ||
| 125 | return -EINVAL; | ||
| 126 | |||
| 127 | if (KVM_REG_SIZE(reg->id) != size) | ||
| 128 | return -EINVAL; | ||
| 129 | |||
| 118 | return 0; | 130 | return 0; |
| 119 | } | 131 | } |
| 120 | 132 | ||
| @@ -207,13 +219,7 @@ out: | |||
| 207 | 219 | ||
| 208 | #define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64) | 220 | #define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64) |
| 209 | #define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64) | 221 | #define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64) |
| 210 | 222 | #define vq_present(vqs, vq) ((vqs)[vq_word(vq)] & vq_mask(vq)) | |
| 211 | static bool vq_present( | ||
| 212 | const u64 (*const vqs)[KVM_ARM64_SVE_VLS_WORDS], | ||
| 213 | unsigned int vq) | ||
| 214 | { | ||
| 215 | return (*vqs)[vq_word(vq)] & vq_mask(vq); | ||
| 216 | } | ||
| 217 | 223 | ||
| 218 | static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) | 224 | static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) |
| 219 | { | 225 | { |
| @@ -258,7 +264,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) | |||
| 258 | 264 | ||
| 259 | max_vq = 0; | 265 | max_vq = 0; |
| 260 | for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq) | 266 | for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq) |
| 261 | if (vq_present(&vqs, vq)) | 267 | if (vq_present(vqs, vq)) |
| 262 | max_vq = vq; | 268 | max_vq = vq; |
| 263 | 269 | ||
| 264 | if (max_vq > sve_vq_from_vl(kvm_sve_max_vl)) | 270 | if (max_vq > sve_vq_from_vl(kvm_sve_max_vl)) |
| @@ -272,7 +278,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) | |||
| 272 | * maximum: | 278 | * maximum: |
| 273 | */ | 279 | */ |
| 274 | for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq) | 280 | for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq) |
| 275 | if (vq_present(&vqs, vq) != sve_vq_available(vq)) | 281 | if (vq_present(vqs, vq) != sve_vq_available(vq)) |
| 276 | return -EINVAL; | 282 | return -EINVAL; |
| 277 | 283 | ||
| 278 | /* Can't run with no vector lengths at all: */ | 284 | /* Can't run with no vector lengths at all: */ |
| @@ -453,19 +459,34 @@ static int copy_core_reg_indices(const struct kvm_vcpu *vcpu, | |||
| 453 | { | 459 | { |
| 454 | unsigned int i; | 460 | unsigned int i; |
| 455 | int n = 0; | 461 | int n = 0; |
| 456 | const u64 core_reg = KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE; | ||
| 457 | 462 | ||
| 458 | for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) { | 463 | for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) { |
| 459 | /* | 464 | u64 reg = KVM_REG_ARM64 | KVM_REG_ARM_CORE | i; |
| 460 | * The KVM_REG_ARM64_SVE regs must be used instead of | 465 | int size = core_reg_size_from_offset(vcpu, i); |
| 461 | * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on | 466 | |
| 462 | * SVE-enabled vcpus: | 467 | if (size < 0) |
| 463 | */ | 468 | continue; |
| 464 | if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(i)) | 469 | |
| 470 | switch (size) { | ||
| 471 | case sizeof(__u32): | ||
| 472 | reg |= KVM_REG_SIZE_U32; | ||
| 473 | break; | ||
| 474 | |||
| 475 | case sizeof(__u64): | ||
| 476 | reg |= KVM_REG_SIZE_U64; | ||
| 477 | break; | ||
| 478 | |||
| 479 | case sizeof(__uint128_t): | ||
| 480 | reg |= KVM_REG_SIZE_U128; | ||
| 481 | break; | ||
| 482 | |||
| 483 | default: | ||
| 484 | WARN_ON(1); | ||
| 465 | continue; | 485 | continue; |
| 486 | } | ||
| 466 | 487 | ||
| 467 | if (uindices) { | 488 | if (uindices) { |
| 468 | if (put_user(core_reg | i, uindices)) | 489 | if (put_user(reg, uindices)) |
| 469 | return -EFAULT; | 490 | return -EFAULT; |
| 470 | uindices++; | 491 | uindices++; |
| 471 | } | 492 | } |
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 7fc272ecae16..1b1c449ceaf4 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
| @@ -321,14 +321,15 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, | |||
| 321 | } | 321 | } |
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | /* Only called for a fully emulated timer */ | ||
| 324 | static void timer_emulate(struct arch_timer_context *ctx) | 325 | static void timer_emulate(struct arch_timer_context *ctx) |
| 325 | { | 326 | { |
| 326 | bool should_fire = kvm_timer_should_fire(ctx); | 327 | bool should_fire = kvm_timer_should_fire(ctx); |
| 327 | 328 | ||
| 328 | trace_kvm_timer_emulate(ctx, should_fire); | 329 | trace_kvm_timer_emulate(ctx, should_fire); |
| 329 | 330 | ||
| 330 | if (should_fire) { | 331 | if (should_fire != ctx->irq.level) { |
| 331 | kvm_timer_update_irq(ctx->vcpu, true, ctx); | 332 | kvm_timer_update_irq(ctx->vcpu, should_fire, ctx); |
| 332 | return; | 333 | return; |
| 333 | } | 334 | } |
| 334 | 335 | ||
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 44ceaccb18cf..8c9fe831bce4 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c | |||
| @@ -1734,6 +1734,7 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev) | |||
| 1734 | 1734 | ||
| 1735 | mutex_unlock(&its->its_lock); | 1735 | mutex_unlock(&its->its_lock); |
| 1736 | kfree(its); | 1736 | kfree(its); |
| 1737 | kfree(kvm_dev);/* alloc by kvm_ioctl_create_device, free by .destroy */ | ||
| 1737 | } | 1738 | } |
| 1738 | 1739 | ||
| 1739 | static int vgic_its_has_attr_regs(struct kvm_device *dev, | 1740 | static int vgic_its_has_attr_regs(struct kvm_device *dev, |
