diff options
author | Scott Wood <scottwood@freescale.com> | 2013-04-30 10:57:13 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2013-05-02 09:28:33 -0400 |
commit | 398d87836e3074ff630805b77d024a88ac288606 (patch) | |
tree | 17b3b58b140472594c83713bb60f3c9c01ce789c /arch/powerpc | |
parent | 121ac4540f606026722ebb1bae68d9c43e518db9 (diff) |
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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kvm/mpic.c | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c index f3148f8cdc12..886ebf6f698d 100644 --- a/arch/powerpc/kvm/mpic.c +++ b/arch/powerpc/kvm/mpic.c | |||
@@ -184,11 +184,14 @@ struct irq_dest { | |||
184 | uint32_t outputs_active[NUM_OUTPUTS]; | 184 | uint32_t outputs_active[NUM_OUTPUTS]; |
185 | }; | 185 | }; |
186 | 186 | ||
187 | #define MAX_MMIO_REGIONS 10 | ||
188 | |||
187 | struct openpic { | 189 | struct openpic { |
188 | struct kvm *kvm; | 190 | struct kvm *kvm; |
189 | struct kvm_device *dev; | 191 | struct kvm_device *dev; |
190 | struct kvm_io_device mmio; | 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 | atomic_t users; | 195 | atomic_t users; |
193 | 196 | ||
194 | gpa_t reg_base; | 197 | gpa_t reg_base; |
@@ -1238,62 +1241,71 @@ static int openpic_cpu_read(void *opaque, gpa_t addr, u32 *ptr) | |||
1238 | } | 1241 | } |
1239 | 1242 | ||
1240 | struct mem_reg { | 1243 | struct mem_reg { |
1241 | struct list_head list; | ||
1242 | int (*read)(void *opaque, gpa_t addr, u32 *ptr); | 1244 | int (*read)(void *opaque, gpa_t addr, u32 *ptr); |
1243 | int (*write)(void *opaque, gpa_t addr, u32 val); | 1245 | int (*write)(void *opaque, gpa_t addr, u32 val); |
1244 | gpa_t start_addr; | 1246 | gpa_t start_addr; |
1245 | int size; | 1247 | int size; |
1246 | }; | 1248 | }; |
1247 | 1249 | ||
1248 | static struct mem_reg openpic_gbl_mmio = { | 1250 | static const struct mem_reg openpic_gbl_mmio = { |
1249 | .write = openpic_gbl_write, | 1251 | .write = openpic_gbl_write, |
1250 | .read = openpic_gbl_read, | 1252 | .read = openpic_gbl_read, |
1251 | .start_addr = OPENPIC_GLB_REG_START, | 1253 | .start_addr = OPENPIC_GLB_REG_START, |
1252 | .size = OPENPIC_GLB_REG_SIZE, | 1254 | .size = OPENPIC_GLB_REG_SIZE, |
1253 | }; | 1255 | }; |
1254 | 1256 | ||
1255 | static struct mem_reg openpic_tmr_mmio = { | 1257 | static const struct mem_reg openpic_tmr_mmio = { |
1256 | .write = openpic_tmr_write, | 1258 | .write = openpic_tmr_write, |
1257 | .read = openpic_tmr_read, | 1259 | .read = openpic_tmr_read, |
1258 | .start_addr = OPENPIC_TMR_REG_START, | 1260 | .start_addr = OPENPIC_TMR_REG_START, |
1259 | .size = OPENPIC_TMR_REG_SIZE, | 1261 | .size = OPENPIC_TMR_REG_SIZE, |
1260 | }; | 1262 | }; |
1261 | 1263 | ||
1262 | static struct mem_reg openpic_cpu_mmio = { | 1264 | static const struct mem_reg openpic_cpu_mmio = { |
1263 | .write = openpic_cpu_write, | 1265 | .write = openpic_cpu_write, |
1264 | .read = openpic_cpu_read, | 1266 | .read = openpic_cpu_read, |
1265 | .start_addr = OPENPIC_CPU_REG_START, | 1267 | .start_addr = OPENPIC_CPU_REG_START, |
1266 | .size = OPENPIC_CPU_REG_SIZE, | 1268 | .size = OPENPIC_CPU_REG_SIZE, |
1267 | }; | 1269 | }; |
1268 | 1270 | ||
1269 | static struct mem_reg openpic_src_mmio = { | 1271 | static const struct mem_reg openpic_src_mmio = { |
1270 | .write = openpic_src_write, | 1272 | .write = openpic_src_write, |
1271 | .read = openpic_src_read, | 1273 | .read = openpic_src_read, |
1272 | .start_addr = OPENPIC_SRC_REG_START, | 1274 | .start_addr = OPENPIC_SRC_REG_START, |
1273 | .size = OPENPIC_SRC_REG_SIZE, | 1275 | .size = OPENPIC_SRC_REG_SIZE, |
1274 | }; | 1276 | }; |
1275 | 1277 | ||
1276 | static struct mem_reg openpic_msi_mmio = { | 1278 | static const struct mem_reg openpic_msi_mmio = { |
1277 | .read = openpic_msi_read, | 1279 | .read = openpic_msi_read, |
1278 | .write = openpic_msi_write, | 1280 | .write = openpic_msi_write, |
1279 | .start_addr = OPENPIC_MSI_REG_START, | 1281 | .start_addr = OPENPIC_MSI_REG_START, |
1280 | .size = OPENPIC_MSI_REG_SIZE, | 1282 | .size = OPENPIC_MSI_REG_SIZE, |
1281 | }; | 1283 | }; |
1282 | 1284 | ||
1283 | static struct mem_reg openpic_summary_mmio = { | 1285 | static const struct mem_reg openpic_summary_mmio = { |
1284 | .read = openpic_summary_read, | 1286 | .read = openpic_summary_read, |
1285 | .write = openpic_summary_write, | 1287 | .write = openpic_summary_write, |
1286 | .start_addr = OPENPIC_SUMMARY_REG_START, | 1288 | .start_addr = OPENPIC_SUMMARY_REG_START, |
1287 | .size = OPENPIC_SUMMARY_REG_SIZE, | 1289 | .size = OPENPIC_SUMMARY_REG_SIZE, |
1288 | }; | 1290 | }; |
1289 | 1291 | ||
1292 | static void add_mmio_region(struct openpic *opp, const struct mem_reg *mr) | ||
1293 | { | ||
1294 | if (opp->num_mmio_regions >= MAX_MMIO_REGIONS) { | ||
1295 | WARN(1, "kvm mpic: too many mmio regions\n"); | ||
1296 | return; | ||
1297 | } | ||
1298 | |||
1299 | opp->mmio_regions[opp->num_mmio_regions++] = mr; | ||
1300 | } | ||
1301 | |||
1290 | static void fsl_common_init(struct openpic *opp) | 1302 | static void fsl_common_init(struct openpic *opp) |
1291 | { | 1303 | { |
1292 | int i; | 1304 | int i; |
1293 | int virq = MAX_SRC; | 1305 | int virq = MAX_SRC; |
1294 | 1306 | ||
1295 | list_add(&openpic_msi_mmio.list, &opp->mmio_regions); | 1307 | add_mmio_region(opp, &openpic_msi_mmio); |
1296 | list_add(&openpic_summary_mmio.list, &opp->mmio_regions); | 1308 | add_mmio_region(opp, &openpic_summary_mmio); |
1297 | 1309 | ||
1298 | opp->vid = VID_REVISION_1_2; | 1310 | opp->vid = VID_REVISION_1_2; |
1299 | opp->vir = VIR_GENERIC; | 1311 | opp->vir = VIR_GENERIC; |
@@ -1330,10 +1342,10 @@ static void fsl_common_init(struct openpic *opp) | |||
1330 | 1342 | ||
1331 | static int kvm_mpic_read_internal(struct openpic *opp, gpa_t addr, u32 *ptr) | 1343 | static int kvm_mpic_read_internal(struct openpic *opp, gpa_t addr, u32 *ptr) |
1332 | { | 1344 | { |
1333 | struct list_head *node; | 1345 | int i; |
1334 | 1346 | ||
1335 | list_for_each(node, &opp->mmio_regions) { | 1347 | for (i = 0; i < opp->num_mmio_regions; i++) { |
1336 | struct mem_reg *mr = list_entry(node, struct mem_reg, list); | 1348 | const struct mem_reg *mr = opp->mmio_regions[i]; |
1337 | 1349 | ||
1338 | if (mr->start_addr > addr || addr >= mr->start_addr + mr->size) | 1350 | if (mr->start_addr > addr || addr >= mr->start_addr + mr->size) |
1339 | continue; | 1351 | continue; |
@@ -1346,10 +1358,10 @@ static int kvm_mpic_read_internal(struct openpic *opp, gpa_t addr, u32 *ptr) | |||
1346 | 1358 | ||
1347 | static int kvm_mpic_write_internal(struct openpic *opp, gpa_t addr, u32 val) | 1359 | static int kvm_mpic_write_internal(struct openpic *opp, gpa_t addr, u32 val) |
1348 | { | 1360 | { |
1349 | struct list_head *node; | 1361 | int i; |
1350 | 1362 | ||
1351 | list_for_each(node, &opp->mmio_regions) { | 1363 | for (i = 0; i < opp->num_mmio_regions; i++) { |
1352 | struct mem_reg *mr = list_entry(node, struct mem_reg, list); | 1364 | const struct mem_reg *mr = opp->mmio_regions[i]; |
1353 | 1365 | ||
1354 | if (mr->start_addr > addr || addr >= mr->start_addr + mr->size) | 1366 | if (mr->start_addr > addr || addr >= mr->start_addr + mr->size) |
1355 | continue; | 1367 | continue; |
@@ -1660,11 +1672,10 @@ static int mpic_create(struct kvm_device *dev, u32 type) | |||
1660 | opp->model = type; | 1672 | opp->model = type; |
1661 | spin_lock_init(&opp->lock); | 1673 | spin_lock_init(&opp->lock); |
1662 | 1674 | ||
1663 | INIT_LIST_HEAD(&opp->mmio_regions); | 1675 | add_mmio_region(opp, &openpic_gbl_mmio); |
1664 | list_add(&openpic_gbl_mmio.list, &opp->mmio_regions); | 1676 | add_mmio_region(opp, &openpic_tmr_mmio); |
1665 | list_add(&openpic_tmr_mmio.list, &opp->mmio_regions); | 1677 | add_mmio_region(opp, &openpic_src_mmio); |
1666 | list_add(&openpic_src_mmio.list, &opp->mmio_regions); | 1678 | add_mmio_region(opp, &openpic_cpu_mmio); |
1667 | list_add(&openpic_cpu_mmio.list, &opp->mmio_regions); | ||
1668 | 1679 | ||
1669 | switch (opp->model) { | 1680 | switch (opp->model) { |
1670 | case KVM_DEV_TYPE_FSL_MPIC_20: | 1681 | case KVM_DEV_TYPE_FSL_MPIC_20: |