Skip to content

Commit c6e0917

Browse files
christofferdall-armMarc Zyngier
authored andcommitted
KVM: arm/arm64: vgic: Permit uaccess writes to return errors
Currently we do not allow any vgic mmio write operations to fail, which makes sense from mmio traps from the guest. However, we should be able to report failures to userspace, if userspace writes incompatible values to read-only registers. Rework the internal interface to allow errors to be returned on the write side for userspace writes. Reviewed-by: Andrew Jones <[email protected]> Signed-off-by: Christoffer Dall <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent 8732209 commit c6e0917

File tree

3 files changed

+31
-18
lines changed

3 files changed

+31
-18
lines changed

virt/kvm/arm/vgic/vgic-mmio-v3.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,9 @@ static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
249249
return value;
250250
}
251251

252-
static void vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
253-
gpa_t addr, unsigned int len,
254-
unsigned long val)
252+
static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
253+
gpa_t addr, unsigned int len,
254+
unsigned long val)
255255
{
256256
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
257257
int i;
@@ -276,6 +276,8 @@ static void vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
276276

277277
vgic_put_irq(vcpu->kvm, irq);
278278
}
279+
280+
return 0;
279281
}
280282

281283
/* We want to avoid outer shareable. */
@@ -468,7 +470,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
468470
VGIC_ACCESS_32bit),
469471
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
470472
vgic_mmio_read_pending, vgic_mmio_write_cpending,
471-
vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
473+
vgic_mmio_read_raz, vgic_mmio_uaccess_write_wi, 1,
472474
VGIC_ACCESS_32bit),
473475
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
474476
vgic_mmio_read_active, vgic_mmio_write_sactive,
@@ -541,7 +543,7 @@ static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
541543
VGIC_ACCESS_32bit),
542544
REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ICPENDR0,
543545
vgic_mmio_read_pending, vgic_mmio_write_cpending,
544-
vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
546+
vgic_mmio_read_raz, vgic_mmio_uaccess_write_wi, 4,
545547
VGIC_ACCESS_32bit),
546548
REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ISACTIVER0,
547549
vgic_mmio_read_active, vgic_mmio_write_sactive,

virt/kvm/arm/vgic/vgic-mmio.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
4040
/* Ignore */
4141
}
4242

43+
int vgic_mmio_uaccess_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
44+
unsigned int len, unsigned long val)
45+
{
46+
/* Ignore */
47+
return 0;
48+
}
49+
4350
/*
4451
* Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
4552
* of the enabled bit, so there is only one function for both here.
@@ -363,11 +370,12 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
363370
mutex_unlock(&vcpu->kvm->lock);
364371
}
365372

366-
void vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
373+
int vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
367374
gpa_t addr, unsigned int len,
368375
unsigned long val)
369376
{
370377
__vgic_mmio_write_cactive(vcpu, addr, len, val);
378+
return 0;
371379
}
372380

373381
static void __vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
@@ -399,11 +407,12 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
399407
mutex_unlock(&vcpu->kvm->lock);
400408
}
401409

402-
void vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
410+
int vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
403411
gpa_t addr, unsigned int len,
404412
unsigned long val)
405413
{
406414
__vgic_mmio_write_sactive(vcpu, addr, len, val);
415+
return 0;
407416
}
408417

409418
unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
@@ -735,10 +744,9 @@ static int vgic_uaccess_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
735744

736745
r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
737746
if (region->uaccess_write)
738-
region->uaccess_write(r_vcpu, addr, sizeof(u32), *val);
739-
else
740-
region->write(r_vcpu, addr, sizeof(u32), *val);
747+
return region->uaccess_write(r_vcpu, addr, sizeof(u32), *val);
741748

749+
region->write(r_vcpu, addr, sizeof(u32), *val);
742750
return 0;
743751
}
744752

virt/kvm/arm/vgic/vgic-mmio.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ struct vgic_register_region {
3737
unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
3838
unsigned int len);
3939
union {
40-
void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
41-
unsigned int len, unsigned long val);
40+
int (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
41+
unsigned int len, unsigned long val);
4242
int (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
4343
gpa_t addr, unsigned int len,
4444
unsigned long val);
@@ -134,6 +134,9 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
134134
void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
135135
unsigned int len, unsigned long val);
136136

137+
int vgic_mmio_uaccess_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
138+
unsigned int len, unsigned long val);
139+
137140
unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
138141
gpa_t addr, unsigned int len);
139142

@@ -167,13 +170,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
167170
gpa_t addr, unsigned int len,
168171
unsigned long val);
169172

170-
void vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
171-
gpa_t addr, unsigned int len,
172-
unsigned long val);
173+
int vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
174+
gpa_t addr, unsigned int len,
175+
unsigned long val);
173176

174-
void vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
175-
gpa_t addr, unsigned int len,
176-
unsigned long val);
177+
int vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
178+
gpa_t addr, unsigned int len,
179+
unsigned long val);
177180

178181
unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
179182
gpa_t addr, unsigned int len);

0 commit comments

Comments
 (0)