Skip to content

Commit 26f3149

Browse files
committed
Merge tag 'kvmarm-fixes-6.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 fixes for 6.4, take #2 - Address some fallout of the locking rework, this time affecting the way the vgic is configured - Fix an issue where the page table walker frees a subtree and then proceeds with walking what it has just freed... - Check that a given PA donated to the gues is actually memory (only affecting pKVM) - Correctly handle MTE CMOs by Set/Way
2 parents b9846a6 + a9f0e3d commit 26f3149

File tree

13 files changed

+112
-54
lines changed

13 files changed

+112
-54
lines changed

arch/arm64/include/asm/kvm_pgtable.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -632,9 +632,9 @@ int kvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size);
632632
*
633633
* The walker will walk the page-table entries corresponding to the input
634634
* address range specified, visiting entries according to the walker flags.
635-
* Invalid entries are treated as leaf entries. Leaf entries are reloaded
636-
* after invoking the walker callback, allowing the walker to descend into
637-
* a newly installed table.
635+
* Invalid entries are treated as leaf entries. The visited page table entry is
636+
* reloaded after invoking the walker callback, allowing the walker to descend
637+
* into a newly installed table.
638638
*
639639
* Returning a negative error code from the walker callback function will
640640
* terminate the walk immediately with the same error code.

arch/arm64/include/asm/sysreg.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,14 @@
115115
#define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31)
116116

117117
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
118+
#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
119+
#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6)
118120
#define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2)
121+
#define SYS_DC_CGSW sys_insn(1, 0, 7, 10, 4)
122+
#define SYS_DC_CGDSW sys_insn(1, 0, 7, 10, 6)
119123
#define SYS_DC_CISW sys_insn(1, 0, 7, 14, 2)
124+
#define SYS_DC_CIGSW sys_insn(1, 0, 7, 14, 4)
125+
#define SYS_DC_CIGDSW sys_insn(1, 0, 7, 14, 6)
120126

121127
/*
122128
* Automatically generated definitions for system registers, the

arch/arm64/kvm/hyp/nvhe/mem_protect.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -575,18 +575,15 @@ struct pkvm_mem_donation {
575575

576576
struct check_walk_data {
577577
enum pkvm_page_state desired;
578-
enum pkvm_page_state (*get_page_state)(kvm_pte_t pte);
578+
enum pkvm_page_state (*get_page_state)(kvm_pte_t pte, u64 addr);
579579
};
580580

581581
static int __check_page_state_visitor(const struct kvm_pgtable_visit_ctx *ctx,
582582
enum kvm_pgtable_walk_flags visit)
583583
{
584584
struct check_walk_data *d = ctx->arg;
585585

586-
if (kvm_pte_valid(ctx->old) && !addr_is_allowed_memory(kvm_pte_to_phys(ctx->old)))
587-
return -EINVAL;
588-
589-
return d->get_page_state(ctx->old) == d->desired ? 0 : -EPERM;
586+
return d->get_page_state(ctx->old, ctx->addr) == d->desired ? 0 : -EPERM;
590587
}
591588

592589
static int check_page_state_range(struct kvm_pgtable *pgt, u64 addr, u64 size,
@@ -601,8 +598,11 @@ static int check_page_state_range(struct kvm_pgtable *pgt, u64 addr, u64 size,
601598
return kvm_pgtable_walk(pgt, addr, size, &walker);
602599
}
603600

604-
static enum pkvm_page_state host_get_page_state(kvm_pte_t pte)
601+
static enum pkvm_page_state host_get_page_state(kvm_pte_t pte, u64 addr)
605602
{
603+
if (!addr_is_allowed_memory(addr))
604+
return PKVM_NOPAGE;
605+
606606
if (!kvm_pte_valid(pte) && pte)
607607
return PKVM_NOPAGE;
608608

@@ -709,7 +709,7 @@ static int host_complete_donation(u64 addr, const struct pkvm_mem_transition *tx
709709
return host_stage2_set_owner_locked(addr, size, host_id);
710710
}
711711

712-
static enum pkvm_page_state hyp_get_page_state(kvm_pte_t pte)
712+
static enum pkvm_page_state hyp_get_page_state(kvm_pte_t pte, u64 addr)
713713
{
714714
if (!kvm_pte_valid(pte))
715715
return PKVM_NOPAGE;

arch/arm64/kvm/hyp/pgtable.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,26 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data,
209209
.flags = flags,
210210
};
211211
int ret = 0;
212+
bool reload = false;
212213
kvm_pteref_t childp;
213214
bool table = kvm_pte_table(ctx.old, level);
214215

215-
if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE))
216+
if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE)) {
216217
ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_TABLE_PRE);
218+
reload = true;
219+
}
217220

218221
if (!table && (ctx.flags & KVM_PGTABLE_WALK_LEAF)) {
219222
ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_LEAF);
223+
reload = true;
224+
}
225+
226+
/*
227+
* Reload the page table after invoking the walker callback for leaf
228+
* entries or after pre-order traversal, to allow the walker to descend
229+
* into a newly installed or replaced table.
230+
*/
231+
if (reload) {
220232
ctx.old = READ_ONCE(*ptep);
221233
table = kvm_pte_table(ctx.old, level);
222234
}

arch/arm64/kvm/sys_regs.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,19 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
211211
return true;
212212
}
213213

214+
static bool access_dcgsw(struct kvm_vcpu *vcpu,
215+
struct sys_reg_params *p,
216+
const struct sys_reg_desc *r)
217+
{
218+
if (!kvm_has_mte(vcpu->kvm)) {
219+
kvm_inject_undefined(vcpu);
220+
return false;
221+
}
222+
223+
/* Treat MTE S/W ops as we treat the classic ones: with contempt */
224+
return access_dcsw(vcpu, p, r);
225+
}
226+
214227
static void get_access_mask(const struct sys_reg_desc *r, u64 *mask, u64 *shift)
215228
{
216229
switch (r->aarch32_map) {
@@ -1756,8 +1769,14 @@ static bool access_spsr(struct kvm_vcpu *vcpu,
17561769
*/
17571770
static const struct sys_reg_desc sys_reg_descs[] = {
17581771
{ SYS_DESC(SYS_DC_ISW), access_dcsw },
1772+
{ SYS_DESC(SYS_DC_IGSW), access_dcgsw },
1773+
{ SYS_DESC(SYS_DC_IGDSW), access_dcgsw },
17591774
{ SYS_DESC(SYS_DC_CSW), access_dcsw },
1775+
{ SYS_DESC(SYS_DC_CGSW), access_dcgsw },
1776+
{ SYS_DESC(SYS_DC_CGDSW), access_dcgsw },
17601777
{ SYS_DESC(SYS_DC_CISW), access_dcsw },
1778+
{ SYS_DESC(SYS_DC_CIGSW), access_dcgsw },
1779+
{ SYS_DESC(SYS_DC_CIGDSW), access_dcgsw },
17611780

17621781
DBG_BCR_BVR_WCR_WVR_EL1(0),
17631782
DBG_BCR_BVR_WCR_WVR_EL1(1),

arch/arm64/kvm/vgic/vgic-init.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,9 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
235235
* KVM io device for the redistributor that belongs to this VCPU.
236236
*/
237237
if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
238-
mutex_lock(&vcpu->kvm->arch.config_lock);
238+
mutex_lock(&vcpu->kvm->slots_lock);
239239
ret = vgic_register_redist_iodev(vcpu);
240-
mutex_unlock(&vcpu->kvm->arch.config_lock);
240+
mutex_unlock(&vcpu->kvm->slots_lock);
241241
}
242242
return ret;
243243
}
@@ -406,7 +406,7 @@ void kvm_vgic_destroy(struct kvm *kvm)
406406

407407
/**
408408
* vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
409-
* is a GICv2. A GICv3 must be explicitly initialized by the guest using the
409+
* is a GICv2. A GICv3 must be explicitly initialized by userspace using the
410410
* KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group.
411411
* @kvm: kvm struct pointer
412412
*/
@@ -446,11 +446,13 @@ int vgic_lazy_init(struct kvm *kvm)
446446
int kvm_vgic_map_resources(struct kvm *kvm)
447447
{
448448
struct vgic_dist *dist = &kvm->arch.vgic;
449+
gpa_t dist_base;
449450
int ret = 0;
450451

451452
if (likely(vgic_ready(kvm)))
452453
return 0;
453454

455+
mutex_lock(&kvm->slots_lock);
454456
mutex_lock(&kvm->arch.config_lock);
455457
if (vgic_ready(kvm))
456458
goto out;
@@ -463,13 +465,26 @@ int kvm_vgic_map_resources(struct kvm *kvm)
463465
else
464466
ret = vgic_v3_map_resources(kvm);
465467

466-
if (ret)
468+
if (ret) {
467469
__kvm_vgic_destroy(kvm);
468-
else
469-
dist->ready = true;
470+
goto out;
471+
}
472+
dist->ready = true;
473+
dist_base = dist->vgic_dist_base;
474+
mutex_unlock(&kvm->arch.config_lock);
475+
476+
ret = vgic_register_dist_iodev(kvm, dist_base,
477+
kvm_vgic_global_state.type);
478+
if (ret) {
479+
kvm_err("Unable to register VGIC dist MMIO regions\n");
480+
kvm_vgic_destroy(kvm);
481+
}
482+
mutex_unlock(&kvm->slots_lock);
483+
return ret;
470484

471485
out:
472486
mutex_unlock(&kvm->arch.config_lock);
487+
mutex_unlock(&kvm->slots_lock);
473488
return ret;
474489
}
475490

arch/arm64/kvm/vgic/vgic-its.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,6 +1936,7 @@ void vgic_lpi_translation_cache_destroy(struct kvm *kvm)
19361936

19371937
static int vgic_its_create(struct kvm_device *dev, u32 type)
19381938
{
1939+
int ret;
19391940
struct vgic_its *its;
19401941

19411942
if (type != KVM_DEV_TYPE_ARM_VGIC_ITS)
@@ -1945,9 +1946,12 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
19451946
if (!its)
19461947
return -ENOMEM;
19471948

1949+
mutex_lock(&dev->kvm->arch.config_lock);
1950+
19481951
if (vgic_initialized(dev->kvm)) {
1949-
int ret = vgic_v4_init(dev->kvm);
1952+
ret = vgic_v4_init(dev->kvm);
19501953
if (ret < 0) {
1954+
mutex_unlock(&dev->kvm->arch.config_lock);
19511955
kfree(its);
19521956
return ret;
19531957
}
@@ -1960,12 +1964,10 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
19601964

19611965
/* Yep, even more trickery for lock ordering... */
19621966
#ifdef CONFIG_LOCKDEP
1963-
mutex_lock(&dev->kvm->arch.config_lock);
19641967
mutex_lock(&its->cmd_lock);
19651968
mutex_lock(&its->its_lock);
19661969
mutex_unlock(&its->its_lock);
19671970
mutex_unlock(&its->cmd_lock);
1968-
mutex_unlock(&dev->kvm->arch.config_lock);
19691971
#endif
19701972

19711973
its->vgic_its_base = VGIC_ADDR_UNDEF;
@@ -1986,7 +1988,11 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
19861988

19871989
dev->private = its;
19881990

1989-
return vgic_its_set_abi(its, NR_ITS_ABIS - 1);
1991+
ret = vgic_its_set_abi(its, NR_ITS_ABIS - 1);
1992+
1993+
mutex_unlock(&dev->kvm->arch.config_lock);
1994+
1995+
return ret;
19901996
}
19911997

19921998
static void vgic_its_destroy(struct kvm_device *kvm_dev)

arch/arm64/kvm/vgic/vgic-kvm-device.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri
102102
if (get_user(addr, uaddr))
103103
return -EFAULT;
104104

105-
mutex_lock(&kvm->arch.config_lock);
105+
/*
106+
* Since we can't hold config_lock while registering the redistributor
107+
* iodevs, take the slots_lock immediately.
108+
*/
109+
mutex_lock(&kvm->slots_lock);
106110
switch (attr->attr) {
107111
case KVM_VGIC_V2_ADDR_TYPE_DIST:
108112
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
@@ -182,16 +186,18 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri
182186
if (r)
183187
goto out;
184188

189+
mutex_lock(&kvm->arch.config_lock);
185190
if (write) {
186191
r = vgic_check_iorange(kvm, *addr_ptr, addr, alignment, size);
187192
if (!r)
188193
*addr_ptr = addr;
189194
} else {
190195
addr = *addr_ptr;
191196
}
197+
mutex_unlock(&kvm->arch.config_lock);
192198

193199
out:
194-
mutex_unlock(&kvm->arch.config_lock);
200+
mutex_unlock(&kvm->slots_lock);
195201

196202
if (!r && !write)
197203
r = put_user(addr, uaddr);

arch/arm64/kvm/vgic/vgic-mmio-v3.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -769,10 +769,13 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
769769
struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;
770770
struct vgic_redist_region *rdreg;
771771
gpa_t rd_base;
772-
int ret;
772+
int ret = 0;
773+
774+
lockdep_assert_held(&kvm->slots_lock);
775+
mutex_lock(&kvm->arch.config_lock);
773776

774777
if (!IS_VGIC_ADDR_UNDEF(vgic_cpu->rd_iodev.base_addr))
775-
return 0;
778+
goto out_unlock;
776779

777780
/*
778781
* We may be creating VCPUs before having set the base address for the
@@ -782,10 +785,12 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
782785
*/
783786
rdreg = vgic_v3_rdist_free_slot(&vgic->rd_regions);
784787
if (!rdreg)
785-
return 0;
788+
goto out_unlock;
786789

787-
if (!vgic_v3_check_base(kvm))
788-
return -EINVAL;
790+
if (!vgic_v3_check_base(kvm)) {
791+
ret = -EINVAL;
792+
goto out_unlock;
793+
}
789794

790795
vgic_cpu->rdreg = rdreg;
791796
vgic_cpu->rdreg_index = rdreg->free_index;
@@ -799,16 +804,20 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
799804
rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rd_registers);
800805
rd_dev->redist_vcpu = vcpu;
801806

802-
mutex_lock(&kvm->slots_lock);
807+
mutex_unlock(&kvm->arch.config_lock);
808+
803809
ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
804810
2 * SZ_64K, &rd_dev->dev);
805-
mutex_unlock(&kvm->slots_lock);
806-
807811
if (ret)
808812
return ret;
809813

814+
/* Protected by slots_lock */
810815
rdreg->free_index++;
811816
return 0;
817+
818+
out_unlock:
819+
mutex_unlock(&kvm->arch.config_lock);
820+
return ret;
812821
}
813822

814823
static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
@@ -834,12 +843,10 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm)
834843
/* The current c failed, so iterate over the previous ones. */
835844
int i;
836845

837-
mutex_lock(&kvm->slots_lock);
838846
for (i = 0; i < c; i++) {
839847
vcpu = kvm_get_vcpu(kvm, i);
840848
vgic_unregister_redist_iodev(vcpu);
841849
}
842-
mutex_unlock(&kvm->slots_lock);
843850
}
844851

845852
return ret;
@@ -938,7 +945,9 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count)
938945
{
939946
int ret;
940947

948+
mutex_lock(&kvm->arch.config_lock);
941949
ret = vgic_v3_alloc_redist_region(kvm, index, addr, count);
950+
mutex_unlock(&kvm->arch.config_lock);
942951
if (ret)
943952
return ret;
944953

@@ -950,8 +959,10 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count)
950959
if (ret) {
951960
struct vgic_redist_region *rdreg;
952961

962+
mutex_lock(&kvm->arch.config_lock);
953963
rdreg = vgic_v3_rdist_region_from_index(kvm, index);
954964
vgic_v3_free_redist_region(rdreg);
965+
mutex_unlock(&kvm->arch.config_lock);
955966
return ret;
956967
}
957968

arch/arm64/kvm/vgic/vgic-mmio.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,6 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
10961096
enum vgic_type type)
10971097
{
10981098
struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev;
1099-
int ret = 0;
11001099
unsigned int len;
11011100

11021101
switch (type) {
@@ -1114,10 +1113,6 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
11141113
io_device->iodev_type = IODEV_DIST;
11151114
io_device->redist_vcpu = NULL;
11161115

1117-
mutex_lock(&kvm->slots_lock);
1118-
ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
1119-
len, &io_device->dev);
1120-
mutex_unlock(&kvm->slots_lock);
1121-
1122-
return ret;
1116+
return kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
1117+
len, &io_device->dev);
11231118
}

0 commit comments

Comments
 (0)