@@ -76,8 +76,7 @@ int kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev
76
76
/**
77
77
* kvm_vgic_addr - set or get vgic VM base addresses
78
78
* @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
81
80
* @write: if true set the address in the VM address space, if false read the
82
81
* address
83
82
*
@@ -89,15 +88,22 @@ int kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev
89
88
* overlapping regions in case of a virtual GICv3 here, since we don't know
90
89
* the number of VCPUs yet, so we defer this check to map_resources().
91
90
*/
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 )
93
92
{
94
- int r = 0 ;
93
+ u64 __user * uaddr = ( u64 __user * ) attr -> addr ;
95
94
struct vgic_dist * vgic = & kvm -> arch .vgic ;
96
95
phys_addr_t * addr_ptr , alignment , size ;
97
96
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 ;
98
104
99
105
mutex_lock (& kvm -> lock );
100
- switch (type ) {
106
+ switch (attr -> attr ) {
101
107
case KVM_VGIC_V2_ADDR_TYPE_DIST :
102
108
r = vgic_check_type (kvm , KVM_DEV_TYPE_ARM_VGIC_V2 );
103
109
addr_ptr = & vgic -> vgic_dist_base ;
@@ -123,7 +129,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
123
129
if (r )
124
130
break ;
125
131
if (write ) {
126
- r = vgic_v3_set_redist_base (kvm , 0 , * addr , 0 );
132
+ r = vgic_v3_set_redist_base (kvm , 0 , addr , 0 );
127
133
goto out ;
128
134
}
129
135
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)
143
149
if (r )
144
150
break ;
145
151
146
- index = * addr & KVM_VGIC_V3_RDIST_INDEX_MASK ;
152
+ index = addr & KVM_VGIC_V3_RDIST_INDEX_MASK ;
147
153
148
154
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 );
154
158
155
159
if (!count || flags )
156
160
r = - EINVAL ;
@@ -166,9 +170,9 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
166
170
goto out ;
167
171
}
168
172
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 ;
172
176
goto out ;
173
177
}
174
178
default :
@@ -179,15 +183,19 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
179
183
goto out ;
180
184
181
185
if (write ) {
182
- r = vgic_check_iorange (kvm , * addr_ptr , * addr , alignment , size );
186
+ r = vgic_check_iorange (kvm , * addr_ptr , addr , alignment , size );
183
187
if (!r )
184
- * addr_ptr = * addr ;
188
+ * addr_ptr = addr ;
185
189
} else {
186
- * addr = * addr_ptr ;
190
+ addr = * addr_ptr ;
187
191
}
188
192
189
193
out :
190
194
mutex_unlock (& kvm -> lock );
195
+
196
+ if (!r && !write )
197
+ r = put_user (addr , uaddr );
198
+
191
199
return r ;
192
200
}
193
201
@@ -197,17 +205,9 @@ static int vgic_set_common_attr(struct kvm_device *dev,
197
205
int r ;
198
206
199
207
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);
209
210
return (r == - ENODEV ) ? - ENXIO : r ;
210
- }
211
211
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS : {
212
212
u32 __user * uaddr = (u32 __user * )(long )attr -> addr ;
213
213
u32 val ;
@@ -260,22 +260,9 @@ static int vgic_get_common_attr(struct kvm_device *dev,
260
260
int r = - ENXIO ;
261
261
262
262
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 ;
279
266
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS : {
280
267
u32 __user * uaddr = (u32 __user * )(long )attr -> addr ;
281
268
0 commit comments