@@ -79,74 +79,120 @@ static void vm_gic_destroy(struct vm_gic *v)
79
79
kvm_vm_free (v -> vm );
80
80
}
81
81
82
+ struct vgic_region_attr {
83
+ uint64_t attr ;
84
+ uint64_t size ;
85
+ uint64_t alignment ;
86
+ };
87
+
88
+ struct vgic_region_attr gic_v3_dist_region = {
89
+ .attr = KVM_VGIC_V3_ADDR_TYPE_DIST ,
90
+ .size = 0x10000 ,
91
+ .alignment = 0x10000 ,
92
+ };
93
+
94
+ struct vgic_region_attr gic_v3_redist_region = {
95
+ .attr = KVM_VGIC_V3_ADDR_TYPE_REDIST ,
96
+ .size = NR_VCPUS * 0x20000 ,
97
+ .alignment = 0x10000 ,
98
+ };
99
+
100
+ struct vgic_region_attr gic_v2_dist_region = {
101
+ .attr = KVM_VGIC_V2_ADDR_TYPE_DIST ,
102
+ .size = 0x1000 ,
103
+ .alignment = 0x1000 ,
104
+ };
105
+
106
+ struct vgic_region_attr gic_v2_cpu_region = {
107
+ .attr = KVM_VGIC_V2_ADDR_TYPE_CPU ,
108
+ .size = 0x2000 ,
109
+ .alignment = 0x1000 ,
110
+ };
111
+
82
112
/**
83
- * Helper routine that performs KVM device tests in general and
84
- * especially ARM_VGIC_V3 ones. Eventually the ARM_VGIC_V3
85
- * device gets created, a legacy RDIST region is set at @0x0
86
- * and a DIST region is set @0x60000
113
+ * Helper routine that performs KVM device tests in general. Eventually the
114
+ * ARM_VGIC (GICv2 or GICv3) device gets created with an overlapping
115
+ * DIST/REDIST (or DIST/CPUIF for GICv2). Assumption is 4 vcpus are going to be
116
+ * used hence the overlap. In the case of GICv3, A RDIST region is set at @0x0
117
+ * and a DIST region is set @0x70000. The GICv2 case sets a CPUIF @0x0 and a
118
+ * DIST region @0x1000.
87
119
*/
88
- static void subtest_v3_dist_rdist (struct vm_gic * v )
120
+ static void subtest_dist_rdist (struct vm_gic * v )
89
121
{
90
122
int ret ;
91
123
uint64_t addr ;
124
+ struct vgic_region_attr rdist ; /* CPU interface in GICv2*/
125
+ struct vgic_region_attr dist ;
126
+
127
+ rdist = VGIC_DEV_IS_V3 (v -> gic_dev_type ) ? gic_v3_redist_region
128
+ : gic_v2_cpu_region ;
129
+ dist = VGIC_DEV_IS_V3 (v -> gic_dev_type ) ? gic_v3_dist_region
130
+ : gic_v2_dist_region ;
92
131
93
132
/* Check existing group/attributes */
94
133
kvm_device_check_attr (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
95
- KVM_VGIC_V3_ADDR_TYPE_DIST );
134
+ dist . attr );
96
135
97
136
kvm_device_check_attr (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
98
- KVM_VGIC_V3_ADDR_TYPE_REDIST );
137
+ rdist . attr );
99
138
100
139
/* check non existing attribute */
101
- ret = _kvm_device_check_attr (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR , 0 );
140
+ ret = _kvm_device_check_attr (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR , -1 );
102
141
TEST_ASSERT (ret && errno == ENXIO , "attribute not supported" );
103
142
104
143
/* misaligned DIST and REDIST address settings */
105
- addr = 0x1000 ;
144
+ addr = dist . alignment / 0x10 ;
106
145
ret = _kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
107
- KVM_VGIC_V3_ADDR_TYPE_DIST , & addr , true);
108
- TEST_ASSERT (ret && errno == EINVAL , "GICv3 dist base not 64kB aligned" );
146
+ dist . attr , & addr , true);
147
+ TEST_ASSERT (ret && errno == EINVAL , "GIC dist base not aligned" );
109
148
149
+ addr = rdist .alignment / 0x10 ;
110
150
ret = _kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
111
- KVM_VGIC_V3_ADDR_TYPE_REDIST , & addr , true);
112
- TEST_ASSERT (ret && errno == EINVAL , "GICv3 redist base not 64kB aligned" );
151
+ rdist . attr , & addr , true);
152
+ TEST_ASSERT (ret && errno == EINVAL , "GIC redist/cpu base not aligned" );
113
153
114
154
/* out of range address */
115
155
if (max_ipa_bits ) {
116
156
addr = 1ULL << max_ipa_bits ;
117
157
ret = _kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
118
- KVM_VGIC_V3_ADDR_TYPE_DIST , & addr , true);
158
+ dist . attr , & addr , true);
119
159
TEST_ASSERT (ret && errno == E2BIG , "dist address beyond IPA limit" );
120
160
121
161
ret = _kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
122
- KVM_VGIC_V3_ADDR_TYPE_REDIST , & addr , true);
162
+ rdist . attr , & addr , true);
123
163
TEST_ASSERT (ret && errno == E2BIG , "redist address beyond IPA limit" );
124
164
}
125
165
126
166
/* set REDIST base address @0x0*/
127
167
addr = 0x00000 ;
128
168
kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
129
- KVM_VGIC_V3_ADDR_TYPE_REDIST , & addr , true);
169
+ rdist . attr , & addr , true);
130
170
131
171
/* Attempt to create a second legacy redistributor region */
132
172
addr = 0xE0000 ;
133
173
ret = _kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
134
- KVM_VGIC_V3_ADDR_TYPE_REDIST , & addr , true);
135
- TEST_ASSERT (ret && errno == EEXIST , "GICv3 redist base set again" );
174
+ rdist . attr , & addr , true);
175
+ TEST_ASSERT (ret && errno == EEXIST , "GIC redist base set again" );
136
176
137
- /* Attempt to mix legacy and new redistributor regions */
138
- addr = REDIST_REGION_ATTR_ADDR (NR_VCPUS , 0x100000 , 0 , 0 );
139
- ret = _kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
140
- KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION , & addr , true);
141
- TEST_ASSERT (ret && errno == EINVAL , "attempt to mix GICv3 REDIST and REDIST_REGION" );
177
+ ret = _kvm_device_check_attr (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
178
+ KVM_VGIC_V3_ADDR_TYPE_REDIST );
179
+ if (!ret ) {
180
+ /* Attempt to mix legacy and new redistributor regions */
181
+ addr = REDIST_REGION_ATTR_ADDR (NR_VCPUS , 0x100000 , 0 , 0 );
182
+ ret = _kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
183
+ KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION ,
184
+ & addr , true);
185
+ TEST_ASSERT (ret && errno == EINVAL ,
186
+ "attempt to mix GICv3 REDIST and REDIST_REGION" );
187
+ }
142
188
143
189
/*
144
190
* Set overlapping DIST / REDIST, cannot be detected here. Will be detected
145
191
* on first vcpu run instead.
146
192
*/
147
- addr = 3 * 2 * 0x10000 ;
148
- kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR , KVM_VGIC_V3_ADDR_TYPE_DIST ,
149
- & addr , true);
193
+ addr = rdist . size - rdist . alignment ;
194
+ kvm_device_access (v -> gic_fd , KVM_DEV_ARM_VGIC_GRP_ADDR ,
195
+ dist . attr , & addr , true);
150
196
}
151
197
152
198
/* Test the new REDIST region API */
@@ -254,14 +300,14 @@ static void subtest_v3_redist_regions(struct vm_gic *v)
254
300
* VGIC KVM device is created and initialized before the secondary CPUs
255
301
* get created
256
302
*/
257
- static void test_v3_vgic_then_vcpus (uint32_t gic_dev_type )
303
+ static void test_vgic_then_vcpus (uint32_t gic_dev_type )
258
304
{
259
305
struct vm_gic v ;
260
306
int ret , i ;
261
307
262
308
v = vm_gic_create_with_vcpus (gic_dev_type , 1 );
263
309
264
- subtest_v3_dist_rdist (& v );
310
+ subtest_dist_rdist (& v );
265
311
266
312
/* Add the rest of the VCPUs */
267
313
for (i = 1 ; i < NR_VCPUS ; ++ i )
@@ -274,14 +320,14 @@ static void test_v3_vgic_then_vcpus(uint32_t gic_dev_type)
274
320
}
275
321
276
322
/* All the VCPUs are created before the VGIC KVM device gets initialized */
277
- static void test_v3_vcpus_then_vgic (uint32_t gic_dev_type )
323
+ static void test_vcpus_then_vgic (uint32_t gic_dev_type )
278
324
{
279
325
struct vm_gic v ;
280
326
int ret ;
281
327
282
328
v = vm_gic_create_with_vcpus (gic_dev_type , NR_VCPUS );
283
329
284
- subtest_v3_dist_rdist (& v );
330
+ subtest_dist_rdist (& v );
285
331
286
332
ret = run_vcpu (v .vm , 3 );
287
333
TEST_ASSERT (ret == - EINVAL , "dist/rdist overlap detected on 1st vcpu run" );
@@ -550,9 +596,10 @@ int test_kvm_device(uint32_t gic_dev_type)
550
596
551
597
void run_tests (uint32_t gic_dev_type )
552
598
{
599
+ test_vcpus_then_vgic (gic_dev_type );
600
+ test_vgic_then_vcpus (gic_dev_type );
601
+
553
602
if (VGIC_DEV_IS_V3 (gic_dev_type )) {
554
- test_v3_vcpus_then_vgic (gic_dev_type );
555
- test_v3_vgic_then_vcpus (gic_dev_type );
556
603
test_v3_new_redist_regions ();
557
604
test_v3_typer_accesses ();
558
605
test_v3_last_bit_redist_regions ();
0 commit comments