Skip to content

Commit 4b85080

Browse files
author
Marc Zyngier
committed
KVM: arm64: vgic: Consolidate userspace access for base address setting
Align kvm_vgic_addr() with the rest of the code by moving the userspace accesses into it. kvm_vgic_addr() is also made static. Signed-off-by: Marc Zyngier <[email protected]>
1 parent 9f968c9 commit 4b85080

File tree

2 files changed

+31
-45
lines changed

2 files changed

+31
-45
lines changed

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

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ int kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev
7676
/**
7777
* kvm_vgic_addr - set or get vgic VM base addresses
7878
* @kvm: pointer to the vm struct
79-
* @type: the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
80-
* @addr: pointer to address value
79+
* @attr: pointer to the attribute being retrieved/updated
8180
* @write: if true set the address in the VM address space, if false read the
8281
* address
8382
*
@@ -89,15 +88,22 @@ int kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev
8988
* overlapping regions in case of a virtual GICv3 here, since we don't know
9089
* the number of VCPUs yet, so we defer this check to map_resources().
9190
*/
92-
int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
91+
static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool write)
9392
{
94-
int r = 0;
93+
u64 __user *uaddr = (u64 __user *)attr->addr;
9594
struct vgic_dist *vgic = &kvm->arch.vgic;
9695
phys_addr_t *addr_ptr, alignment, size;
9796
u64 undef_value = VGIC_ADDR_UNDEF;
97+
u64 addr;
98+
int r;
99+
100+
/* Reading a redistributor region addr implies getting the index */
101+
if (write || attr->attr == KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION)
102+
if (get_user(addr, uaddr))
103+
return -EFAULT;
98104

99105
mutex_lock(&kvm->lock);
100-
switch (type) {
106+
switch (attr->attr) {
101107
case KVM_VGIC_V2_ADDR_TYPE_DIST:
102108
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
103109
addr_ptr = &vgic->vgic_dist_base;
@@ -123,7 +129,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
123129
if (r)
124130
break;
125131
if (write) {
126-
r = vgic_v3_set_redist_base(kvm, 0, *addr, 0);
132+
r = vgic_v3_set_redist_base(kvm, 0, addr, 0);
127133
goto out;
128134
}
129135
rdreg = list_first_entry_or_null(&vgic->rd_regions,
@@ -143,14 +149,12 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
143149
if (r)
144150
break;
145151

146-
index = *addr & KVM_VGIC_V3_RDIST_INDEX_MASK;
152+
index = addr & KVM_VGIC_V3_RDIST_INDEX_MASK;
147153

148154
if (write) {
149-
gpa_t base = *addr & KVM_VGIC_V3_RDIST_BASE_MASK;
150-
u32 count = (*addr & KVM_VGIC_V3_RDIST_COUNT_MASK)
151-
>> KVM_VGIC_V3_RDIST_COUNT_SHIFT;
152-
u8 flags = (*addr & KVM_VGIC_V3_RDIST_FLAGS_MASK)
153-
>> KVM_VGIC_V3_RDIST_FLAGS_SHIFT;
155+
gpa_t base = addr & KVM_VGIC_V3_RDIST_BASE_MASK;
156+
u32 count = FIELD_GET(KVM_VGIC_V3_RDIST_COUNT_MASK, addr);
157+
u8 flags = FIELD_GET(KVM_VGIC_V3_RDIST_FLAGS_MASK, addr);
154158

155159
if (!count || flags)
156160
r = -EINVAL;
@@ -166,9 +170,9 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
166170
goto out;
167171
}
168172

169-
*addr = index;
170-
*addr |= rdreg->base;
171-
*addr |= (u64)rdreg->count << KVM_VGIC_V3_RDIST_COUNT_SHIFT;
173+
addr = index;
174+
addr |= rdreg->base;
175+
addr |= (u64)rdreg->count << KVM_VGIC_V3_RDIST_COUNT_SHIFT;
172176
goto out;
173177
}
174178
default:
@@ -179,15 +183,19 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
179183
goto out;
180184

181185
if (write) {
182-
r = vgic_check_iorange(kvm, *addr_ptr, *addr, alignment, size);
186+
r = vgic_check_iorange(kvm, *addr_ptr, addr, alignment, size);
183187
if (!r)
184-
*addr_ptr = *addr;
188+
*addr_ptr = addr;
185189
} else {
186-
*addr = *addr_ptr;
190+
addr = *addr_ptr;
187191
}
188192

189193
out:
190194
mutex_unlock(&kvm->lock);
195+
196+
if (!r && !write)
197+
r = put_user(addr, uaddr);
198+
191199
return r;
192200
}
193201

@@ -197,17 +205,9 @@ static int vgic_set_common_attr(struct kvm_device *dev,
197205
int r;
198206

199207
switch (attr->group) {
200-
case KVM_DEV_ARM_VGIC_GRP_ADDR: {
201-
u64 __user *uaddr = (u64 __user *)(long)attr->addr;
202-
u64 addr;
203-
unsigned long type = (unsigned long)attr->attr;
204-
205-
if (get_user(addr, uaddr))
206-
return -EFAULT;
207-
208-
r = kvm_vgic_addr(dev->kvm, type, &addr, true);
208+
case KVM_DEV_ARM_VGIC_GRP_ADDR:
209+
r = kvm_vgic_addr(dev->kvm, attr, true);
209210
return (r == -ENODEV) ? -ENXIO : r;
210-
}
211211
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
212212
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
213213
u32 val;
@@ -260,22 +260,9 @@ static int vgic_get_common_attr(struct kvm_device *dev,
260260
int r = -ENXIO;
261261

262262
switch (attr->group) {
263-
case KVM_DEV_ARM_VGIC_GRP_ADDR: {
264-
u64 __user *uaddr = (u64 __user *)(long)attr->addr;
265-
u64 addr;
266-
unsigned long type = (unsigned long)attr->attr;
267-
268-
if (get_user(addr, uaddr))
269-
return -EFAULT;
270-
271-
r = kvm_vgic_addr(dev->kvm, type, &addr, false);
272-
if (r)
273-
return (r == -ENODEV) ? -ENXIO : r;
274-
275-
if (put_user(addr, uaddr))
276-
return -EFAULT;
277-
break;
278-
}
263+
case KVM_DEV_ARM_VGIC_GRP_ADDR:
264+
r = kvm_vgic_addr(dev->kvm, attr, false);
265+
return (r == -ENODEV) ? -ENXIO : r;
279266
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
280267
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
281268

include/kvm/arm_vgic.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,6 @@ struct vgic_cpu {
364364
extern struct static_key_false vgic_v2_cpuif_trap;
365365
extern struct static_key_false vgic_v3_cpuif_trap;
366366

367-
int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
368367
int kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev_addr);
369368
void kvm_vgic_early_init(struct kvm *kvm);
370369
int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu);

0 commit comments

Comments
 (0)