Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kvm/ppc/mpic: fix mmio region lists when multiple guests used

Keeping a linked list of statically defined objects doesn't work
very well when we have multiple guests. :-P

Switch to an array of constant objects. This fixes a hang when
multiple guests are used.

Signed-off-by: Scott Wood <scottwood@freescale.com>
[agraf: remove struct list_head from mem_reg]
Signed-off-by: Alexander Graf <agraf@suse.de>

authored by

Scott Wood and committed by
Alexander Graf
398d8783 121ac454

+32 -21
+32 -21
arch/powerpc/kvm/mpic.c
··· 184 184 uint32_t outputs_active[NUM_OUTPUTS]; 185 185 }; 186 186 187 + #define MAX_MMIO_REGIONS 10 188 + 187 189 struct openpic { 188 190 struct kvm *kvm; 189 191 struct kvm_device *dev; 190 192 struct kvm_io_device mmio; 191 - struct list_head mmio_regions; 193 + const struct mem_reg *mmio_regions[MAX_MMIO_REGIONS]; 194 + int num_mmio_regions; 192 195 atomic_t users; 193 196 194 197 gpa_t reg_base; ··· 1241 1238 } 1242 1239 1243 1240 struct mem_reg { 1244 - struct list_head list; 1245 1241 int (*read)(void *opaque, gpa_t addr, u32 *ptr); 1246 1242 int (*write)(void *opaque, gpa_t addr, u32 val); 1247 1243 gpa_t start_addr; 1248 1244 int size; 1249 1245 }; 1250 1246 1251 - static struct mem_reg openpic_gbl_mmio = { 1247 + static const struct mem_reg openpic_gbl_mmio = { 1252 1248 .write = openpic_gbl_write, 1253 1249 .read = openpic_gbl_read, 1254 1250 .start_addr = OPENPIC_GLB_REG_START, 1255 1251 .size = OPENPIC_GLB_REG_SIZE, 1256 1252 }; 1257 1253 1258 - static struct mem_reg openpic_tmr_mmio = { 1254 + static const struct mem_reg openpic_tmr_mmio = { 1259 1255 .write = openpic_tmr_write, 1260 1256 .read = openpic_tmr_read, 1261 1257 .start_addr = OPENPIC_TMR_REG_START, 1262 1258 .size = OPENPIC_TMR_REG_SIZE, 1263 1259 }; 1264 1260 1265 - static struct mem_reg openpic_cpu_mmio = { 1261 + static const struct mem_reg openpic_cpu_mmio = { 1266 1262 .write = openpic_cpu_write, 1267 1263 .read = openpic_cpu_read, 1268 1264 .start_addr = OPENPIC_CPU_REG_START, 1269 1265 .size = OPENPIC_CPU_REG_SIZE, 1270 1266 }; 1271 1267 1272 - static struct mem_reg openpic_src_mmio = { 1268 + static const struct mem_reg openpic_src_mmio = { 1273 1269 .write = openpic_src_write, 1274 1270 .read = openpic_src_read, 1275 1271 .start_addr = OPENPIC_SRC_REG_START, 1276 1272 .size = OPENPIC_SRC_REG_SIZE, 1277 1273 }; 1278 1274 1279 - static struct mem_reg openpic_msi_mmio = { 1275 + static const struct mem_reg openpic_msi_mmio = { 1280 1276 .read = openpic_msi_read, 1281 1277 .write = openpic_msi_write, 1282 1278 .start_addr = OPENPIC_MSI_REG_START, 1283 1279 .size = OPENPIC_MSI_REG_SIZE, 1284 1280 }; 1285 1281 1286 - static struct mem_reg openpic_summary_mmio = { 1282 + static const struct mem_reg openpic_summary_mmio = { 1287 1283 .read = openpic_summary_read, 1288 1284 .write = openpic_summary_write, 1289 1285 .start_addr = OPENPIC_SUMMARY_REG_START, 1290 1286 .size = OPENPIC_SUMMARY_REG_SIZE, 1291 1287 }; 1292 1288 1289 + static void add_mmio_region(struct openpic *opp, const struct mem_reg *mr) 1290 + { 1291 + if (opp->num_mmio_regions >= MAX_MMIO_REGIONS) { 1292 + WARN(1, "kvm mpic: too many mmio regions\n"); 1293 + return; 1294 + } 1295 + 1296 + opp->mmio_regions[opp->num_mmio_regions++] = mr; 1297 + } 1298 + 1293 1299 static void fsl_common_init(struct openpic *opp) 1294 1300 { 1295 1301 int i; 1296 1302 int virq = MAX_SRC; 1297 1303 1298 - list_add(&openpic_msi_mmio.list, &opp->mmio_regions); 1299 - list_add(&openpic_summary_mmio.list, &opp->mmio_regions); 1304 + add_mmio_region(opp, &openpic_msi_mmio); 1305 + add_mmio_region(opp, &openpic_summary_mmio); 1300 1306 1301 1307 opp->vid = VID_REVISION_1_2; 1302 1308 opp->vir = VIR_GENERIC; ··· 1342 1330 1343 1331 static int kvm_mpic_read_internal(struct openpic *opp, gpa_t addr, u32 *ptr) 1344 1332 { 1345 - struct list_head *node; 1333 + int i; 1346 1334 1347 - list_for_each(node, &opp->mmio_regions) { 1348 - struct mem_reg *mr = list_entry(node, struct mem_reg, list); 1335 + for (i = 0; i < opp->num_mmio_regions; i++) { 1336 + const struct mem_reg *mr = opp->mmio_regions[i]; 1349 1337 1350 1338 if (mr->start_addr > addr || addr >= mr->start_addr + mr->size) 1351 1339 continue; ··· 1358 1346 1359 1347 static int kvm_mpic_write_internal(struct openpic *opp, gpa_t addr, u32 val) 1360 1348 { 1361 - struct list_head *node; 1349 + int i; 1362 1350 1363 - list_for_each(node, &opp->mmio_regions) { 1364 - struct mem_reg *mr = list_entry(node, struct mem_reg, list); 1351 + for (i = 0; i < opp->num_mmio_regions; i++) { 1352 + const struct mem_reg *mr = opp->mmio_regions[i]; 1365 1353 1366 1354 if (mr->start_addr > addr || addr >= mr->start_addr + mr->size) 1367 1355 continue; ··· 1672 1660 opp->model = type; 1673 1661 spin_lock_init(&opp->lock); 1674 1662 1675 - INIT_LIST_HEAD(&opp->mmio_regions); 1676 - list_add(&openpic_gbl_mmio.list, &opp->mmio_regions); 1677 - list_add(&openpic_tmr_mmio.list, &opp->mmio_regions); 1678 - list_add(&openpic_src_mmio.list, &opp->mmio_regions); 1679 - list_add(&openpic_cpu_mmio.list, &opp->mmio_regions); 1663 + add_mmio_region(opp, &openpic_gbl_mmio); 1664 + add_mmio_region(opp, &openpic_tmr_mmio); 1665 + add_mmio_region(opp, &openpic_src_mmio); 1666 + add_mmio_region(opp, &openpic_cpu_mmio); 1680 1667 1681 1668 switch (opp->model) { 1682 1669 case KVM_DEV_TYPE_FSL_MPIC_20: