@@ -66,6 +66,10 @@ struct kvm_resize_hpt {
66
66
/* These fields protected by kvm->lock */
67
67
int error ;
68
68
bool prepare_done ;
69
+
70
+ /* Private to the work thread, until prepare_done is true,
71
+ * then protected by kvm->resize_hpt_sem */
72
+ struct kvm_hpt_info hpt ;
69
73
};
70
74
71
75
static void kvmppc_rmap_reset (struct kvm * kvm );
@@ -1209,21 +1213,203 @@ void kvmppc_unpin_guest_page(struct kvm *kvm, void *va, unsigned long gpa,
1209
1213
*/
1210
1214
static int resize_hpt_allocate (struct kvm_resize_hpt * resize )
1211
1215
{
1216
+ int rc ;
1217
+
1218
+ rc = kvmppc_allocate_hpt (& resize -> hpt , resize -> order );
1219
+ if (rc < 0 )
1220
+ return rc ;
1221
+
1222
+ resize_hpt_debug (resize , "resize_hpt_allocate(): HPT @ 0x%lx\n" ,
1223
+ resize -> hpt .virt );
1224
+
1212
1225
return 0 ;
1213
1226
}
1214
1227
1228
+ static unsigned long resize_hpt_rehash_hpte (struct kvm_resize_hpt * resize ,
1229
+ unsigned long idx )
1230
+ {
1231
+ struct kvm * kvm = resize -> kvm ;
1232
+ struct kvm_hpt_info * old = & kvm -> arch .hpt ;
1233
+ struct kvm_hpt_info * new = & resize -> hpt ;
1234
+ unsigned long old_hash_mask = (1ULL << (old -> order - 7 )) - 1 ;
1235
+ unsigned long new_hash_mask = (1ULL << (new -> order - 7 )) - 1 ;
1236
+ __be64 * hptep , * new_hptep ;
1237
+ unsigned long vpte , rpte , guest_rpte ;
1238
+ int ret ;
1239
+ struct revmap_entry * rev ;
1240
+ unsigned long apsize , psize , avpn , pteg , hash ;
1241
+ unsigned long new_idx , new_pteg , replace_vpte ;
1242
+
1243
+ hptep = (__be64 * )(old -> virt + (idx << 4 ));
1244
+
1245
+ /* Guest is stopped, so new HPTEs can't be added or faulted
1246
+ * in, only unmapped or altered by host actions. So, it's
1247
+ * safe to check this before we take the HPTE lock */
1248
+ vpte = be64_to_cpu (hptep [0 ]);
1249
+ if (!(vpte & HPTE_V_VALID ) && !(vpte & HPTE_V_ABSENT ))
1250
+ return 0 ; /* nothing to do */
1251
+
1252
+ while (!try_lock_hpte (hptep , HPTE_V_HVLOCK ))
1253
+ cpu_relax ();
1254
+
1255
+ vpte = be64_to_cpu (hptep [0 ]);
1256
+
1257
+ ret = 0 ;
1258
+ if (!(vpte & HPTE_V_VALID ) && !(vpte & HPTE_V_ABSENT ))
1259
+ /* Nothing to do */
1260
+ goto out ;
1261
+
1262
+ /* Unmap */
1263
+ rev = & old -> rev [idx ];
1264
+ guest_rpte = rev -> guest_rpte ;
1265
+
1266
+ ret = - EIO ;
1267
+ apsize = hpte_page_size (vpte , guest_rpte );
1268
+ if (!apsize )
1269
+ goto out ;
1270
+
1271
+ if (vpte & HPTE_V_VALID ) {
1272
+ unsigned long gfn = hpte_rpn (guest_rpte , apsize );
1273
+ int srcu_idx = srcu_read_lock (& kvm -> srcu );
1274
+ struct kvm_memory_slot * memslot =
1275
+ __gfn_to_memslot (kvm_memslots (kvm ), gfn );
1276
+
1277
+ if (memslot ) {
1278
+ unsigned long * rmapp ;
1279
+ rmapp = & memslot -> arch .rmap [gfn - memslot -> base_gfn ];
1280
+
1281
+ lock_rmap (rmapp );
1282
+ kvmppc_unmap_hpte (kvm , idx , rmapp , gfn );
1283
+ unlock_rmap (rmapp );
1284
+ }
1285
+
1286
+ srcu_read_unlock (& kvm -> srcu , srcu_idx );
1287
+ }
1288
+
1289
+ /* Reload PTE after unmap */
1290
+ vpte = be64_to_cpu (hptep [0 ]);
1291
+
1292
+ BUG_ON (vpte & HPTE_V_VALID );
1293
+ BUG_ON (!(vpte & HPTE_V_ABSENT ));
1294
+
1295
+ ret = 0 ;
1296
+ if (!(vpte & HPTE_V_BOLTED ))
1297
+ goto out ;
1298
+
1299
+ rpte = be64_to_cpu (hptep [1 ]);
1300
+ psize = hpte_base_page_size (vpte , rpte );
1301
+ avpn = HPTE_V_AVPN_VAL (vpte ) & ~((psize - 1 ) >> 23 );
1302
+ pteg = idx / HPTES_PER_GROUP ;
1303
+ if (vpte & HPTE_V_SECONDARY )
1304
+ pteg = ~pteg ;
1305
+
1306
+ if (!(vpte & HPTE_V_1TB_SEG )) {
1307
+ unsigned long offset , vsid ;
1308
+
1309
+ /* We only have 28 - 23 bits of offset in avpn */
1310
+ offset = (avpn & 0x1f ) << 23 ;
1311
+ vsid = avpn >> 5 ;
1312
+ /* We can find more bits from the pteg value */
1313
+ if (psize < (1ULL << 23 ))
1314
+ offset |= ((vsid ^ pteg ) & old_hash_mask ) * psize ;
1315
+
1316
+ hash = vsid ^ (offset / psize );
1317
+ } else {
1318
+ unsigned long offset , vsid ;
1319
+
1320
+ /* We only have 40 - 23 bits of seg_off in avpn */
1321
+ offset = (avpn & 0x1ffff ) << 23 ;
1322
+ vsid = avpn >> 17 ;
1323
+ if (psize < (1ULL << 23 ))
1324
+ offset |= ((vsid ^ (vsid << 25 ) ^ pteg ) & old_hash_mask ) * psize ;
1325
+
1326
+ hash = vsid ^ (vsid << 25 ) ^ (offset / psize );
1327
+ }
1328
+
1329
+ new_pteg = hash & new_hash_mask ;
1330
+ if (vpte & HPTE_V_SECONDARY ) {
1331
+ BUG_ON (~pteg != (hash & old_hash_mask ));
1332
+ new_pteg = ~new_pteg ;
1333
+ } else {
1334
+ BUG_ON (pteg != (hash & old_hash_mask ));
1335
+ }
1336
+
1337
+ new_idx = new_pteg * HPTES_PER_GROUP + (idx % HPTES_PER_GROUP );
1338
+ new_hptep = (__be64 * )(new -> virt + (new_idx << 4 ));
1339
+
1340
+ replace_vpte = be64_to_cpu (new_hptep [0 ]);
1341
+
1342
+ if (replace_vpte & (HPTE_V_VALID | HPTE_V_ABSENT )) {
1343
+ BUG_ON (new -> order >= old -> order );
1344
+
1345
+ if (replace_vpte & HPTE_V_BOLTED ) {
1346
+ if (vpte & HPTE_V_BOLTED )
1347
+ /* Bolted collision, nothing we can do */
1348
+ ret = - ENOSPC ;
1349
+ /* Discard the new HPTE */
1350
+ goto out ;
1351
+ }
1352
+
1353
+ /* Discard the previous HPTE */
1354
+ }
1355
+
1356
+ new_hptep [1 ] = cpu_to_be64 (rpte );
1357
+ new -> rev [new_idx ].guest_rpte = guest_rpte ;
1358
+ /* No need for a barrier, since new HPT isn't active */
1359
+ new_hptep [0 ] = cpu_to_be64 (vpte );
1360
+ unlock_hpte (new_hptep , vpte );
1361
+
1362
+ out :
1363
+ unlock_hpte (hptep , vpte );
1364
+ return ret ;
1365
+ }
1366
+
1215
1367
static int resize_hpt_rehash (struct kvm_resize_hpt * resize )
1216
1368
{
1217
- return - EIO ;
1369
+ struct kvm * kvm = resize -> kvm ;
1370
+ unsigned long i ;
1371
+ int rc ;
1372
+
1373
+ for (i = 0 ; i < kvmppc_hpt_npte (& kvm -> arch .hpt ); i ++ ) {
1374
+ rc = resize_hpt_rehash_hpte (resize , i );
1375
+ if (rc != 0 )
1376
+ return rc ;
1377
+ }
1378
+
1379
+ return 0 ;
1218
1380
}
1219
1381
1220
1382
static void resize_hpt_pivot (struct kvm_resize_hpt * resize )
1221
1383
{
1384
+ struct kvm * kvm = resize -> kvm ;
1385
+ struct kvm_hpt_info hpt_tmp ;
1386
+
1387
+ /* Exchange the pending tables in the resize structure with
1388
+ * the active tables */
1389
+
1390
+ resize_hpt_debug (resize , "resize_hpt_pivot()\n" );
1391
+
1392
+ spin_lock (& kvm -> mmu_lock );
1393
+ asm volatile ("ptesync" : : : "memory" );
1394
+
1395
+ hpt_tmp = kvm -> arch .hpt ;
1396
+ kvmppc_set_hpt (kvm , & resize -> hpt );
1397
+ resize -> hpt = hpt_tmp ;
1398
+
1399
+ spin_unlock (& kvm -> mmu_lock );
1400
+
1401
+ synchronize_srcu_expedited (& kvm -> srcu );
1402
+
1403
+ resize_hpt_debug (resize , "resize_hpt_pivot() done\n" );
1222
1404
}
1223
1405
1224
1406
static void resize_hpt_release (struct kvm * kvm , struct kvm_resize_hpt * resize )
1225
1407
{
1226
1408
BUG_ON (kvm -> arch .resize_hpt != resize );
1409
+
1410
+ if (resize -> hpt .virt )
1411
+ kvmppc_free_hpt (& resize -> hpt );
1412
+
1227
1413
kvm -> arch .resize_hpt = NULL ;
1228
1414
kfree (resize );
1229
1415
}
0 commit comments