Compare commits
	
		
			290 Commits
		
	
	
		
			pull-input
			...
			pull-roms-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 3257fc8383 | ||
|  | 9bb931802e | ||
|  | d7d3d6092c | ||
|  | 66226ffd05 | ||
|  | 24666baf1f | ||
|  | a62f6f5600 | ||
|  | ae18b28dd1 | ||
|  | d2e16f2ce1 | ||
|  | 1695974187 | ||
|  | 3d9bddb30b | ||
|  | e9a9a5b605 | ||
|  | 2c90784abf | ||
|  | 011209e19f | ||
|  | bbb8a1b455 | ||
|  | afb49896fa | ||
|  | 72866e823e | ||
|  | a5ed2de10a | ||
|  | 836d6ed96e | ||
|  | c017230d9b | ||
|  | 944eea962b | ||
|  | 2ef6175aa7 | ||
|  | a763551ad5 | ||
|  | de77914e50 | ||
|  | a5f54290ce | ||
|  | 6b1b144019 | ||
|  | a199b2b6a5 | ||
|  | 1d10b44546 | ||
|  | 13d7adf92a | ||
|  | 3ef9622182 | ||
|  | 0380aef323 | ||
|  | 3ee933c9d4 | ||
|  | 052367ba85 | ||
|  | adbfc34103 | ||
|  | 972b09c219 | ||
|  | fbab9ccbdb | ||
|  | efde4b6252 | ||
|  | e67c399363 | ||
|  | dc83cd427b | ||
|  | 7d2d3e74e5 | ||
|  | 318df29e10 | ||
|  | 356b4ca2bb | ||
|  | dfb12bf86e | ||
|  | d11c8917b2 | ||
|  | 68c70af16d | ||
|  | 5496fb1aeb | ||
|  | 5f0c39e598 | ||
|  | 4618e658e6 | ||
|  | 01c2b265fc | ||
|  | 04bc7c0e38 | ||
|  | d61563b235 | ||
|  | 3775ec6f5a | ||
|  | b1422f2040 | ||
|  | e8817e7b0e | ||
|  | 6815bce542 | ||
|  | ce782938b8 | ||
|  | 826b6ca0b0 | ||
|  | 920beae103 | ||
|  | 8d24cce1e3 | ||
|  | 628ff68303 | ||
|  | 3718d8ab65 | ||
|  | fbe40ff780 | ||
|  | 8574575f90 | ||
|  | 0bf7488afb | ||
|  | 271c0f68b4 | ||
|  | bd60436936 | ||
|  | 4ba6fabfb4 | ||
|  | 7cf6376ae8 | ||
|  | 53651ec26b | ||
|  | 109519fd32 | ||
|  | 4aa23452e3 | ||
|  | 9474ab1487 | ||
|  | 2f21ff25c0 | ||
|  | 27aa948502 | ||
|  | a1ba125c0c | ||
|  | d42e3c26cd | ||
|  | 855ea66dd5 | ||
|  | 61d4b215d1 | ||
|  | db6c3cd0e7 | ||
|  | 14c521d45e | ||
|  | 7ab6c10d00 | ||
|  | 81547d6630 | ||
|  | 3b685ba7bf | ||
|  | 1fe8141ed4 | ||
|  | cca7c2f523 | ||
|  | 2a923c4dde | ||
|  | 28c9457df0 | ||
|  | 1b1742386c | ||
|  | 73fb3b764b | ||
|  | 68fdb6c5b0 | ||
|  | d81c519c40 | ||
|  | 6947f05978 | ||
|  | f79fbf39e2 | ||
|  | 6ce2faf43c | ||
|  | c119779543 | ||
|  | a99caa48d8 | ||
|  | 9d4c4e872e | ||
|  | f0aff25570 | ||
|  | fc37b7a0b0 | ||
|  | 9ef137cad6 | ||
|  | 93f94f9018 | ||
|  | 00d0f7cb66 | ||
|  | 57a740514d | ||
|  | ca3164df4d | ||
|  | 433d33c555 | ||
|  | 8977bd111f | ||
|  | f85d28316a | ||
|  | ee8c0b622c | ||
|  | 6f5943cf45 | ||
|  | 8b84286f4c | ||
|  | 1ff5eedd1d | ||
|  | 86846bfe64 | ||
|  | 2386a90730 | ||
|  | 11c7fa7fa6 | ||
|  | f5c0ab1312 | ||
|  | 1687a089f1 | ||
|  | 116d554601 | ||
|  | 1fba509527 | ||
|  | 69e995040c | ||
|  | 8d1bd3c901 | ||
|  | 56a9f18051 | ||
|  | b664b80f19 | ||
|  | 19e8393170 | ||
|  | 22513a9b44 | ||
|  | 68206d7342 | ||
|  | 36084d7e31 | ||
|  | f995523582 | ||
|  | 058fdcf52c | ||
|  | 463c534db5 | ||
|  | 6fa2769751 | ||
|  | 82fc18099a | ||
|  | 0f61a61df3 | ||
|  | 3158a3482b | ||
|  | aa0a55d42d | ||
|  | 0c77a37f11 | ||
|  | 99623c90d1 | ||
|  | 2884cf5b93 | ||
|  | 4eeaa3a885 | ||
|  | 746b867030 | ||
|  | 4c638e2e4b | ||
|  | 1c856da57b | ||
|  | 74444bc198 | ||
|  | cdeb7090ee | ||
|  | d3ef575080 | ||
|  | 6a24ced5ca | ||
|  | ed1132e41a | ||
|  | e3500d1f5f | ||
|  | 271a25c0b6 | ||
|  | 832189c9b1 | ||
|  | 0fb20d1c39 | ||
|  | ee5f31e48b | ||
|  | 6fe83074d7 | ||
|  | 3f9a6e852e | ||
|  | fd07d07ba9 | ||
|  | aea7947c74 | ||
|  | b35e3ba01a | ||
|  | 521a580d23 | ||
|  | afff2b15e8 | ||
|  | d09b8fa161 | ||
|  | 25156d1061 | ||
|  | 4e7d30a22a | ||
|  | f7bbcfb5c3 | ||
|  | a946ce8020 | ||
|  | b6bfeea92a | ||
|  | 33fac20bb2 | ||
|  | 3401fd259e | ||
|  | 1db1c4d7d9 | ||
|  | 9a2f0bfe32 | ||
|  | c068896f7f | ||
|  | fd1cf66630 | ||
|  | 4f048535cd | ||
|  | 741f117d9a | ||
|  | 22ee3a987d | ||
|  | 070603f62b | ||
|  | ac0f3b1263 | ||
|  | 1c4182687e | ||
|  | f216a35f36 | ||
|  | 6c530e32f4 | ||
|  | 418839044e | ||
|  | fbef2cc80f | ||
|  | ce0236cfbd | ||
|  | 9d8bf2d125 | ||
|  | f9a716325f | ||
|  | 7dae901d2d | ||
|  | f8c9eddb2b | ||
|  | 483c76e140 | ||
|  | 479eb12108 | ||
|  | 42119fa356 | ||
|  | 26b78f4d3c | ||
|  | f33a984d51 | ||
|  | fa5912a17b | ||
|  | 124fe7fb1b | ||
|  | d357e3d9d2 | ||
|  | 5b9d313e3f | ||
|  | 8cd05ab65a | ||
|  | 9c132c7f64 | ||
|  | 0971f1bed2 | ||
|  | b645000e1a | ||
|  | e35f29ded3 | ||
|  | 1a3de8dbec | ||
|  | 9e04c683fc | ||
|  | 5672ee54d5 | ||
|  | 36af599417 | ||
|  | aef553fdca | ||
|  | 78a4b8d205 | ||
|  | a3abb29292 | ||
|  | 178ac111bc | ||
|  | 6054d883d6 | ||
|  | 5118dc5975 | ||
|  | 45e66b7beb | ||
|  | 65903a8b08 | ||
|  | fc13d93726 | ||
|  | 3478881130 | ||
|  | d2e064a73e | ||
|  | 3894c78764 | ||
|  | 0aff637e92 | ||
|  | 5f758366c0 | ||
|  | 3f9286b721 | ||
|  | 3b69595068 | ||
|  | 5a7733b0b7 | ||
|  | 770a63792b | ||
|  | b30f4dfbda | ||
|  | 8e4e86afa5 | ||
|  | 76eb98d51c | ||
|  | d426d9fba8 | ||
|  | 7bca3892cb | ||
|  | 03cf077ac9 | ||
|  | 7b35d0c44c | ||
|  | 61c7bbd236 | ||
|  | ca8c0fab95 | ||
|  | f2564d88fe | ||
|  | b1fe60cd35 | ||
|  | a2554a334a | ||
|  | c5fa6c86d0 | ||
|  | 5bc8f026dd | ||
|  | 465bee1da8 | ||
|  | 6a23082b4e | ||
|  | 82a402e99f | ||
|  | 43f35cb5e0 | ||
|  | d66e5cee00 | ||
|  | 46485de0cb | ||
|  | 42eb58179b | ||
|  | 7159a45b2b | ||
|  | ea54feff58 | ||
|  | 0a86cb7317 | ||
|  | 97a3ea5719 | ||
|  | e3542c67af | ||
|  | 9aedd5a5d6 | ||
|  | b5e51dd714 | ||
|  | d530e34232 | ||
|  | 4ad303369c | ||
|  | 4993f7ea7e | ||
|  | 8a5eb36a1c | ||
|  | 9c52681277 | ||
|  | 26e2da7279 | ||
|  | 6906046169 | ||
|  | 395071a763 | ||
|  | e88ae2264d | ||
|  | 91e7fcca47 | ||
|  | c4ce4c4b1f | ||
|  | 24fd848950 | ||
|  | 11b389f21e | ||
|  | b162b49adc | ||
|  | 40d19394b7 | ||
|  | 13e315dada | ||
|  | 6297d9a279 | ||
|  | 29136cd8a4 | ||
|  | 87a560c455 | ||
|  | 297a3646c2 | ||
|  | cdaec3808e | ||
|  | 2ddb16a95f | ||
|  | f9f3a5ecde | ||
|  | be3c771796 | ||
|  | 192cca60ae | ||
|  | 4fa953f20d | ||
|  | 468866b816 | ||
|  | e2cd0f4fb4 | ||
|  | cbc95538ed | ||
|  | f9bee751be | ||
|  | 6e2bb3ec70 | ||
|  | 6a86dec619 | ||
|  | 3d2acaa308 | ||
|  | 5917af812e | ||
|  | b03c38057b | ||
|  | dbe5c58f2a | ||
|  | d383c625e2 | ||
|  | 4522b69c6c | ||
|  | 23335f6273 | ||
|  | 34bb4d02e0 | ||
|  | 6ee143a0a4 | ||
|  | 4bbeb8b173 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -4,6 +4,7 @@ | |||||||
| /config-host.* | /config-host.* | ||||||
| /config-target.* | /config-target.* | ||||||
| /config.status | /config.status | ||||||
|  | /config-temp | ||||||
| /trace/generated-tracers.h | /trace/generated-tracers.h | ||||||
| /trace/generated-tracers.c | /trace/generated-tracers.c | ||||||
| /trace/generated-tracers-dtrace.h | /trace/generated-tracers-dtrace.h | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								MAINTAINERS
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								MAINTAINERS
									
									
									
									
									
								
							| @@ -243,8 +243,8 @@ S: Maintained | |||||||
| F: hw/*/exynos* | F: hw/*/exynos* | ||||||
|  |  | ||||||
| Calxeda Highbank | Calxeda Highbank | ||||||
| M: Mark Langsdorf <mark.langsdorf@calxeda.com> | M: Rob Herring <robh@kernel.org> | ||||||
| S: Supported | S: Maintained | ||||||
| F: hw/arm/highbank.c | F: hw/arm/highbank.c | ||||||
| F: hw/net/xgmac.c | F: hw/net/xgmac.c | ||||||
|  |  | ||||||
| @@ -659,6 +659,12 @@ S: Supported | |||||||
| F: hw/block/nvme* | F: hw/block/nvme* | ||||||
| F: tests/nvme-test.c | F: tests/nvme-test.c | ||||||
|  |  | ||||||
|  | megasas | ||||||
|  | M: Hannes Reinecke <hare@suse.de> | ||||||
|  | S: Supported | ||||||
|  | F: hw/scsi/megasas.c | ||||||
|  | F: hw/scsi/mfi.h | ||||||
|  |  | ||||||
| Xilinx EDK | Xilinx EDK | ||||||
| M: Peter Crosthwaite <peter.crosthwaite@xilinx.com> | M: Peter Crosthwaite <peter.crosthwaite@xilinx.com> | ||||||
| M: Edgar E. Iglesias <edgar.iglesias@gmail.com> | M: Edgar E. Iglesias <edgar.iglesias@gmail.com> | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								arch_init.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								arch_init.c
									
									
									
									
									
								
							| @@ -975,12 +975,12 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) | |||||||
|     xh_len = qemu_get_be16(f); |     xh_len = qemu_get_be16(f); | ||||||
|  |  | ||||||
|     if (xh_flags != ENCODING_FLAG_XBZRLE) { |     if (xh_flags != ENCODING_FLAG_XBZRLE) { | ||||||
|         fprintf(stderr, "Failed to load XBZRLE page - wrong compression!\n"); |         error_report("Failed to load XBZRLE page - wrong compression!"); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (xh_len > TARGET_PAGE_SIZE) { |     if (xh_len > TARGET_PAGE_SIZE) { | ||||||
|         fprintf(stderr, "Failed to load XBZRLE page - len overflow!\n"); |         error_report("Failed to load XBZRLE page - len overflow!"); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     /* load data and decode */ |     /* load data and decode */ | ||||||
| @@ -989,7 +989,7 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) | |||||||
|     /* decode RLE */ |     /* decode RLE */ | ||||||
|     if (xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host, |     if (xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host, | ||||||
|                              TARGET_PAGE_SIZE) == -1) { |                              TARGET_PAGE_SIZE) == -1) { | ||||||
|         fprintf(stderr, "Failed to load XBZRLE page - decode error!\n"); |         error_report("Failed to load XBZRLE page - decode error!"); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1006,7 +1006,7 @@ static inline void *host_from_stream_offset(QEMUFile *f, | |||||||
|  |  | ||||||
|     if (flags & RAM_SAVE_FLAG_CONTINUE) { |     if (flags & RAM_SAVE_FLAG_CONTINUE) { | ||||||
|         if (!block) { |         if (!block) { | ||||||
|             fprintf(stderr, "Ack, bad migration stream!\n"); |             error_report("Ack, bad migration stream!"); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1022,7 +1022,7 @@ static inline void *host_from_stream_offset(QEMUFile *f, | |||||||
|             return memory_region_get_ram_ptr(block->mr) + offset; |             return memory_region_get_ram_ptr(block->mr) + offset; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fprintf(stderr, "Can't find block %s!\n", id); |     error_report("Can't find block %s!", id); | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1075,9 +1075,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) | |||||||
|                 QTAILQ_FOREACH(block, &ram_list.blocks, next) { |                 QTAILQ_FOREACH(block, &ram_list.blocks, next) { | ||||||
|                     if (!strncmp(id, block->idstr, sizeof(id))) { |                     if (!strncmp(id, block->idstr, sizeof(id))) { | ||||||
|                         if (block->length != length) { |                         if (block->length != length) { | ||||||
|                             fprintf(stderr, |                             error_report("Length mismatch: %s: " RAM_ADDR_FMT | ||||||
|                                     "Length mismatch: %s: " RAM_ADDR_FMT |                                          " in != " RAM_ADDR_FMT, id, length, | ||||||
|                                     " in != " RAM_ADDR_FMT "\n", id, length, |  | ||||||
|                                          block->length); |                                          block->length); | ||||||
|                             ret =  -EINVAL; |                             ret =  -EINVAL; | ||||||
|                             goto done; |                             goto done; | ||||||
| @@ -1087,8 +1086,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) | |||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (!block) { |                 if (!block) { | ||||||
|                     fprintf(stderr, "Unknown ramblock \"%s\", cannot " |                     error_report("Unknown ramblock \"%s\", cannot " | ||||||
|                             "accept migration\n", id); |                                  "accept migration", id); | ||||||
|                     ret = -EINVAL; |                     ret = -EINVAL; | ||||||
|                     goto done; |                     goto done; | ||||||
|                 } |                 } | ||||||
| @@ -1243,11 +1242,10 @@ void select_soundhw(const char *optarg) | |||||||
|  |  | ||||||
|             if (!c->name) { |             if (!c->name) { | ||||||
|                 if (l > 80) { |                 if (l > 80) { | ||||||
|                     fprintf(stderr, |                     error_report("Unknown sound card name (too big to show)"); | ||||||
|                             "Unknown sound card name (too big to show)\n"); |  | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
|                     fprintf(stderr, "Unknown sound card name `%.*s'\n", |                     error_report("Unknown sound card name `%.*s'", | ||||||
|                                  (int) l, p); |                                  (int) l, p); | ||||||
|                 } |                 } | ||||||
|                 bad_card = 1; |                 bad_card = 1; | ||||||
| @@ -1271,13 +1269,13 @@ void audio_init(void) | |||||||
|         if (c->enabled) { |         if (c->enabled) { | ||||||
|             if (c->isa) { |             if (c->isa) { | ||||||
|                 if (!isa_bus) { |                 if (!isa_bus) { | ||||||
|                     fprintf(stderr, "ISA bus not available for %s\n", c->name); |                     error_report("ISA bus not available for %s", c->name); | ||||||
|                     exit(1); |                     exit(1); | ||||||
|                 } |                 } | ||||||
|                 c->init.init_isa(isa_bus); |                 c->init.init_isa(isa_bus); | ||||||
|             } else { |             } else { | ||||||
|                 if (!pci_bus) { |                 if (!pci_bus) { | ||||||
|                     fprintf(stderr, "PCI bus not available for %s\n", c->name); |                     error_report("PCI bus not available for %s", c->name); | ||||||
|                     exit(1); |                     exit(1); | ||||||
|                 } |                 } | ||||||
|                 c->init.init_pci(pci_bus); |                 c->init.init_pci(pci_bus); | ||||||
|   | |||||||
| @@ -105,7 +105,7 @@ static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate) | |||||||
|     bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ()); |     bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ()); | ||||||
|     samples = (bytes - rate->bytes_sent) >> info->shift; |     samples = (bytes - rate->bytes_sent) >> info->shift; | ||||||
|     if (samples < 0 || samples > 65536) { |     if (samples < 0 || samples > 65536) { | ||||||
|         fprintf (stderr, "Resetting rate control (%" PRId64 " samples)\n", samples); |         error_report("Resetting rate control (%" PRId64 " samples)", samples); | ||||||
|         rate_start (rate); |         rate_start (rate); | ||||||
|         samples = 0; |         samples = 0; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -63,8 +63,7 @@ static void wav_destroy (void *opaque) | |||||||
|         } |         } | ||||||
|     doclose: |     doclose: | ||||||
|         if (fclose (wav->f)) { |         if (fclose (wav->f)) { | ||||||
|             fprintf (stderr, "wav_destroy: fclose failed: %s", |             error_report("wav_destroy: fclose failed: %s", strerror(errno)); | ||||||
|                      strerror (errno)); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -59,6 +59,7 @@ typedef struct BlkMigDevState { | |||||||
|     unsigned long *aio_bitmap; |     unsigned long *aio_bitmap; | ||||||
|     int64_t completed_sectors; |     int64_t completed_sectors; | ||||||
|     BdrvDirtyBitmap *dirty_bitmap; |     BdrvDirtyBitmap *dirty_bitmap; | ||||||
|  |     Error *blocker; | ||||||
| } BlkMigDevState; | } BlkMigDevState; | ||||||
|  |  | ||||||
| typedef struct BlkMigBlock { | typedef struct BlkMigBlock { | ||||||
| @@ -361,7 +362,8 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs) | |||||||
|         bmds->completed_sectors = 0; |         bmds->completed_sectors = 0; | ||||||
|         bmds->shared_base = block_mig_state.shared_base; |         bmds->shared_base = block_mig_state.shared_base; | ||||||
|         alloc_aio_bitmap(bmds); |         alloc_aio_bitmap(bmds); | ||||||
|         bdrv_set_in_use(bs, 1); |         error_setg(&bmds->blocker, "block device is in use by migration"); | ||||||
|  |         bdrv_op_block_all(bs, bmds->blocker); | ||||||
|         bdrv_ref(bs); |         bdrv_ref(bs); | ||||||
|  |  | ||||||
|         block_mig_state.total_sector_sum += sectors; |         block_mig_state.total_sector_sum += sectors; | ||||||
| @@ -599,7 +601,8 @@ static void blk_mig_cleanup(void) | |||||||
|     blk_mig_lock(); |     blk_mig_lock(); | ||||||
|     while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) { |     while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) { | ||||||
|         QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry); |         QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry); | ||||||
|         bdrv_set_in_use(bmds->bs, 0); |         bdrv_op_unblock_all(bmds->bs, bmds->blocker); | ||||||
|  |         error_free(bmds->blocker); | ||||||
|         bdrv_unref(bmds->bs); |         bdrv_unref(bmds->bs); | ||||||
|         g_free(bmds->aio_bitmap); |         g_free(bmds->aio_bitmap); | ||||||
|         g_free(bmds); |         g_free(bmds); | ||||||
|   | |||||||
							
								
								
									
										212
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										212
									
								
								block.c
									
									
									
									
									
								
							| @@ -335,6 +335,7 @@ void bdrv_register(BlockDriver *bdrv) | |||||||
| BlockDriverState *bdrv_new(const char *device_name, Error **errp) | BlockDriverState *bdrv_new(const char *device_name, Error **errp) | ||||||
| { | { | ||||||
|     BlockDriverState *bs; |     BlockDriverState *bs; | ||||||
|  |     int i; | ||||||
|  |  | ||||||
|     if (bdrv_find(device_name)) { |     if (bdrv_find(device_name)) { | ||||||
|         error_setg(errp, "Device with id '%s' already exists", |         error_setg(errp, "Device with id '%s' already exists", | ||||||
| @@ -353,6 +354,9 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp) | |||||||
|     if (device_name[0] != '\0') { |     if (device_name[0] != '\0') { | ||||||
|         QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list); |         QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list); | ||||||
|     } |     } | ||||||
|  |     for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) { | ||||||
|  |         QLIST_INIT(&bs->op_blockers[i]); | ||||||
|  |     } | ||||||
|     bdrv_iostatus_disable(bs); |     bdrv_iostatus_disable(bs); | ||||||
|     notifier_list_init(&bs->close_notifiers); |     notifier_list_init(&bs->close_notifiers); | ||||||
|     notifier_with_return_list_init(&bs->before_write_notifiers); |     notifier_with_return_list_init(&bs->before_write_notifiers); | ||||||
| @@ -1090,6 +1094,37 @@ fail: | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd) | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     if (bs->backing_hd) { | ||||||
|  |         assert(bs->backing_blocker); | ||||||
|  |         bdrv_op_unblock_all(bs->backing_hd, bs->backing_blocker); | ||||||
|  |     } else if (backing_hd) { | ||||||
|  |         error_setg(&bs->backing_blocker, | ||||||
|  |                    "device is used as backing hd of '%s'", | ||||||
|  |                    bs->device_name); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bs->backing_hd = backing_hd; | ||||||
|  |     if (!backing_hd) { | ||||||
|  |         error_free(bs->backing_blocker); | ||||||
|  |         bs->backing_blocker = NULL; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |     bs->open_flags &= ~BDRV_O_NO_BACKING; | ||||||
|  |     pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_hd->filename); | ||||||
|  |     pstrcpy(bs->backing_format, sizeof(bs->backing_format), | ||||||
|  |             backing_hd->drv ? backing_hd->drv->format_name : ""); | ||||||
|  |  | ||||||
|  |     bdrv_op_block_all(bs->backing_hd, bs->backing_blocker); | ||||||
|  |     /* Otherwise we won't be able to commit due to check in bdrv_commit */ | ||||||
|  |     bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT, | ||||||
|  |                     bs->backing_blocker); | ||||||
|  | out: | ||||||
|  |     bdrv_refresh_limits(bs); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Opens the backing file for a BlockDriverState if not yet open |  * Opens the backing file for a BlockDriverState if not yet open | ||||||
|  * |  * | ||||||
| @@ -1103,6 +1138,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) | |||||||
|     char *backing_filename = g_malloc0(PATH_MAX); |     char *backing_filename = g_malloc0(PATH_MAX); | ||||||
|     int ret = 0; |     int ret = 0; | ||||||
|     BlockDriver *back_drv = NULL; |     BlockDriver *back_drv = NULL; | ||||||
|  |     BlockDriverState *backing_hd; | ||||||
|     Error *local_err = NULL; |     Error *local_err = NULL; | ||||||
|  |  | ||||||
|     if (bs->backing_hd != NULL) { |     if (bs->backing_hd != NULL) { | ||||||
| @@ -1125,30 +1161,26 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) | |||||||
|         bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX); |         bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     backing_hd = bdrv_new("", errp); | ||||||
|  |  | ||||||
|     if (bs->backing_format[0] != '\0') { |     if (bs->backing_format[0] != '\0') { | ||||||
|         back_drv = bdrv_find_format(bs->backing_format); |         back_drv = bdrv_find_format(bs->backing_format); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     assert(bs->backing_hd == NULL); |     assert(bs->backing_hd == NULL); | ||||||
|     ret = bdrv_open(&bs->backing_hd, |     ret = bdrv_open(&backing_hd, | ||||||
|                     *backing_filename ? backing_filename : NULL, NULL, options, |                     *backing_filename ? backing_filename : NULL, NULL, options, | ||||||
|                     bdrv_backing_flags(bs->open_flags), back_drv, &local_err); |                     bdrv_backing_flags(bs->open_flags), back_drv, &local_err); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         bs->backing_hd = NULL; |         bdrv_unref(backing_hd); | ||||||
|  |         backing_hd = NULL; | ||||||
|         bs->open_flags |= BDRV_O_NO_BACKING; |         bs->open_flags |= BDRV_O_NO_BACKING; | ||||||
|         error_setg(errp, "Could not open backing file: %s", |         error_setg(errp, "Could not open backing file: %s", | ||||||
|                    error_get_pretty(local_err)); |                    error_get_pretty(local_err)); | ||||||
|         error_free(local_err); |         error_free(local_err); | ||||||
|         goto free_exit; |         goto free_exit; | ||||||
|     } |     } | ||||||
|  |     bdrv_set_backing_hd(bs, backing_hd); | ||||||
|     if (bs->backing_hd->file) { |  | ||||||
|         pstrcpy(bs->backing_file, sizeof(bs->backing_file), |  | ||||||
|                 bs->backing_hd->file->filename); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* Recalculate the BlockLimits with the backing file */ |  | ||||||
|     bdrv_refresh_limits(bs); |  | ||||||
|  |  | ||||||
| free_exit: | free_exit: | ||||||
|     g_free(backing_filename); |     g_free(backing_filename); | ||||||
| @@ -1274,6 +1306,33 @@ out: | |||||||
|     g_free(tmp_filename); |     g_free(tmp_filename); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static QDict *parse_json_filename(const char *filename, Error **errp) | ||||||
|  | { | ||||||
|  |     QObject *options_obj; | ||||||
|  |     QDict *options; | ||||||
|  |     int ret; | ||||||
|  |  | ||||||
|  |     ret = strstart(filename, "json:", &filename); | ||||||
|  |     assert(ret); | ||||||
|  |  | ||||||
|  |     options_obj = qobject_from_json(filename); | ||||||
|  |     if (!options_obj) { | ||||||
|  |         error_setg(errp, "Could not parse the JSON options"); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (qobject_type(options_obj) != QTYPE_QDICT) { | ||||||
|  |         qobject_decref(options_obj); | ||||||
|  |         error_setg(errp, "Invalid JSON object given"); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     options = qobject_to_qdict(options_obj); | ||||||
|  |     qdict_flatten(options); | ||||||
|  |  | ||||||
|  |     return options; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Opens a disk image (raw, qcow2, vmdk, ...) |  * Opens a disk image (raw, qcow2, vmdk, ...) | ||||||
|  * |  * | ||||||
| @@ -1337,6 +1396,20 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, | |||||||
|         options = qdict_new(); |         options = qdict_new(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (filename && g_str_has_prefix(filename, "json:")) { | ||||||
|  |         QDict *json_options = parse_json_filename(filename, &local_err); | ||||||
|  |         if (local_err) { | ||||||
|  |             ret = -EINVAL; | ||||||
|  |             goto fail; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* Options given in the filename have lower priority than options | ||||||
|  |          * specified directly */ | ||||||
|  |         qdict_join(options, json_options, false); | ||||||
|  |         QDECREF(json_options); | ||||||
|  |         filename = NULL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     bs->options = options; |     bs->options = options; | ||||||
|     options = qdict_clone_shallow(options); |     options = qdict_clone_shallow(options); | ||||||
|  |  | ||||||
| @@ -1743,8 +1816,9 @@ void bdrv_close(BlockDriverState *bs) | |||||||
|  |  | ||||||
|     if (bs->drv) { |     if (bs->drv) { | ||||||
|         if (bs->backing_hd) { |         if (bs->backing_hd) { | ||||||
|             bdrv_unref(bs->backing_hd); |             BlockDriverState *backing_hd = bs->backing_hd; | ||||||
|             bs->backing_hd = NULL; |             bdrv_set_backing_hd(bs, NULL); | ||||||
|  |             bdrv_unref(backing_hd); | ||||||
|         } |         } | ||||||
|         bs->drv->bdrv_close(bs); |         bs->drv->bdrv_close(bs); | ||||||
|         g_free(bs->opaque); |         g_free(bs->opaque); | ||||||
| @@ -1904,13 +1978,14 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, | |||||||
|     bs_dest->refcnt             = bs_src->refcnt; |     bs_dest->refcnt             = bs_src->refcnt; | ||||||
|  |  | ||||||
|     /* job */ |     /* job */ | ||||||
|     bs_dest->in_use             = bs_src->in_use; |  | ||||||
|     bs_dest->job                = bs_src->job; |     bs_dest->job                = bs_src->job; | ||||||
|  |  | ||||||
|     /* keep the same entry in bdrv_states */ |     /* keep the same entry in bdrv_states */ | ||||||
|     pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name), |     pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name), | ||||||
|             bs_src->device_name); |             bs_src->device_name); | ||||||
|     bs_dest->device_list = bs_src->device_list; |     bs_dest->device_list = bs_src->device_list; | ||||||
|  |     memcpy(bs_dest->op_blockers, bs_src->op_blockers, | ||||||
|  |            sizeof(bs_dest->op_blockers)); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -1945,7 +2020,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) | |||||||
|     assert(QLIST_EMPTY(&bs_new->dirty_bitmaps)); |     assert(QLIST_EMPTY(&bs_new->dirty_bitmaps)); | ||||||
|     assert(bs_new->job == NULL); |     assert(bs_new->job == NULL); | ||||||
|     assert(bs_new->dev == NULL); |     assert(bs_new->dev == NULL); | ||||||
|     assert(bs_new->in_use == 0); |  | ||||||
|     assert(bs_new->io_limits_enabled == false); |     assert(bs_new->io_limits_enabled == false); | ||||||
|     assert(!throttle_have_timer(&bs_new->throttle_state)); |     assert(!throttle_have_timer(&bs_new->throttle_state)); | ||||||
|  |  | ||||||
| @@ -1964,7 +2038,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) | |||||||
|     /* Check a few fields that should remain attached to the device */ |     /* Check a few fields that should remain attached to the device */ | ||||||
|     assert(bs_new->dev == NULL); |     assert(bs_new->dev == NULL); | ||||||
|     assert(bs_new->job == NULL); |     assert(bs_new->job == NULL); | ||||||
|     assert(bs_new->in_use == 0); |  | ||||||
|     assert(bs_new->io_limits_enabled == false); |     assert(bs_new->io_limits_enabled == false); | ||||||
|     assert(!throttle_have_timer(&bs_new->throttle_state)); |     assert(!throttle_have_timer(&bs_new->throttle_state)); | ||||||
|  |  | ||||||
| @@ -1997,19 +2070,14 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top) | |||||||
|  |  | ||||||
|     /* The contents of 'tmp' will become bs_top, as we are |     /* The contents of 'tmp' will become bs_top, as we are | ||||||
|      * swapping bs_new and bs_top contents. */ |      * swapping bs_new and bs_top contents. */ | ||||||
|     bs_top->backing_hd = bs_new; |     bdrv_set_backing_hd(bs_top, bs_new); | ||||||
|     bs_top->open_flags &= ~BDRV_O_NO_BACKING; |  | ||||||
|     pstrcpy(bs_top->backing_file, sizeof(bs_top->backing_file), |  | ||||||
|             bs_new->filename); |  | ||||||
|     pstrcpy(bs_top->backing_format, sizeof(bs_top->backing_format), |  | ||||||
|             bs_new->drv ? bs_new->drv->format_name : ""); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void bdrv_delete(BlockDriverState *bs) | static void bdrv_delete(BlockDriverState *bs) | ||||||
| { | { | ||||||
|     assert(!bs->dev); |     assert(!bs->dev); | ||||||
|     assert(!bs->job); |     assert(!bs->job); | ||||||
|     assert(!bs->in_use); |     assert(bdrv_op_blocker_is_empty(bs)); | ||||||
|     assert(!bs->refcnt); |     assert(!bs->refcnt); | ||||||
|     assert(QLIST_EMPTY(&bs->dirty_bitmaps)); |     assert(QLIST_EMPTY(&bs->dirty_bitmaps)); | ||||||
|  |  | ||||||
| @@ -2191,7 +2259,8 @@ int bdrv_commit(BlockDriverState *bs) | |||||||
|         return -ENOTSUP; |         return -ENOTSUP; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) { |     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT, NULL) || | ||||||
|  |         bdrv_op_is_blocked(bs->backing_hd, BLOCK_OP_TYPE_COMMIT, NULL)) { | ||||||
|         return -EBUSY; |         return -EBUSY; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2595,13 +2664,11 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top, | |||||||
|     if (ret) { |     if (ret) { | ||||||
|         goto exit; |         goto exit; | ||||||
|     } |     } | ||||||
|     new_top_bs->backing_hd = base_bs; |     bdrv_set_backing_hd(new_top_bs, base_bs); | ||||||
|  |  | ||||||
|     bdrv_refresh_limits(new_top_bs); |  | ||||||
|  |  | ||||||
|     QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) { |     QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) { | ||||||
|         /* so that bdrv_close() does not recursively close the chain */ |         /* so that bdrv_close() does not recursively close the chain */ | ||||||
|         intermediate_state->bs->backing_hd = NULL; |         bdrv_set_backing_hd(intermediate_state->bs, NULL); | ||||||
|         bdrv_unref(intermediate_state->bs); |         bdrv_unref(intermediate_state->bs); | ||||||
|     } |     } | ||||||
|     ret = 0; |     ret = 0; | ||||||
| @@ -3248,6 +3315,15 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, | |||||||
|  |  | ||||||
|     ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req); |     ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req); | ||||||
|  |  | ||||||
|  |     if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF && | ||||||
|  |         !(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_write_zeroes && | ||||||
|  |         qemu_iovec_is_zero(qiov)) { | ||||||
|  |         flags |= BDRV_REQ_ZERO_WRITE; | ||||||
|  |         if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) { | ||||||
|  |             flags |= BDRV_REQ_MAY_UNMAP; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         /* Do nothing, write notifier decided to fail this request */ |         /* Do nothing, write notifier decided to fail this request */ | ||||||
|     } else if (flags & BDRV_REQ_ZERO_WRITE) { |     } else if (flags & BDRV_REQ_ZERO_WRITE) { | ||||||
| @@ -3444,8 +3520,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset) | |||||||
|         return -ENOTSUP; |         return -ENOTSUP; | ||||||
|     if (bs->read_only) |     if (bs->read_only) | ||||||
|         return -EACCES; |         return -EACCES; | ||||||
|     if (bdrv_in_use(bs)) |     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) { | ||||||
|         return -EBUSY; |         return -EBUSY; | ||||||
|  |     } | ||||||
|     ret = drv->bdrv_truncate(bs, offset); |     ret = drv->bdrv_truncate(bs, offset); | ||||||
|     if (ret == 0) { |     if (ret == 0) { | ||||||
|         ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); |         ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); | ||||||
| @@ -3864,7 +3941,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, | |||||||
|  |  | ||||||
|     if (!bs->drv->bdrv_co_get_block_status) { |     if (!bs->drv->bdrv_co_get_block_status) { | ||||||
|         *pnum = nb_sectors; |         *pnum = nb_sectors; | ||||||
|         ret = BDRV_BLOCK_DATA; |         ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED; | ||||||
|         if (bs->drv->protocol_name) { |         if (bs->drv->protocol_name) { | ||||||
|             ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE); |             ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE); | ||||||
|         } |         } | ||||||
| @@ -3883,6 +3960,10 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, | |||||||
|                                      *pnum, pnum); |                                      *pnum, pnum); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) { | ||||||
|  |         ret |= BDRV_BLOCK_ALLOCATED; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (!(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO)) { |     if (!(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO)) { | ||||||
|         if (bdrv_unallocated_blocks_are_zero(bs)) { |         if (bdrv_unallocated_blocks_are_zero(bs)) { | ||||||
|             ret |= BDRV_BLOCK_ZERO; |             ret |= BDRV_BLOCK_ZERO; | ||||||
| @@ -3959,9 +4040,7 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, | |||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         return ret; |         return ret; | ||||||
|     } |     } | ||||||
|     return |     return (ret & BDRV_BLOCK_ALLOCATED); | ||||||
|         (ret & BDRV_BLOCK_DATA) || |  | ||||||
|         ((ret & BDRV_BLOCK_ZERO) && !bdrv_has_zero_init(bs)); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -5273,15 +5352,74 @@ void bdrv_unref(BlockDriverState *bs) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void bdrv_set_in_use(BlockDriverState *bs, int in_use) | struct BdrvOpBlocker { | ||||||
|  |     Error *reason; | ||||||
|  |     QLIST_ENTRY(BdrvOpBlocker) list; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp) | ||||||
| { | { | ||||||
|     assert(bs->in_use != in_use); |     BdrvOpBlocker *blocker; | ||||||
|     bs->in_use = in_use; |     assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX); | ||||||
|  |     if (!QLIST_EMPTY(&bs->op_blockers[op])) { | ||||||
|  |         blocker = QLIST_FIRST(&bs->op_blockers[op]); | ||||||
|  |         if (errp) { | ||||||
|  |             error_setg(errp, "Device '%s' is busy: %s", | ||||||
|  |                        bs->device_name, error_get_pretty(blocker->reason)); | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| int bdrv_in_use(BlockDriverState *bs) | void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason) | ||||||
| { | { | ||||||
|     return bs->in_use; |     BdrvOpBlocker *blocker; | ||||||
|  |     assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX); | ||||||
|  |  | ||||||
|  |     blocker = g_malloc0(sizeof(BdrvOpBlocker)); | ||||||
|  |     blocker->reason = reason; | ||||||
|  |     QLIST_INSERT_HEAD(&bs->op_blockers[op], blocker, list); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason) | ||||||
|  | { | ||||||
|  |     BdrvOpBlocker *blocker, *next; | ||||||
|  |     assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX); | ||||||
|  |     QLIST_FOREACH_SAFE(blocker, &bs->op_blockers[op], list, next) { | ||||||
|  |         if (blocker->reason == reason) { | ||||||
|  |             QLIST_REMOVE(blocker, list); | ||||||
|  |             g_free(blocker); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void bdrv_op_block_all(BlockDriverState *bs, Error *reason) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |     for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) { | ||||||
|  |         bdrv_op_block(bs, i, reason); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |     for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) { | ||||||
|  |         bdrv_op_unblock(bs, i, reason); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool bdrv_op_blocker_is_empty(BlockDriverState *bs) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |  | ||||||
|  |     for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) { | ||||||
|  |         if (!QLIST_EMPTY(&bs->op_blockers[i])) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void bdrv_iostatus_enable(BlockDriverState *bs) | void bdrv_iostatus_enable(BlockDriverState *bs) | ||||||
|   | |||||||
							
								
								
									
										79
									
								
								block/curl.c
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								block/curl.c
									
									
									
									
									
								
							| @@ -23,6 +23,7 @@ | |||||||
|  */ |  */ | ||||||
| #include "qemu-common.h" | #include "qemu-common.h" | ||||||
| #include "block/block_int.h" | #include "block/block_int.h" | ||||||
|  | #include "qapi/qmp/qbool.h" | ||||||
| #include <curl/curl.h> | #include <curl/curl.h> | ||||||
|  |  | ||||||
| // #define DEBUG | // #define DEBUG | ||||||
| @@ -37,6 +38,21 @@ | |||||||
| #if LIBCURL_VERSION_NUM >= 0x071000 | #if LIBCURL_VERSION_NUM >= 0x071000 | ||||||
| /* The multi interface timer callback was introduced in 7.16.0 */ | /* The multi interface timer callback was introduced in 7.16.0 */ | ||||||
| #define NEED_CURL_TIMER_CALLBACK | #define NEED_CURL_TIMER_CALLBACK | ||||||
|  | #define HAVE_SOCKET_ACTION | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef HAVE_SOCKET_ACTION | ||||||
|  | /* If curl_multi_socket_action isn't available, define it statically here in | ||||||
|  |  * terms of curl_multi_socket. Note that ev_bitmask will be ignored, which is | ||||||
|  |  * less efficient but still safe. */ | ||||||
|  | static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, | ||||||
|  |                                             curl_socket_t sockfd, | ||||||
|  |                                             int ev_bitmask, | ||||||
|  |                                             int *running_handles) | ||||||
|  | { | ||||||
|  |     return curl_multi_socket(multi_handle, sockfd, running_handles); | ||||||
|  | } | ||||||
|  | #define curl_multi_socket_action __curl_multi_socket_action | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ | #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ | ||||||
| @@ -46,12 +62,16 @@ | |||||||
| #define CURL_NUM_STATES 8 | #define CURL_NUM_STATES 8 | ||||||
| #define CURL_NUM_ACB    8 | #define CURL_NUM_ACB    8 | ||||||
| #define SECTOR_SIZE     512 | #define SECTOR_SIZE     512 | ||||||
| #define READ_AHEAD_SIZE (256 * 1024) | #define READ_AHEAD_DEFAULT (256 * 1024) | ||||||
|  |  | ||||||
| #define FIND_RET_NONE   0 | #define FIND_RET_NONE   0 | ||||||
| #define FIND_RET_OK     1 | #define FIND_RET_OK     1 | ||||||
| #define FIND_RET_WAIT   2 | #define FIND_RET_WAIT   2 | ||||||
|  |  | ||||||
|  | #define CURL_BLOCK_OPT_URL       "url" | ||||||
|  | #define CURL_BLOCK_OPT_READAHEAD "readahead" | ||||||
|  | #define CURL_BLOCK_OPT_SSLVERIFY "sslverify" | ||||||
|  |  | ||||||
| struct BDRVCURLState; | struct BDRVCURLState; | ||||||
|  |  | ||||||
| typedef struct CURLAIOCB { | typedef struct CURLAIOCB { | ||||||
| @@ -88,6 +108,7 @@ typedef struct BDRVCURLState { | |||||||
|     CURLState states[CURL_NUM_STATES]; |     CURLState states[CURL_NUM_STATES]; | ||||||
|     char *url; |     char *url; | ||||||
|     size_t readahead_size; |     size_t readahead_size; | ||||||
|  |     bool sslverify; | ||||||
|     bool accept_range; |     bool accept_range; | ||||||
| } BDRVCURLState; | } BDRVCURLState; | ||||||
|  |  | ||||||
| @@ -354,6 +375,8 @@ static CURLState *curl_init_state(BDRVCURLState *s) | |||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|         curl_easy_setopt(state->curl, CURLOPT_URL, s->url); |         curl_easy_setopt(state->curl, CURLOPT_URL, s->url); | ||||||
|  |         curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER, | ||||||
|  |                          (long) s->sslverify); | ||||||
|         curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5); |         curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5); | ||||||
|         curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, |         curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, | ||||||
|                          (void *)curl_read_cb); |                          (void *)curl_read_cb); | ||||||
| @@ -396,43 +419,7 @@ static void curl_clean_state(CURLState *s) | |||||||
| static void curl_parse_filename(const char *filename, QDict *options, | static void curl_parse_filename(const char *filename, QDict *options, | ||||||
|                                 Error **errp) |                                 Error **errp) | ||||||
| { | { | ||||||
|  |     qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename)); | ||||||
|     #define RA_OPTSTR ":readahead=" |  | ||||||
|     char *file; |  | ||||||
|     char *ra; |  | ||||||
|     const char *ra_val; |  | ||||||
|     int parse_state = 0; |  | ||||||
|  |  | ||||||
|     file = g_strdup(filename); |  | ||||||
|  |  | ||||||
|     /* Parse a trailing ":readahead=#:" param, if present. */ |  | ||||||
|     ra = file + strlen(file) - 1; |  | ||||||
|     while (ra >= file) { |  | ||||||
|         if (parse_state == 0) { |  | ||||||
|             if (*ra == ':') { |  | ||||||
|                 parse_state++; |  | ||||||
|             } else { |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } else if (parse_state == 1) { |  | ||||||
|             if (*ra > '9' || *ra < '0') { |  | ||||||
|                 char *opt_start = ra - strlen(RA_OPTSTR) + 1; |  | ||||||
|                 if (opt_start > file && |  | ||||||
|                     strncmp(opt_start, RA_OPTSTR, strlen(RA_OPTSTR)) == 0) { |  | ||||||
|                     ra_val = ra + 1; |  | ||||||
|                     ra -= strlen(RA_OPTSTR) - 1; |  | ||||||
|                     *ra = '\0'; |  | ||||||
|                     qdict_put(options, "readahead", qstring_from_str(ra_val)); |  | ||||||
|                 } |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         ra--; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     qdict_put(options, "url", qstring_from_str(file)); |  | ||||||
|  |  | ||||||
|     g_free(file); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static QemuOptsList runtime_opts = { | static QemuOptsList runtime_opts = { | ||||||
| @@ -440,15 +427,20 @@ static QemuOptsList runtime_opts = { | |||||||
|     .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), |     .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), | ||||||
|     .desc = { |     .desc = { | ||||||
|         { |         { | ||||||
|             .name = "url", |             .name = CURL_BLOCK_OPT_URL, | ||||||
|             .type = QEMU_OPT_STRING, |             .type = QEMU_OPT_STRING, | ||||||
|             .help = "URL to open", |             .help = "URL to open", | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             .name = "readahead", |             .name = CURL_BLOCK_OPT_READAHEAD, | ||||||
|             .type = QEMU_OPT_SIZE, |             .type = QEMU_OPT_SIZE, | ||||||
|             .help = "Readahead size", |             .help = "Readahead size", | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             .name = CURL_BLOCK_OPT_SSLVERIFY, | ||||||
|  |             .type = QEMU_OPT_BOOL, | ||||||
|  |             .help = "Verify SSL certificate" | ||||||
|  |         }, | ||||||
|         { /* end of list */ } |         { /* end of list */ } | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| @@ -477,14 +469,17 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|         goto out_noclean; |         goto out_noclean; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     s->readahead_size = qemu_opt_get_size(opts, "readahead", READ_AHEAD_SIZE); |     s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD, | ||||||
|  |                                           READ_AHEAD_DEFAULT); | ||||||
|     if ((s->readahead_size & 0x1ff) != 0) { |     if ((s->readahead_size & 0x1ff) != 0) { | ||||||
|         error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512", |         error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512", | ||||||
|                    s->readahead_size); |                    s->readahead_size); | ||||||
|         goto out_noclean; |         goto out_noclean; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     file = qemu_opt_get(opts, "url"); |     s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); | ||||||
|  |  | ||||||
|  |     file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); | ||||||
|     if (file == NULL) { |     if (file == NULL) { | ||||||
|         error_setg(errp, "curl block driver requires an 'url' option"); |         error_setg(errp, "curl block driver requires an 'url' option"); | ||||||
|         goto out_noclean; |         goto out_noclean; | ||||||
|   | |||||||
							
								
								
									
										317
									
								
								block/iscsi.c
									
									
									
									
									
								
							
							
						
						
									
										317
									
								
								block/iscsi.c
									
									
									
									
									
								
							| @@ -30,6 +30,8 @@ | |||||||
| #include "qemu-common.h" | #include "qemu-common.h" | ||||||
| #include "qemu/config-file.h" | #include "qemu/config-file.h" | ||||||
| #include "qemu/error-report.h" | #include "qemu/error-report.h" | ||||||
|  | #include "qemu/bitops.h" | ||||||
|  | #include "qemu/bitmap.h" | ||||||
| #include "block/block_int.h" | #include "block/block_int.h" | ||||||
| #include "trace.h" | #include "trace.h" | ||||||
| #include "block/scsi.h" | #include "block/scsi.h" | ||||||
| @@ -59,6 +61,8 @@ typedef struct IscsiLun { | |||||||
|     struct scsi_inquiry_logical_block_provisioning lbp; |     struct scsi_inquiry_logical_block_provisioning lbp; | ||||||
|     struct scsi_inquiry_block_limits bl; |     struct scsi_inquiry_block_limits bl; | ||||||
|     unsigned char *zeroblock; |     unsigned char *zeroblock; | ||||||
|  |     unsigned long *allocationmap; | ||||||
|  |     int cluster_sectors; | ||||||
| } IscsiLun; | } IscsiLun; | ||||||
|  |  | ||||||
| typedef struct IscsiTask { | typedef struct IscsiTask { | ||||||
| @@ -92,6 +96,15 @@ typedef struct IscsiAIOCB { | |||||||
| #define MAX_NOP_FAILURES 3 | #define MAX_NOP_FAILURES 3 | ||||||
| #define ISCSI_CMD_RETRIES 5 | #define ISCSI_CMD_RETRIES 5 | ||||||
|  |  | ||||||
|  | /* this threshhold is a trade-off knob to choose between | ||||||
|  |  * the potential additional overhead of an extra GET_LBA_STATUS request | ||||||
|  |  * vs. unnecessarily reading a lot of zero sectors over the wire. | ||||||
|  |  * If a read request is greater or equal than ISCSI_CHECKALLOC_THRES | ||||||
|  |  * sectors we check the allocation status of the area covered by the | ||||||
|  |  * request first if the allocationmap indicates that the area might be | ||||||
|  |  * unallocated. */ | ||||||
|  | #define ISCSI_CHECKALLOC_THRES 64 | ||||||
|  |  | ||||||
| static void | static void | ||||||
| iscsi_bh_cb(void *p) | iscsi_bh_cb(void *p) | ||||||
| { | { | ||||||
| @@ -273,6 +286,32 @@ static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors, | |||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void iscsi_allocationmap_set(IscsiLun *iscsilun, int64_t sector_num, | ||||||
|  |                                     int nb_sectors) | ||||||
|  | { | ||||||
|  |     if (iscsilun->allocationmap == NULL) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     bitmap_set(iscsilun->allocationmap, | ||||||
|  |                sector_num / iscsilun->cluster_sectors, | ||||||
|  |                DIV_ROUND_UP(nb_sectors, iscsilun->cluster_sectors)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void iscsi_allocationmap_clear(IscsiLun *iscsilun, int64_t sector_num, | ||||||
|  |                                       int nb_sectors) | ||||||
|  | { | ||||||
|  |     int64_t cluster_num, nb_clusters; | ||||||
|  |     if (iscsilun->allocationmap == NULL) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     cluster_num = DIV_ROUND_UP(sector_num, iscsilun->cluster_sectors); | ||||||
|  |     nb_clusters = (sector_num + nb_sectors) / iscsilun->cluster_sectors | ||||||
|  |                   - cluster_num; | ||||||
|  |     if (nb_clusters > 0) { | ||||||
|  |         bitmap_clear(iscsilun->allocationmap, cluster_num, nb_clusters); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| static int coroutine_fn iscsi_co_writev(BlockDriverState *bs, | static int coroutine_fn iscsi_co_writev(BlockDriverState *bs, | ||||||
|                                         int64_t sector_num, int nb_sectors, |                                         int64_t sector_num, int nb_sectors, | ||||||
|                                         QEMUIOVector *iov) |                                         QEMUIOVector *iov) | ||||||
| @@ -336,9 +375,125 @@ retry: | |||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     iscsi_allocationmap_set(iscsilun, sector_num, nb_sectors); | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if defined(LIBISCSI_FEATURE_IOVECTOR) | ||||||
|  | static bool iscsi_allocationmap_is_allocated(IscsiLun *iscsilun, | ||||||
|  |                                              int64_t sector_num, int nb_sectors) | ||||||
|  | { | ||||||
|  |     unsigned long size; | ||||||
|  |     if (iscsilun->allocationmap == NULL) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors); | ||||||
|  |     return !(find_next_bit(iscsilun->allocationmap, size, | ||||||
|  |                            sector_num / iscsilun->cluster_sectors) == size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs, | ||||||
|  |                                                   int64_t sector_num, | ||||||
|  |                                                   int nb_sectors, int *pnum) | ||||||
|  | { | ||||||
|  |     IscsiLun *iscsilun = bs->opaque; | ||||||
|  |     struct scsi_get_lba_status *lbas = NULL; | ||||||
|  |     struct scsi_lba_status_descriptor *lbasd = NULL; | ||||||
|  |     struct IscsiTask iTask; | ||||||
|  |     int64_t ret; | ||||||
|  |  | ||||||
|  |     iscsi_co_init_iscsitask(iscsilun, &iTask); | ||||||
|  |  | ||||||
|  |     if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) { | ||||||
|  |         ret = -EINVAL; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* default to all sectors allocated */ | ||||||
|  |     ret = BDRV_BLOCK_DATA; | ||||||
|  |     ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID; | ||||||
|  |     *pnum = nb_sectors; | ||||||
|  |  | ||||||
|  |     /* LUN does not support logical block provisioning */ | ||||||
|  |     if (iscsilun->lbpme == 0) { | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | retry: | ||||||
|  |     if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun, | ||||||
|  |                                   sector_qemu2lun(sector_num, iscsilun), | ||||||
|  |                                   8 + 16, iscsi_co_generic_cb, | ||||||
|  |                                   &iTask) == NULL) { | ||||||
|  |         ret = -ENOMEM; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     while (!iTask.complete) { | ||||||
|  |         iscsi_set_events(iscsilun); | ||||||
|  |         qemu_coroutine_yield(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (iTask.do_retry) { | ||||||
|  |         if (iTask.task != NULL) { | ||||||
|  |             scsi_free_scsi_task(iTask.task); | ||||||
|  |             iTask.task = NULL; | ||||||
|  |         } | ||||||
|  |         iTask.complete = 0; | ||||||
|  |         goto retry; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (iTask.status != SCSI_STATUS_GOOD) { | ||||||
|  |         /* in case the get_lba_status_callout fails (i.e. | ||||||
|  |          * because the device is busy or the cmd is not | ||||||
|  |          * supported) we pretend all blocks are allocated | ||||||
|  |          * for backwards compatibility */ | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     lbas = scsi_datain_unmarshall(iTask.task); | ||||||
|  |     if (lbas == NULL) { | ||||||
|  |         ret = -EIO; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     lbasd = &lbas->descriptors[0]; | ||||||
|  |  | ||||||
|  |     if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) { | ||||||
|  |         ret = -EIO; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun); | ||||||
|  |  | ||||||
|  |     if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED || | ||||||
|  |         lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) { | ||||||
|  |         ret &= ~BDRV_BLOCK_DATA; | ||||||
|  |         if (iscsilun->lbprz) { | ||||||
|  |             ret |= BDRV_BLOCK_ZERO; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (ret & BDRV_BLOCK_ZERO) { | ||||||
|  |         iscsi_allocationmap_clear(iscsilun, sector_num, *pnum); | ||||||
|  |     } else { | ||||||
|  |         iscsi_allocationmap_set(iscsilun, sector_num, *pnum); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (*pnum > nb_sectors) { | ||||||
|  |         *pnum = nb_sectors; | ||||||
|  |     } | ||||||
|  | out: | ||||||
|  |     if (iTask.task != NULL) { | ||||||
|  |         scsi_free_scsi_task(iTask.task); | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif /* LIBISCSI_FEATURE_IOVECTOR */ | ||||||
|  |  | ||||||
|  |  | ||||||
| static int coroutine_fn iscsi_co_readv(BlockDriverState *bs, | static int coroutine_fn iscsi_co_readv(BlockDriverState *bs, | ||||||
|                                        int64_t sector_num, int nb_sectors, |                                        int64_t sector_num, int nb_sectors, | ||||||
|                                        QEMUIOVector *iov) |                                        QEMUIOVector *iov) | ||||||
| @@ -355,6 +510,22 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs, | |||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #if defined(LIBISCSI_FEATURE_IOVECTOR) | ||||||
|  |     if (iscsilun->lbprz && nb_sectors >= ISCSI_CHECKALLOC_THRES && | ||||||
|  |         !iscsi_allocationmap_is_allocated(iscsilun, sector_num, nb_sectors)) { | ||||||
|  |         int64_t ret; | ||||||
|  |         int pnum; | ||||||
|  |         ret = iscsi_co_get_block_status(bs, sector_num, INT_MAX, &pnum); | ||||||
|  |         if (ret < 0) { | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  |         if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors) { | ||||||
|  |             qemu_iovec_memset(iov, 0, 0x00, iov->size); | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     lba = sector_qemu2lun(sector_num, iscsilun); |     lba = sector_qemu2lun(sector_num, iscsilun); | ||||||
|     num_sectors = sector_qemu2lun(nb_sectors, iscsilun); |     num_sectors = sector_qemu2lun(nb_sectors, iscsilun); | ||||||
|  |  | ||||||
| @@ -643,101 +814,6 @@ iscsi_getlength(BlockDriverState *bs) | |||||||
|     return len; |     return len; | ||||||
| } | } | ||||||
|  |  | ||||||
| #if defined(LIBISCSI_FEATURE_IOVECTOR) |  | ||||||
|  |  | ||||||
| static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs, |  | ||||||
|                                                   int64_t sector_num, |  | ||||||
|                                                   int nb_sectors, int *pnum) |  | ||||||
| { |  | ||||||
|     IscsiLun *iscsilun = bs->opaque; |  | ||||||
|     struct scsi_get_lba_status *lbas = NULL; |  | ||||||
|     struct scsi_lba_status_descriptor *lbasd = NULL; |  | ||||||
|     struct IscsiTask iTask; |  | ||||||
|     int64_t ret; |  | ||||||
|  |  | ||||||
|     iscsi_co_init_iscsitask(iscsilun, &iTask); |  | ||||||
|  |  | ||||||
|     if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) { |  | ||||||
|         ret = -EINVAL; |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* default to all sectors allocated */ |  | ||||||
|     ret = BDRV_BLOCK_DATA; |  | ||||||
|     ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID; |  | ||||||
|     *pnum = nb_sectors; |  | ||||||
|  |  | ||||||
|     /* LUN does not support logical block provisioning */ |  | ||||||
|     if (iscsilun->lbpme == 0) { |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| retry: |  | ||||||
|     if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun, |  | ||||||
|                                   sector_qemu2lun(sector_num, iscsilun), |  | ||||||
|                                   8 + 16, iscsi_co_generic_cb, |  | ||||||
|                                   &iTask) == NULL) { |  | ||||||
|         ret = -ENOMEM; |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     while (!iTask.complete) { |  | ||||||
|         iscsi_set_events(iscsilun); |  | ||||||
|         qemu_coroutine_yield(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (iTask.do_retry) { |  | ||||||
|         if (iTask.task != NULL) { |  | ||||||
|             scsi_free_scsi_task(iTask.task); |  | ||||||
|             iTask.task = NULL; |  | ||||||
|         } |  | ||||||
|         iTask.complete = 0; |  | ||||||
|         goto retry; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (iTask.status != SCSI_STATUS_GOOD) { |  | ||||||
|         /* in case the get_lba_status_callout fails (i.e. |  | ||||||
|          * because the device is busy or the cmd is not |  | ||||||
|          * supported) we pretend all blocks are allocated |  | ||||||
|          * for backwards compatibility */ |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lbas = scsi_datain_unmarshall(iTask.task); |  | ||||||
|     if (lbas == NULL) { |  | ||||||
|         ret = -EIO; |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     lbasd = &lbas->descriptors[0]; |  | ||||||
|  |  | ||||||
|     if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) { |  | ||||||
|         ret = -EIO; |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun); |  | ||||||
|     if (*pnum > nb_sectors) { |  | ||||||
|         *pnum = nb_sectors; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED || |  | ||||||
|         lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) { |  | ||||||
|         ret &= ~BDRV_BLOCK_DATA; |  | ||||||
|         if (iscsilun->lbprz) { |  | ||||||
|             ret |= BDRV_BLOCK_ZERO; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| out: |  | ||||||
|     if (iTask.task != NULL) { |  | ||||||
|         scsi_free_scsi_task(iTask.task); |  | ||||||
|     } |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif /* LIBISCSI_FEATURE_IOVECTOR */ |  | ||||||
|  |  | ||||||
| static int | static int | ||||||
| coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num, | coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num, | ||||||
|                                    int nb_sectors) |                                    int nb_sectors) | ||||||
| @@ -791,6 +867,8 @@ retry: | |||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     iscsi_allocationmap_clear(iscsilun, sector_num, nb_sectors); | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -809,13 +887,14 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num, | |||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) { |     if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) { | ||||||
|         /* WRITE SAME without UNMAP is not supported by the target */ |         /* WRITE SAME with UNMAP is not supported by the target, | ||||||
|         return -ENOTSUP; |          * fall back and try WRITE SAME without UNMAP */ | ||||||
|  |         flags &= ~BDRV_REQ_MAY_UNMAP; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) { |     if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) { | ||||||
|         /* WRITE SAME with UNMAP is not supported by the target */ |         /* WRITE SAME without UNMAP is not supported by the target */ | ||||||
|         return -ENOTSUP; |         return -ENOTSUP; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -864,6 +943,12 @@ retry: | |||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (flags & BDRV_REQ_MAY_UNMAP) { | ||||||
|  |         iscsi_allocationmap_clear(iscsilun, sector_num, nb_sectors); | ||||||
|  |     } else { | ||||||
|  |         iscsi_allocationmap_set(iscsilun, sector_num, nb_sectors); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1295,6 +1380,22 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL); |     timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |     /* Guess the internal cluster (page) size of the iscsi target by the means | ||||||
|  |      * of opt_unmap_gran. Transfer the unmap granularity only if it has a | ||||||
|  |      * reasonable size */ | ||||||
|  |     if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 && | ||||||
|  |         iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) { | ||||||
|  |         iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran * | ||||||
|  |                                      iscsilun->block_size) >> BDRV_SECTOR_BITS; | ||||||
|  | #if defined(LIBISCSI_FEATURE_IOVECTOR) | ||||||
|  |         if (iscsilun->lbprz && !(bs->open_flags & BDRV_O_NOCACHE)) { | ||||||
|  |             iscsilun->allocationmap = | ||||||
|  |                 bitmap_new(DIV_ROUND_UP(bs->total_sectors, | ||||||
|  |                                         iscsilun->cluster_sectors)); | ||||||
|  |         } | ||||||
|  | #endif | ||||||
|  |     } | ||||||
|  |  | ||||||
| out: | out: | ||||||
|     qemu_opts_del(opts); |     qemu_opts_del(opts); | ||||||
|     if (initiator_name != NULL) { |     if (initiator_name != NULL) { | ||||||
| @@ -1328,6 +1429,7 @@ static void iscsi_close(BlockDriverState *bs) | |||||||
|     qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL); |     qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL); | ||||||
|     iscsi_destroy_context(iscsi); |     iscsi_destroy_context(iscsi); | ||||||
|     g_free(iscsilun->zeroblock); |     g_free(iscsilun->zeroblock); | ||||||
|  |     g_free(iscsilun->allocationmap); | ||||||
|     memset(iscsilun, 0, sizeof(IscsiLun)); |     memset(iscsilun, 0, sizeof(IscsiLun)); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1388,6 +1490,13 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset) | |||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (iscsilun->allocationmap != NULL) { | ||||||
|  |         g_free(iscsilun->allocationmap); | ||||||
|  |         iscsilun->allocationmap = | ||||||
|  |             bitmap_new(DIV_ROUND_UP(bs->total_sectors, | ||||||
|  |                                     iscsilun->cluster_sectors)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1450,13 +1559,7 @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | |||||||
|     IscsiLun *iscsilun = bs->opaque; |     IscsiLun *iscsilun = bs->opaque; | ||||||
|     bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz; |     bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz; | ||||||
|     bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws; |     bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws; | ||||||
|     /* Guess the internal cluster (page) size of the iscsi target by the means |     bdi->cluster_size = iscsilun->cluster_sectors * BDRV_SECTOR_SIZE; | ||||||
|      * of opt_unmap_gran. Transfer the unmap granularity only if it has a |  | ||||||
|      * reasonable size for bdi->cluster_size */ |  | ||||||
|     if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 64 * 1024 && |  | ||||||
|         iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) { |  | ||||||
|         bdi->cluster_size = iscsilun->bl.opt_unmap_gran * iscsilun->block_size; |  | ||||||
|     } |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -498,7 +498,7 @@ immediate_exit: | |||||||
|             /* drop the bs loop chain formed by the swap: break the loop then |             /* drop the bs loop chain formed by the swap: break the loop then | ||||||
|              * trigger the unref from the top one */ |              * trigger the unref from the top one */ | ||||||
|             BlockDriverState *p = s->base->backing_hd; |             BlockDriverState *p = s->base->backing_hd; | ||||||
|             s->base->backing_hd = NULL; |             bdrv_set_backing_hd(s->base, NULL); | ||||||
|             bdrv_unref(p); |             bdrv_unref(p); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     info->backing_file_depth = bdrv_get_backing_file_depth(bs); |     info->backing_file_depth = bdrv_get_backing_file_depth(bs); | ||||||
|  |     info->detect_zeroes = bs->detect_zeroes; | ||||||
|  |  | ||||||
|     if (bs->io_limits_enabled) { |     if (bs->io_limits_enabled) { | ||||||
|         ThrottleConfig cfg; |         ThrottleConfig cfg; | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								block/qcow.c
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								block/qcow.c
									
									
									
									
									
								
							| @@ -48,9 +48,10 @@ typedef struct QCowHeader { | |||||||
|     uint64_t size; /* in bytes */ |     uint64_t size; /* in bytes */ | ||||||
|     uint8_t cluster_bits; |     uint8_t cluster_bits; | ||||||
|     uint8_t l2_bits; |     uint8_t l2_bits; | ||||||
|  |     uint16_t padding; | ||||||
|     uint32_t crypt_method; |     uint32_t crypt_method; | ||||||
|     uint64_t l1_table_offset; |     uint64_t l1_table_offset; | ||||||
| } QCowHeader; | } QEMU_PACKED QCowHeader; | ||||||
|  |  | ||||||
| #define L2_CACHE_SIZE 16 | #define L2_CACHE_SIZE 16 | ||||||
|  |  | ||||||
| @@ -60,7 +61,7 @@ typedef struct BDRVQcowState { | |||||||
|     int cluster_sectors; |     int cluster_sectors; | ||||||
|     int l2_bits; |     int l2_bits; | ||||||
|     int l2_size; |     int l2_size; | ||||||
|     int l1_size; |     unsigned int l1_size; | ||||||
|     uint64_t cluster_offset_mask; |     uint64_t cluster_offset_mask; | ||||||
|     uint64_t l1_table_offset; |     uint64_t l1_table_offset; | ||||||
|     uint64_t *l1_table; |     uint64_t *l1_table; | ||||||
| @@ -96,7 +97,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|                      Error **errp) |                      Error **errp) | ||||||
| { | { | ||||||
|     BDRVQcowState *s = bs->opaque; |     BDRVQcowState *s = bs->opaque; | ||||||
|     int len, i, shift, ret; |     unsigned int len, i, shift; | ||||||
|  |     int ret; | ||||||
|     QCowHeader header; |     QCowHeader header; | ||||||
|  |  | ||||||
|     ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); |     ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); | ||||||
| @@ -127,11 +129,25 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|         goto fail; |         goto fail; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (header.size <= 1 || header.cluster_bits < 9) { |     if (header.size <= 1) { | ||||||
|         error_setg(errp, "invalid value in qcow header"); |         error_setg(errp, "Image size is too small (must be at least 2 bytes)"); | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         goto fail; |         goto fail; | ||||||
|     } |     } | ||||||
|  |     if (header.cluster_bits < 9 || header.cluster_bits > 16) { | ||||||
|  |         error_setg(errp, "Cluster size must be between 512 and 64k"); | ||||||
|  |         ret = -EINVAL; | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* l2_bits specifies number of entries; storing a uint64_t in each entry, | ||||||
|  |      * so bytes = num_entries << 3. */ | ||||||
|  |     if (header.l2_bits < 9 - 3 || header.l2_bits > 16 - 3) { | ||||||
|  |         error_setg(errp, "L2 table size must be between 512 and 64k"); | ||||||
|  |         ret = -EINVAL; | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (header.crypt_method > QCOW_CRYPT_AES) { |     if (header.crypt_method > QCOW_CRYPT_AES) { | ||||||
|         error_setg(errp, "invalid encryption method in qcow header"); |         error_setg(errp, "invalid encryption method in qcow header"); | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
| @@ -151,7 +167,19 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|  |  | ||||||
|     /* read the level 1 table */ |     /* read the level 1 table */ | ||||||
|     shift = s->cluster_bits + s->l2_bits; |     shift = s->cluster_bits + s->l2_bits; | ||||||
|     s->l1_size = (header.size + (1LL << shift) - 1) >> shift; |     if (header.size > UINT64_MAX - (1LL << shift)) { | ||||||
|  |         error_setg(errp, "Image too large"); | ||||||
|  |         ret = -EINVAL; | ||||||
|  |         goto fail; | ||||||
|  |     } else { | ||||||
|  |         uint64_t l1_size = (header.size + (1LL << shift) - 1) >> shift; | ||||||
|  |         if (l1_size > INT_MAX / sizeof(uint64_t)) { | ||||||
|  |             error_setg(errp, "Image too large"); | ||||||
|  |             ret = -EINVAL; | ||||||
|  |             goto fail; | ||||||
|  |         } | ||||||
|  |         s->l1_size = l1_size; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     s->l1_table_offset = header.l1_table_offset; |     s->l1_table_offset = header.l1_table_offset; | ||||||
|     s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t)); |     s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t)); | ||||||
| @@ -175,7 +203,9 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     if (header.backing_file_offset != 0) { |     if (header.backing_file_offset != 0) { | ||||||
|         len = header.backing_file_size; |         len = header.backing_file_size; | ||||||
|         if (len > 1023) { |         if (len > 1023) { | ||||||
|             len = 1023; |             error_setg(errp, "Backing file name too long"); | ||||||
|  |             ret = -EINVAL; | ||||||
|  |             goto fail; | ||||||
|         } |         } | ||||||
|         ret = bdrv_pread(bs->file, header.backing_file_offset, |         ret = bdrv_pread(bs->file, header.backing_file_offset, | ||||||
|                    bs->backing_file, len); |                    bs->backing_file, len); | ||||||
|   | |||||||
| @@ -379,7 +379,8 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs, | |||||||
|     BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); |     BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); | ||||||
|  |  | ||||||
|     if (!bs->drv) { |     if (!bs->drv) { | ||||||
|         return -ENOMEDIUM; |         ret = -ENOMEDIUM; | ||||||
|  |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Call .bdrv_co_readv() directly instead of using the public block-layer |     /* Call .bdrv_co_readv() directly instead of using the public block-layer | ||||||
|   | |||||||
							
								
								
									
										71
									
								
								block/rbd.c
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								block/rbd.c
									
									
									
									
									
								
							| @@ -105,7 +105,7 @@ typedef struct BDRVRBDState { | |||||||
| static int qemu_rbd_next_tok(char *dst, int dst_len, | static int qemu_rbd_next_tok(char *dst, int dst_len, | ||||||
|                              char *src, char delim, |                              char *src, char delim, | ||||||
|                              const char *name, |                              const char *name, | ||||||
|                              char **p) |                              char **p, Error **errp) | ||||||
| { | { | ||||||
|     int l; |     int l; | ||||||
|     char *end; |     char *end; | ||||||
| @@ -128,10 +128,10 @@ static int qemu_rbd_next_tok(char *dst, int dst_len, | |||||||
|     } |     } | ||||||
|     l = strlen(src); |     l = strlen(src); | ||||||
|     if (l >= dst_len) { |     if (l >= dst_len) { | ||||||
|         error_report("%s too long", name); |         error_setg(errp, "%s too long", name); | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } else if (l == 0) { |     } else if (l == 0) { | ||||||
|         error_report("%s too short", name); |         error_setg(errp, "%s too short", name); | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -157,13 +157,15 @@ static int qemu_rbd_parsename(const char *filename, | |||||||
|                               char *pool, int pool_len, |                               char *pool, int pool_len, | ||||||
|                               char *snap, int snap_len, |                               char *snap, int snap_len, | ||||||
|                               char *name, int name_len, |                               char *name, int name_len, | ||||||
|                               char *conf, int conf_len) |                               char *conf, int conf_len, | ||||||
|  |                               Error **errp) | ||||||
| { | { | ||||||
|     const char *start; |     const char *start; | ||||||
|     char *p, *buf; |     char *p, *buf; | ||||||
|     int ret; |     int ret; | ||||||
|  |  | ||||||
|     if (!strstart(filename, "rbd:", &start)) { |     if (!strstart(filename, "rbd:", &start)) { | ||||||
|  |         error_setg(errp, "File name must start with 'rbd:'"); | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -172,7 +174,8 @@ static int qemu_rbd_parsename(const char *filename, | |||||||
|     *snap = '\0'; |     *snap = '\0'; | ||||||
|     *conf = '\0'; |     *conf = '\0'; | ||||||
|  |  | ||||||
|     ret = qemu_rbd_next_tok(pool, pool_len, p, '/', "pool name", &p); |     ret = qemu_rbd_next_tok(pool, pool_len, p, | ||||||
|  |                             '/', "pool name", &p, errp); | ||||||
|     if (ret < 0 || !p) { |     if (ret < 0 || !p) { | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         goto done; |         goto done; | ||||||
| @@ -180,21 +183,25 @@ static int qemu_rbd_parsename(const char *filename, | |||||||
|     qemu_rbd_unescape(pool); |     qemu_rbd_unescape(pool); | ||||||
|  |  | ||||||
|     if (strchr(p, '@')) { |     if (strchr(p, '@')) { | ||||||
|         ret = qemu_rbd_next_tok(name, name_len, p, '@', "object name", &p); |         ret = qemu_rbd_next_tok(name, name_len, p, | ||||||
|  |                                 '@', "object name", &p, errp); | ||||||
|         if (ret < 0) { |         if (ret < 0) { | ||||||
|             goto done; |             goto done; | ||||||
|         } |         } | ||||||
|         ret = qemu_rbd_next_tok(snap, snap_len, p, ':', "snap name", &p); |         ret = qemu_rbd_next_tok(snap, snap_len, p, | ||||||
|  |                                 ':', "snap name", &p, errp); | ||||||
|         qemu_rbd_unescape(snap); |         qemu_rbd_unescape(snap); | ||||||
|     } else { |     } else { | ||||||
|         ret = qemu_rbd_next_tok(name, name_len, p, ':', "object name", &p); |         ret = qemu_rbd_next_tok(name, name_len, p, | ||||||
|  |                                 ':', "object name", &p, errp); | ||||||
|     } |     } | ||||||
|     qemu_rbd_unescape(name); |     qemu_rbd_unescape(name); | ||||||
|     if (ret < 0 || !p) { |     if (ret < 0 || !p) { | ||||||
|         goto done; |         goto done; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ret = qemu_rbd_next_tok(conf, conf_len, p, '\0', "configuration", &p); |     ret = qemu_rbd_next_tok(conf, conf_len, p, | ||||||
|  |                             '\0', "configuration", &p, errp); | ||||||
|  |  | ||||||
| done: | done: | ||||||
|     g_free(buf); |     g_free(buf); | ||||||
| @@ -229,7 +236,7 @@ static char *qemu_rbd_parse_clientname(const char *conf, char *clientname) | |||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int qemu_rbd_set_conf(rados_t cluster, const char *conf) | static int qemu_rbd_set_conf(rados_t cluster, const char *conf, Error **errp) | ||||||
| { | { | ||||||
|     char *p, *buf; |     char *p, *buf; | ||||||
|     char name[RBD_MAX_CONF_NAME_SIZE]; |     char name[RBD_MAX_CONF_NAME_SIZE]; | ||||||
| @@ -241,20 +248,20 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf) | |||||||
|  |  | ||||||
|     while (p) { |     while (p) { | ||||||
|         ret = qemu_rbd_next_tok(name, sizeof(name), p, |         ret = qemu_rbd_next_tok(name, sizeof(name), p, | ||||||
|                                 '=', "conf option name", &p); |                                 '=', "conf option name", &p, errp); | ||||||
|         if (ret < 0) { |         if (ret < 0) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         qemu_rbd_unescape(name); |         qemu_rbd_unescape(name); | ||||||
|  |  | ||||||
|         if (!p) { |         if (!p) { | ||||||
|             error_report("conf option %s has no value", name); |             error_setg(errp, "conf option %s has no value", name); | ||||||
|             ret = -EINVAL; |             ret = -EINVAL; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ret = qemu_rbd_next_tok(value, sizeof(value), p, |         ret = qemu_rbd_next_tok(value, sizeof(value), p, | ||||||
|                                 ':', "conf option value", &p); |                                 ':', "conf option value", &p, errp); | ||||||
|         if (ret < 0) { |         if (ret < 0) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| @@ -263,7 +270,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf) | |||||||
|         if (strcmp(name, "conf") == 0) { |         if (strcmp(name, "conf") == 0) { | ||||||
|             ret = rados_conf_read_file(cluster, value); |             ret = rados_conf_read_file(cluster, value); | ||||||
|             if (ret < 0) { |             if (ret < 0) { | ||||||
|                 error_report("error reading conf file %s", value); |                 error_setg(errp, "error reading conf file %s", value); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } else if (strcmp(name, "id") == 0) { |         } else if (strcmp(name, "id") == 0) { | ||||||
| @@ -271,7 +278,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf) | |||||||
|         } else { |         } else { | ||||||
|             ret = rados_conf_set(cluster, name, value); |             ret = rados_conf_set(cluster, name, value); | ||||||
|             if (ret < 0) { |             if (ret < 0) { | ||||||
|                 error_report("invalid conf option %s", name); |                 error_setg(errp, "invalid conf option %s", name); | ||||||
|                 ret = -EINVAL; |                 ret = -EINVAL; | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| @@ -285,6 +292,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf) | |||||||
| static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options, | static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options, | ||||||
|                            Error **errp) |                            Error **errp) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     int64_t bytes = 0; |     int64_t bytes = 0; | ||||||
|     int64_t objsize; |     int64_t objsize; | ||||||
|     int obj_order = 0; |     int obj_order = 0; | ||||||
| @@ -301,7 +309,8 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|     if (qemu_rbd_parsename(filename, pool, sizeof(pool), |     if (qemu_rbd_parsename(filename, pool, sizeof(pool), | ||||||
|                            snap_buf, sizeof(snap_buf), |                            snap_buf, sizeof(snap_buf), | ||||||
|                            name, sizeof(name), |                            name, sizeof(name), | ||||||
|                            conf, sizeof(conf)) < 0) { |                            conf, sizeof(conf), &local_err) < 0) { | ||||||
|  |         error_propagate(errp, local_err); | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -313,11 +322,11 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|             if (options->value.n) { |             if (options->value.n) { | ||||||
|                 objsize = options->value.n; |                 objsize = options->value.n; | ||||||
|                 if ((objsize - 1) & objsize) {    /* not a power of 2? */ |                 if ((objsize - 1) & objsize) {    /* not a power of 2? */ | ||||||
|                     error_report("obj size needs to be power of 2"); |                     error_setg(errp, "obj size needs to be power of 2"); | ||||||
|                     return -EINVAL; |                     return -EINVAL; | ||||||
|                 } |                 } | ||||||
|                 if (objsize < 4096) { |                 if (objsize < 4096) { | ||||||
|                     error_report("obj size too small"); |                     error_setg(errp, "obj size too small"); | ||||||
|                     return -EINVAL; |                     return -EINVAL; | ||||||
|                 } |                 } | ||||||
|                 obj_order = ffs(objsize) - 1; |                 obj_order = ffs(objsize) - 1; | ||||||
| @@ -328,7 +337,7 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|  |  | ||||||
|     clientname = qemu_rbd_parse_clientname(conf, clientname_buf); |     clientname = qemu_rbd_parse_clientname(conf, clientname_buf); | ||||||
|     if (rados_create(&cluster, clientname) < 0) { |     if (rados_create(&cluster, clientname) < 0) { | ||||||
|         error_report("error initializing"); |         error_setg(errp, "error initializing"); | ||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -338,20 +347,20 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (conf[0] != '\0' && |     if (conf[0] != '\0' && | ||||||
|         qemu_rbd_set_conf(cluster, conf) < 0) { |         qemu_rbd_set_conf(cluster, conf, &local_err) < 0) { | ||||||
|         error_report("error setting config options"); |  | ||||||
|         rados_shutdown(cluster); |         rados_shutdown(cluster); | ||||||
|  |         error_propagate(errp, local_err); | ||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (rados_connect(cluster) < 0) { |     if (rados_connect(cluster) < 0) { | ||||||
|         error_report("error connecting"); |         error_setg(errp, "error connecting"); | ||||||
|         rados_shutdown(cluster); |         rados_shutdown(cluster); | ||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (rados_ioctx_create(cluster, pool, &io_ctx) < 0) { |     if (rados_ioctx_create(cluster, pool, &io_ctx) < 0) { | ||||||
|         error_report("error opening pool %s", pool); |         error_setg(errp, "error opening pool %s", pool); | ||||||
|         rados_shutdown(cluster); |         rados_shutdown(cluster); | ||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
| @@ -441,8 +450,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); |     opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); | ||||||
|     qemu_opts_absorb_qdict(opts, options, &local_err); |     qemu_opts_absorb_qdict(opts, options, &local_err); | ||||||
|     if (local_err) { |     if (local_err) { | ||||||
|         qerror_report_err(local_err); |         error_propagate(errp, local_err); | ||||||
|         error_free(local_err); |  | ||||||
|         qemu_opts_del(opts); |         qemu_opts_del(opts); | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
| @@ -452,7 +460,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     if (qemu_rbd_parsename(filename, pool, sizeof(pool), |     if (qemu_rbd_parsename(filename, pool, sizeof(pool), | ||||||
|                            snap_buf, sizeof(snap_buf), |                            snap_buf, sizeof(snap_buf), | ||||||
|                            s->name, sizeof(s->name), |                            s->name, sizeof(s->name), | ||||||
|                            conf, sizeof(conf)) < 0) { |                            conf, sizeof(conf), errp) < 0) { | ||||||
|         r = -EINVAL; |         r = -EINVAL; | ||||||
|         goto failed_opts; |         goto failed_opts; | ||||||
|     } |     } | ||||||
| @@ -460,7 +468,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     clientname = qemu_rbd_parse_clientname(conf, clientname_buf); |     clientname = qemu_rbd_parse_clientname(conf, clientname_buf); | ||||||
|     r = rados_create(&s->cluster, clientname); |     r = rados_create(&s->cluster, clientname); | ||||||
|     if (r < 0) { |     if (r < 0) { | ||||||
|         error_report("error initializing"); |         error_setg(&local_err, "error initializing"); | ||||||
|         goto failed_opts; |         goto failed_opts; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -488,28 +496,27 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (conf[0] != '\0') { |     if (conf[0] != '\0') { | ||||||
|         r = qemu_rbd_set_conf(s->cluster, conf); |         r = qemu_rbd_set_conf(s->cluster, conf, errp); | ||||||
|         if (r < 0) { |         if (r < 0) { | ||||||
|             error_report("error setting config options"); |  | ||||||
|             goto failed_shutdown; |             goto failed_shutdown; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     r = rados_connect(s->cluster); |     r = rados_connect(s->cluster); | ||||||
|     if (r < 0) { |     if (r < 0) { | ||||||
|         error_report("error connecting"); |         error_setg(&local_err, "error connecting"); | ||||||
|         goto failed_shutdown; |         goto failed_shutdown; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); |     r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); | ||||||
|     if (r < 0) { |     if (r < 0) { | ||||||
|         error_report("error opening pool %s", pool); |         error_setg(&local_err, "error opening pool %s", pool); | ||||||
|         goto failed_shutdown; |         goto failed_shutdown; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); |     r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); | ||||||
|     if (r < 0) { |     if (r < 0) { | ||||||
|         error_report("error reading header from %s", s->name); |         error_setg(&local_err, "error reading header from %s", s->name); | ||||||
|         goto failed_open; |         goto failed_open; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										145
									
								
								block/sheepdog.c
									
									
									
									
									
								
							
							
						
						
									
										145
									
								
								block/sheepdog.c
									
									
									
									
									
								
							| @@ -526,17 +526,16 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov, | |||||||
|     return acb; |     return acb; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int connect_to_sdog(BDRVSheepdogState *s) | static int connect_to_sdog(BDRVSheepdogState *s, Error **errp) | ||||||
| { | { | ||||||
|     int fd; |     int fd; | ||||||
|     Error *err = NULL; |  | ||||||
|  |  | ||||||
|     if (s->is_unix) { |     if (s->is_unix) { | ||||||
|         fd = unix_connect(s->host_spec, &err); |         fd = unix_connect(s->host_spec, errp); | ||||||
|     } else { |     } else { | ||||||
|         fd = inet_connect(s->host_spec, &err); |         fd = inet_connect(s->host_spec, errp); | ||||||
|  |  | ||||||
|         if (err == NULL) { |         if (fd >= 0) { | ||||||
|             int ret = socket_set_nodelay(fd); |             int ret = socket_set_nodelay(fd); | ||||||
|             if (ret < 0) { |             if (ret < 0) { | ||||||
|                 error_report("%s", strerror(errno)); |                 error_report("%s", strerror(errno)); | ||||||
| @@ -544,10 +543,7 @@ static int connect_to_sdog(BDRVSheepdogState *s) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (err != NULL) { |     if (fd >= 0) { | ||||||
|         qerror_report_err(err); |  | ||||||
|         error_free(err); |  | ||||||
|     } else { |  | ||||||
|         qemu_set_nonblock(fd); |         qemu_set_nonblock(fd); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -672,7 +668,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, | |||||||
|                            enum AIOCBState aiocb_type); |                            enum AIOCBState aiocb_type); | ||||||
| static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req); | static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req); | ||||||
| static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag); | static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag); | ||||||
| static int get_sheep_fd(BDRVSheepdogState *s); | static int get_sheep_fd(BDRVSheepdogState *s, Error **errp); | ||||||
| static void co_write_request(void *opaque); | static void co_write_request(void *opaque); | ||||||
|  |  | ||||||
| static AIOReq *find_pending_req(BDRVSheepdogState *s, uint64_t oid) | static AIOReq *find_pending_req(BDRVSheepdogState *s, uint64_t oid) | ||||||
| @@ -709,6 +705,7 @@ static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid) | |||||||
|  |  | ||||||
| static coroutine_fn void reconnect_to_sdog(void *opaque) | static coroutine_fn void reconnect_to_sdog(void *opaque) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     BDRVSheepdogState *s = opaque; |     BDRVSheepdogState *s = opaque; | ||||||
|     AIOReq *aio_req, *next; |     AIOReq *aio_req, *next; | ||||||
|  |  | ||||||
| @@ -723,9 +720,11 @@ static coroutine_fn void reconnect_to_sdog(void *opaque) | |||||||
|  |  | ||||||
|     /* Try to reconnect the sheepdog server every one second. */ |     /* Try to reconnect the sheepdog server every one second. */ | ||||||
|     while (s->fd < 0) { |     while (s->fd < 0) { | ||||||
|         s->fd = get_sheep_fd(s); |         s->fd = get_sheep_fd(s, &local_err); | ||||||
|         if (s->fd < 0) { |         if (s->fd < 0) { | ||||||
|             DPRINTF("Wait for connection to be established\n"); |             DPRINTF("Wait for connection to be established\n"); | ||||||
|  |             error_report("%s", error_get_pretty(local_err)); | ||||||
|  |             error_free(local_err); | ||||||
|             co_aio_sleep_ns(bdrv_get_aio_context(s->bs), QEMU_CLOCK_REALTIME, |             co_aio_sleep_ns(bdrv_get_aio_context(s->bs), QEMU_CLOCK_REALTIME, | ||||||
|                             1000000000ULL); |                             1000000000ULL); | ||||||
|         } |         } | ||||||
| @@ -914,11 +913,11 @@ static void co_write_request(void *opaque) | |||||||
|  * We cannot use this descriptor for other operations because |  * We cannot use this descriptor for other operations because | ||||||
|  * the block driver may be on waiting response from the server. |  * the block driver may be on waiting response from the server. | ||||||
|  */ |  */ | ||||||
| static int get_sheep_fd(BDRVSheepdogState *s) | static int get_sheep_fd(BDRVSheepdogState *s, Error **errp) | ||||||
| { | { | ||||||
|     int fd; |     int fd; | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, errp); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|         return fd; |         return fd; | ||||||
|     } |     } | ||||||
| @@ -1061,7 +1060,7 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename, | |||||||
|  |  | ||||||
| static int find_vdi_name(BDRVSheepdogState *s, const char *filename, | static int find_vdi_name(BDRVSheepdogState *s, const char *filename, | ||||||
|                          uint32_t snapid, const char *tag, uint32_t *vid, |                          uint32_t snapid, const char *tag, uint32_t *vid, | ||||||
|                          bool lock) |                          bool lock, Error **errp) | ||||||
| { | { | ||||||
|     int ret, fd; |     int ret, fd; | ||||||
|     SheepdogVdiReq hdr; |     SheepdogVdiReq hdr; | ||||||
| @@ -1069,7 +1068,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename, | |||||||
|     unsigned int wlen, rlen = 0; |     unsigned int wlen, rlen = 0; | ||||||
|     char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN]; |     char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN]; | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, errp); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|         return fd; |         return fd; | ||||||
|     } |     } | ||||||
| @@ -1095,11 +1094,12 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename, | |||||||
|  |  | ||||||
|     ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen); |     ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen); | ||||||
|     if (ret) { |     if (ret) { | ||||||
|  |         error_setg_errno(errp, -ret, "cannot get vdi info"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (rsp->result != SD_RES_SUCCESS) { |     if (rsp->result != SD_RES_SUCCESS) { | ||||||
|         error_report("cannot get vdi info, %s, %s %" PRIu32 " %s", |         error_setg(errp, "cannot get vdi info, %s, %s %" PRIu32 " %s", | ||||||
|                    sd_strerror(rsp->result), filename, snapid, tag); |                    sd_strerror(rsp->result), filename, snapid, tag); | ||||||
|         if (rsp->result == SD_RES_NO_VDI) { |         if (rsp->result == SD_RES_NO_VDI) { | ||||||
|             ret = -ENOENT; |             ret = -ENOENT; | ||||||
| @@ -1263,19 +1263,24 @@ static int write_object(int fd, char *buf, uint64_t oid, uint8_t copies, | |||||||
| /* update inode with the latest state */ | /* update inode with the latest state */ | ||||||
| static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag) | static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     SheepdogInode *inode; |     SheepdogInode *inode; | ||||||
|     int ret = 0, fd; |     int ret = 0, fd; | ||||||
|     uint32_t vid = 0; |     uint32_t vid = 0; | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     inode = g_malloc(sizeof(s->inode)); |     inode = g_malloc(sizeof(s->inode)); | ||||||
|  |  | ||||||
|     ret = find_vdi_name(s, s->name, snapid, tag, &vid, false); |     ret = find_vdi_name(s, s->name, snapid, tag, &vid, false, &local_err); | ||||||
|     if (ret) { |     if (ret) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1386,8 +1391,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); |     opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); | ||||||
|     qemu_opts_absorb_qdict(opts, options, &local_err); |     qemu_opts_absorb_qdict(opts, options, &local_err); | ||||||
|     if (local_err) { |     if (local_err) { | ||||||
|         qerror_report_err(local_err); |         error_propagate(errp, local_err); | ||||||
|         error_free(local_err); |  | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
| @@ -1408,15 +1412,16 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|         ret = parse_vdiname(s, filename, vdi, &snapid, tag); |         ret = parse_vdiname(s, filename, vdi, &snapid, tag); | ||||||
|     } |     } | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|  |         error_setg(errp, "Can't parse filename"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|     s->fd = get_sheep_fd(s); |     s->fd = get_sheep_fd(s, errp); | ||||||
|     if (s->fd < 0) { |     if (s->fd < 0) { | ||||||
|         ret = s->fd; |         ret = s->fd; | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ret = find_vdi_name(s, vdi, snapid, tag, &vid, true); |     ret = find_vdi_name(s, vdi, snapid, tag, &vid, true, errp); | ||||||
|     if (ret) { |     if (ret) { | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
| @@ -1436,7 +1441,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|         s->is_snapshot = true; |         s->is_snapshot = true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, errp); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|         ret = fd; |         ret = fd; | ||||||
|         goto out; |         goto out; | ||||||
| @@ -1449,6 +1454,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     closesocket(fd); |     closesocket(fd); | ||||||
|  |  | ||||||
|     if (ret) { |     if (ret) { | ||||||
|  |         error_setg(errp, "Can't read snapshot inode"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1472,7 +1478,8 @@ out: | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot) | static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot, | ||||||
|  |                         Error **errp) | ||||||
| { | { | ||||||
|     SheepdogVdiReq hdr; |     SheepdogVdiReq hdr; | ||||||
|     SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; |     SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; | ||||||
| @@ -1480,7 +1487,7 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot) | |||||||
|     unsigned int wlen, rlen = 0; |     unsigned int wlen, rlen = 0; | ||||||
|     char buf[SD_MAX_VDI_LEN]; |     char buf[SD_MAX_VDI_LEN]; | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, errp); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|         return fd; |         return fd; | ||||||
|     } |     } | ||||||
| @@ -1510,11 +1517,12 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot) | |||||||
|     closesocket(fd); |     closesocket(fd); | ||||||
|  |  | ||||||
|     if (ret) { |     if (ret) { | ||||||
|  |         error_setg_errno(errp, -ret, "create failed"); | ||||||
|         return ret; |         return ret; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (rsp->result != SD_RES_SUCCESS) { |     if (rsp->result != SD_RES_SUCCESS) { | ||||||
|         error_report("%s, %s", sd_strerror(rsp->result), s->inode.name); |         error_setg(errp, "%s, %s", sd_strerror(rsp->result), s->inode.name); | ||||||
|         return -EIO; |         return -EIO; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1525,21 +1533,18 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int sd_prealloc(const char *filename) | static int sd_prealloc(const char *filename, Error **errp) | ||||||
| { | { | ||||||
|     BlockDriverState *bs = NULL; |     BlockDriverState *bs = NULL; | ||||||
|     uint32_t idx, max_idx; |     uint32_t idx, max_idx; | ||||||
|     int64_t vdi_size; |     int64_t vdi_size; | ||||||
|     void *buf = g_malloc0(SD_DATA_OBJ_SIZE); |     void *buf = g_malloc0(SD_DATA_OBJ_SIZE); | ||||||
|     Error *local_err = NULL; |  | ||||||
|     int ret; |     int ret; | ||||||
|  |  | ||||||
|     ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, |     ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, | ||||||
|                     NULL, &local_err); |                     NULL, errp); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         qerror_report_err(local_err); |         goto out_with_err_set; | ||||||
|         error_free(local_err); |  | ||||||
|         goto out; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     vdi_size = bdrv_getlength(bs); |     vdi_size = bdrv_getlength(bs); | ||||||
| @@ -1563,7 +1568,12 @@ static int sd_prealloc(const char *filename) | |||||||
|             goto out; |             goto out; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| out: | out: | ||||||
|  |     if (ret < 0) { | ||||||
|  |         error_setg_errno(errp, -ret, "Can't pre-allocate"); | ||||||
|  |     } | ||||||
|  | out_with_err_set: | ||||||
|     if (bs) { |     if (bs) { | ||||||
|         bdrv_unref(bs); |         bdrv_unref(bs); | ||||||
|     } |     } | ||||||
| @@ -1636,7 +1646,6 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|     char tag[SD_MAX_VDI_TAG_LEN]; |     char tag[SD_MAX_VDI_TAG_LEN]; | ||||||
|     uint32_t snapid; |     uint32_t snapid; | ||||||
|     bool prealloc = false; |     bool prealloc = false; | ||||||
|     Error *local_err = NULL; |  | ||||||
|  |  | ||||||
|     s = g_malloc0(sizeof(BDRVSheepdogState)); |     s = g_malloc0(sizeof(BDRVSheepdogState)); | ||||||
|  |  | ||||||
| @@ -1647,6 +1656,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|         ret = parse_vdiname(s, filename, s->name, &snapid, tag); |         ret = parse_vdiname(s, filename, s->name, &snapid, tag); | ||||||
|     } |     } | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|  |         error_setg(errp, "Can't parse filename"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1661,7 +1671,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|             } else if (!strcmp(options->value.s, "full")) { |             } else if (!strcmp(options->value.s, "full")) { | ||||||
|                 prealloc = true; |                 prealloc = true; | ||||||
|             } else { |             } else { | ||||||
|                 error_report("Invalid preallocation mode: '%s'", |                 error_setg(errp, "Invalid preallocation mode: '%s'", | ||||||
|                            options->value.s); |                            options->value.s); | ||||||
|                 ret = -EINVAL; |                 ret = -EINVAL; | ||||||
|                 goto out; |                 goto out; | ||||||
| @@ -1670,6 +1680,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|             if (options->value.s) { |             if (options->value.s) { | ||||||
|                 ret = parse_redundancy(s, options->value.s); |                 ret = parse_redundancy(s, options->value.s); | ||||||
|                 if (ret < 0) { |                 if (ret < 0) { | ||||||
|  |                     error_setg(errp, "Invalid redundancy mode: '%s'", | ||||||
|  |                                options->value.s); | ||||||
|                     goto out; |                     goto out; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -1678,7 +1690,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (s->inode.vdi_size > SD_MAX_VDI_SIZE) { |     if (s->inode.vdi_size > SD_MAX_VDI_SIZE) { | ||||||
|         error_report("too big image size"); |         error_setg(errp, "too big image size"); | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
| @@ -1691,24 +1703,22 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|         /* Currently, only Sheepdog backing image is supported. */ |         /* Currently, only Sheepdog backing image is supported. */ | ||||||
|         drv = bdrv_find_protocol(backing_file, true); |         drv = bdrv_find_protocol(backing_file, true); | ||||||
|         if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) { |         if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) { | ||||||
|             error_report("backing_file must be a sheepdog image"); |             error_setg(errp, "backing_file must be a sheepdog image"); | ||||||
|             ret = -EINVAL; |             ret = -EINVAL; | ||||||
|             goto out; |             goto out; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         bs = NULL; |         bs = NULL; | ||||||
|         ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_PROTOCOL, NULL, |         ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_PROTOCOL, NULL, | ||||||
|                         &local_err); |                         errp); | ||||||
|         if (ret < 0) { |         if (ret < 0) { | ||||||
|             qerror_report_err(local_err); |  | ||||||
|             error_free(local_err); |  | ||||||
|             goto out; |             goto out; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         base = bs->opaque; |         base = bs->opaque; | ||||||
|  |  | ||||||
|         if (!is_snapshot(&base->inode)) { |         if (!is_snapshot(&base->inode)) { | ||||||
|             error_report("cannot clone from a non snapshot vdi"); |             error_setg(errp, "cannot clone from a non snapshot vdi"); | ||||||
|             bdrv_unref(bs); |             bdrv_unref(bs); | ||||||
|             ret = -EINVAL; |             ret = -EINVAL; | ||||||
|             goto out; |             goto out; | ||||||
| @@ -1717,12 +1727,14 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, | |||||||
|         bdrv_unref(bs); |         bdrv_unref(bs); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ret = do_sd_create(s, &vid, 0); |     ret = do_sd_create(s, &vid, 0, errp); | ||||||
|     if (!prealloc || ret) { |     if (ret) { | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ret = sd_prealloc(filename); |     if (prealloc) { | ||||||
|  |         ret = sd_prealloc(filename, errp); | ||||||
|  |     } | ||||||
| out: | out: | ||||||
|     g_free(s); |     g_free(s); | ||||||
|     return ret; |     return ret; | ||||||
| @@ -1730,6 +1742,7 @@ out: | |||||||
|  |  | ||||||
| static void sd_close(BlockDriverState *bs) | static void sd_close(BlockDriverState *bs) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     BDRVSheepdogState *s = bs->opaque; |     BDRVSheepdogState *s = bs->opaque; | ||||||
|     SheepdogVdiReq hdr; |     SheepdogVdiReq hdr; | ||||||
|     SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; |     SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; | ||||||
| @@ -1738,8 +1751,10 @@ static void sd_close(BlockDriverState *bs) | |||||||
|  |  | ||||||
|     DPRINTF("%s\n", s->name); |     DPRINTF("%s\n", s->name); | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1774,6 +1789,7 @@ static int64_t sd_getlength(BlockDriverState *bs) | |||||||
|  |  | ||||||
| static int sd_truncate(BlockDriverState *bs, int64_t offset) | static int sd_truncate(BlockDriverState *bs, int64_t offset) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     BDRVSheepdogState *s = bs->opaque; |     BDRVSheepdogState *s = bs->opaque; | ||||||
|     int ret, fd; |     int ret, fd; | ||||||
|     unsigned int datalen; |     unsigned int datalen; | ||||||
| @@ -1786,8 +1802,10 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset) | |||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         return fd; |         return fd; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1846,6 +1864,7 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb) | |||||||
| /* Delete current working VDI on the snapshot chain */ | /* Delete current working VDI on the snapshot chain */ | ||||||
| static bool sd_delete(BDRVSheepdogState *s) | static bool sd_delete(BDRVSheepdogState *s) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     unsigned int wlen = SD_MAX_VDI_LEN, rlen = 0; |     unsigned int wlen = SD_MAX_VDI_LEN, rlen = 0; | ||||||
|     SheepdogVdiReq hdr = { |     SheepdogVdiReq hdr = { | ||||||
|         .opcode = SD_OP_DEL_VDI, |         .opcode = SD_OP_DEL_VDI, | ||||||
| @@ -1856,8 +1875,10 @@ static bool sd_delete(BDRVSheepdogState *s) | |||||||
|     SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; |     SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; | ||||||
|     int fd, ret; |     int fd, ret; | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1885,6 +1906,7 @@ static bool sd_delete(BDRVSheepdogState *s) | |||||||
|  */ |  */ | ||||||
| static int sd_create_branch(BDRVSheepdogState *s) | static int sd_create_branch(BDRVSheepdogState *s) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     int ret, fd; |     int ret, fd; | ||||||
|     uint32_t vid; |     uint32_t vid; | ||||||
|     char *buf; |     char *buf; | ||||||
| @@ -1900,15 +1922,19 @@ static int sd_create_branch(BDRVSheepdogState *s) | |||||||
|      * false bail out. |      * false bail out. | ||||||
|      */ |      */ | ||||||
|     deleted = sd_delete(s); |     deleted = sd_delete(s); | ||||||
|     ret = do_sd_create(s, &vid, !deleted); |     ret = do_sd_create(s, &vid, !deleted, &local_err); | ||||||
|     if (ret) { |     if (ret) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     DPRINTF("%" PRIx32 " is created.\n", vid); |     DPRINTF("%" PRIx32 " is created.\n", vid); | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         ret = fd; |         ret = fd; | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
| @@ -2122,6 +2148,7 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs) | |||||||
|  |  | ||||||
| static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) | static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     BDRVSheepdogState *s = bs->opaque; |     BDRVSheepdogState *s = bs->opaque; | ||||||
|     int ret, fd; |     int ret, fd; | ||||||
|     uint32_t new_vid; |     uint32_t new_vid; | ||||||
| @@ -2151,8 +2178,10 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) | |||||||
|     datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id); |     datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id); | ||||||
|  |  | ||||||
|     /* refresh inode. */ |     /* refresh inode. */ | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         ret = fd; |         ret = fd; | ||||||
|         goto cleanup; |         goto cleanup; | ||||||
|     } |     } | ||||||
| @@ -2164,8 +2193,10 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) | |||||||
|         goto cleanup; |         goto cleanup; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ret = do_sd_create(s, &new_vid, 1); |     ret = do_sd_create(s, &new_vid, 1, &local_err); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         error_report("failed to create inode for snapshot. %s", |         error_report("failed to create inode for snapshot. %s", | ||||||
|                      strerror(errno)); |                      strerror(errno)); | ||||||
|         goto cleanup; |         goto cleanup; | ||||||
| @@ -2249,6 +2280,7 @@ static int sd_snapshot_delete(BlockDriverState *bs, | |||||||
|  |  | ||||||
| static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) | static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     BDRVSheepdogState *s = bs->opaque; |     BDRVSheepdogState *s = bs->opaque; | ||||||
|     SheepdogReq req; |     SheepdogReq req; | ||||||
|     int fd, nr = 1024, ret, max = BITS_TO_LONGS(SD_NR_VDIS) * sizeof(long); |     int fd, nr = 1024, ret, max = BITS_TO_LONGS(SD_NR_VDIS) * sizeof(long); | ||||||
| @@ -2263,8 +2295,10 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) | |||||||
|  |  | ||||||
|     vdi_inuse = g_malloc(max); |     vdi_inuse = g_malloc(max); | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         ret = fd; |         ret = fd; | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
| @@ -2290,8 +2324,10 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) | |||||||
|     hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT); |     hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT); | ||||||
|     start_nr = hval & (SD_NR_VDIS - 1); |     start_nr = hval & (SD_NR_VDIS - 1); | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         ret = fd; |         ret = fd; | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
| @@ -2341,6 +2377,7 @@ out: | |||||||
| static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, | static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, | ||||||
|                                 int64_t pos, int size, int load) |                                 int64_t pos, int size, int load) | ||||||
| { | { | ||||||
|  |     Error *local_err = NULL; | ||||||
|     bool create; |     bool create; | ||||||
|     int fd, ret = 0, remaining = size; |     int fd, ret = 0, remaining = size; | ||||||
|     unsigned int data_len; |     unsigned int data_len; | ||||||
| @@ -2349,8 +2386,10 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, | |||||||
|     uint32_t vdi_index; |     uint32_t vdi_index; | ||||||
|     uint32_t vdi_id = load ? s->inode.parent_vdi_id : s->inode.vdi_id; |     uint32_t vdi_id = load ? s->inode.parent_vdi_id : s->inode.vdi_id; | ||||||
|  |  | ||||||
|     fd = connect_to_sdog(s); |     fd = connect_to_sdog(s, &local_err); | ||||||
|     if (fd < 0) { |     if (fd < 0) { | ||||||
|  |         error_report("%s", error_get_pretty(local_err));; | ||||||
|  |         error_free(local_err); | ||||||
|         return fd; |         return fd; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										147
									
								
								block/ssh.c
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								block/ssh.c
									
									
									
									
									
								
							| @@ -106,30 +106,59 @@ static void ssh_state_free(BDRVSSHState *s) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Wrappers around error_report which make sure to dump as much | static void GCC_FMT_ATTR(3, 4) | ||||||
|  * information from libssh2 as possible. | session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) | ||||||
|  */ |  | ||||||
| static void GCC_FMT_ATTR(2, 3) |  | ||||||
| session_error_report(BDRVSSHState *s, const char *fs, ...) |  | ||||||
| { | { | ||||||
|     va_list args; |     va_list args; | ||||||
|  |     char *msg; | ||||||
|  |  | ||||||
|     va_start(args, fs); |     va_start(args, fs); | ||||||
|     error_vprintf(fs, args); |     msg = g_strdup_vprintf(fs, args); | ||||||
|  |     va_end(args); | ||||||
|  |  | ||||||
|     if ((s)->session) { |     if (s->session) { | ||||||
|         char *ssh_err; |         char *ssh_err; | ||||||
|         int ssh_err_code; |         int ssh_err_code; | ||||||
|  |  | ||||||
|         libssh2_session_last_error((s)->session, &ssh_err, NULL, 0); |  | ||||||
|         /* This is not an errno.  See <libssh2.h>. */ |         /* This is not an errno.  See <libssh2.h>. */ | ||||||
|         ssh_err_code = libssh2_session_last_errno((s)->session); |         ssh_err_code = libssh2_session_last_error(s->session, | ||||||
|  |                                                   &ssh_err, NULL, 0); | ||||||
|         error_printf(": %s (libssh2 error code: %d)", ssh_err, ssh_err_code); |         error_setg(errp, "%s: %s (libssh2 error code: %d)", | ||||||
|  |                    msg, ssh_err, ssh_err_code); | ||||||
|  |     } else { | ||||||
|  |         error_setg(errp, "%s", msg); | ||||||
|     } |     } | ||||||
|  |     g_free(msg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void GCC_FMT_ATTR(3, 4) | ||||||
|  | sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) | ||||||
|  | { | ||||||
|  |     va_list args; | ||||||
|  |     char *msg; | ||||||
|  |  | ||||||
|  |     va_start(args, fs); | ||||||
|  |     msg = g_strdup_vprintf(fs, args); | ||||||
|     va_end(args); |     va_end(args); | ||||||
|     error_printf("\n"); |  | ||||||
|  |     if (s->sftp) { | ||||||
|  |         char *ssh_err; | ||||||
|  |         int ssh_err_code; | ||||||
|  |         unsigned long sftp_err_code; | ||||||
|  |  | ||||||
|  |         /* This is not an errno.  See <libssh2.h>. */ | ||||||
|  |         ssh_err_code = libssh2_session_last_error(s->session, | ||||||
|  |                                                   &ssh_err, NULL, 0); | ||||||
|  |         /* See <libssh2_sftp.h>. */ | ||||||
|  |         sftp_err_code = libssh2_sftp_last_error((s)->sftp); | ||||||
|  |  | ||||||
|  |         error_setg(errp, | ||||||
|  |                    "%s: %s (libssh2 error code: %d, sftp error code: %lu)", | ||||||
|  |                    msg, ssh_err, ssh_err_code, sftp_err_code); | ||||||
|  |     } else { | ||||||
|  |         error_setg(errp, "%s", msg); | ||||||
|  |     } | ||||||
|  |     g_free(msg); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void GCC_FMT_ATTR(2, 3) | static void GCC_FMT_ATTR(2, 3) | ||||||
| @@ -145,9 +174,9 @@ sftp_error_report(BDRVSSHState *s, const char *fs, ...) | |||||||
|         int ssh_err_code; |         int ssh_err_code; | ||||||
|         unsigned long sftp_err_code; |         unsigned long sftp_err_code; | ||||||
|  |  | ||||||
|         libssh2_session_last_error((s)->session, &ssh_err, NULL, 0); |  | ||||||
|         /* This is not an errno.  See <libssh2.h>. */ |         /* This is not an errno.  See <libssh2.h>. */ | ||||||
|         ssh_err_code = libssh2_session_last_errno((s)->session); |         ssh_err_code = libssh2_session_last_error(s->session, | ||||||
|  |                                                   &ssh_err, NULL, 0); | ||||||
|         /* See <libssh2_sftp.h>. */ |         /* See <libssh2_sftp.h>. */ | ||||||
|         sftp_err_code = libssh2_sftp_last_error((s)->sftp); |         sftp_err_code = libssh2_sftp_last_error((s)->sftp); | ||||||
|  |  | ||||||
| @@ -243,7 +272,7 @@ static void ssh_parse_filename(const char *filename, QDict *options, | |||||||
| } | } | ||||||
|  |  | ||||||
| static int check_host_key_knownhosts(BDRVSSHState *s, | static int check_host_key_knownhosts(BDRVSSHState *s, | ||||||
|                                      const char *host, int port) |                                      const char *host, int port, Error **errp) | ||||||
| { | { | ||||||
|     const char *home; |     const char *home; | ||||||
|     char *knh_file = NULL; |     char *knh_file = NULL; | ||||||
| @@ -257,14 +286,15 @@ static int check_host_key_knownhosts(BDRVSSHState *s, | |||||||
|     hostkey = libssh2_session_hostkey(s->session, &len, &type); |     hostkey = libssh2_session_hostkey(s->session, &len, &type); | ||||||
|     if (!hostkey) { |     if (!hostkey) { | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "failed to read remote host key"); |         session_error_setg(errp, s, "failed to read remote host key"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     knh = libssh2_knownhost_init(s->session); |     knh = libssh2_knownhost_init(s->session); | ||||||
|     if (!knh) { |     if (!knh) { | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "failed to initialize known hosts support"); |         session_error_setg(errp, s, | ||||||
|  |                            "failed to initialize known hosts support"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -289,21 +319,23 @@ static int check_host_key_knownhosts(BDRVSSHState *s, | |||||||
|         break; |         break; | ||||||
|     case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: |     case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "host key does not match the one in known_hosts (found key %s)", |         session_error_setg(errp, s, | ||||||
|                              found->key); |                       "host key does not match the one in known_hosts" | ||||||
|  |                       " (found key %s)", found->key); | ||||||
|         goto out; |         goto out; | ||||||
|     case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND: |     case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND: | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "no host key was found in known_hosts"); |         session_error_setg(errp, s, "no host key was found in known_hosts"); | ||||||
|         goto out; |         goto out; | ||||||
|     case LIBSSH2_KNOWNHOST_CHECK_FAILURE: |     case LIBSSH2_KNOWNHOST_CHECK_FAILURE: | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "failure matching the host key with known_hosts"); |         session_error_setg(errp, s, | ||||||
|  |                       "failure matching the host key with known_hosts"); | ||||||
|         goto out; |         goto out; | ||||||
|     default: |     default: | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "unknown error matching the host key with known_hosts (%d)", |         session_error_setg(errp, s, "unknown error matching the host key" | ||||||
|                              r); |                       " with known_hosts (%d)", r); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -358,19 +390,19 @@ static int compare_fingerprint(const unsigned char *fingerprint, size_t len, | |||||||
|  |  | ||||||
| static int | static int | ||||||
| check_host_key_hash(BDRVSSHState *s, const char *hash, | check_host_key_hash(BDRVSSHState *s, const char *hash, | ||||||
|                     int hash_type, size_t fingerprint_len) |                     int hash_type, size_t fingerprint_len, Error **errp) | ||||||
| { | { | ||||||
|     const char *fingerprint; |     const char *fingerprint; | ||||||
|  |  | ||||||
|     fingerprint = libssh2_hostkey_hash(s->session, hash_type); |     fingerprint = libssh2_hostkey_hash(s->session, hash_type); | ||||||
|     if (!fingerprint) { |     if (!fingerprint) { | ||||||
|         session_error_report(s, "failed to read remote host key"); |         session_error_setg(errp, s, "failed to read remote host key"); | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len, |     if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len, | ||||||
|                            hash) != 0) { |                            hash) != 0) { | ||||||
|         error_report("remote host key does not match host_key_check '%s'", |         error_setg(errp, "remote host key does not match host_key_check '%s'", | ||||||
|                    hash); |                    hash); | ||||||
|         return -EPERM; |         return -EPERM; | ||||||
|     } |     } | ||||||
| @@ -379,7 +411,7 @@ check_host_key_hash(BDRVSSHState *s, const char *hash, | |||||||
| } | } | ||||||
|  |  | ||||||
| static int check_host_key(BDRVSSHState *s, const char *host, int port, | static int check_host_key(BDRVSSHState *s, const char *host, int port, | ||||||
|                           const char *host_key_check) |                           const char *host_key_check, Error **errp) | ||||||
| { | { | ||||||
|     /* host_key_check=no */ |     /* host_key_check=no */ | ||||||
|     if (strcmp(host_key_check, "no") == 0) { |     if (strcmp(host_key_check, "no") == 0) { | ||||||
| @@ -389,25 +421,25 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port, | |||||||
|     /* host_key_check=md5:xx:yy:zz:... */ |     /* host_key_check=md5:xx:yy:zz:... */ | ||||||
|     if (strncmp(host_key_check, "md5:", 4) == 0) { |     if (strncmp(host_key_check, "md5:", 4) == 0) { | ||||||
|         return check_host_key_hash(s, &host_key_check[4], |         return check_host_key_hash(s, &host_key_check[4], | ||||||
|                                    LIBSSH2_HOSTKEY_HASH_MD5, 16); |                                    LIBSSH2_HOSTKEY_HASH_MD5, 16, errp); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* host_key_check=sha1:xx:yy:zz:... */ |     /* host_key_check=sha1:xx:yy:zz:... */ | ||||||
|     if (strncmp(host_key_check, "sha1:", 5) == 0) { |     if (strncmp(host_key_check, "sha1:", 5) == 0) { | ||||||
|         return check_host_key_hash(s, &host_key_check[5], |         return check_host_key_hash(s, &host_key_check[5], | ||||||
|                                    LIBSSH2_HOSTKEY_HASH_SHA1, 20); |                                    LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* host_key_check=yes */ |     /* host_key_check=yes */ | ||||||
|     if (strcmp(host_key_check, "yes") == 0) { |     if (strcmp(host_key_check, "yes") == 0) { | ||||||
|         return check_host_key_knownhosts(s, host, port); |         return check_host_key_knownhosts(s, host, port, errp); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     error_report("unknown host_key_check setting (%s)", host_key_check); |     error_setg(errp, "unknown host_key_check setting (%s)", host_key_check); | ||||||
|     return -EINVAL; |     return -EINVAL; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int authenticate(BDRVSSHState *s, const char *user) | static int authenticate(BDRVSSHState *s, const char *user, Error **errp) | ||||||
| { | { | ||||||
|     int r, ret; |     int r, ret; | ||||||
|     const char *userauthlist; |     const char *userauthlist; | ||||||
| @@ -418,7 +450,8 @@ static int authenticate(BDRVSSHState *s, const char *user) | |||||||
|     userauthlist = libssh2_userauth_list(s->session, user, strlen(user)); |     userauthlist = libssh2_userauth_list(s->session, user, strlen(user)); | ||||||
|     if (strstr(userauthlist, "publickey") == NULL) { |     if (strstr(userauthlist, "publickey") == NULL) { | ||||||
|         ret = -EPERM; |         ret = -EPERM; | ||||||
|         error_report("remote server does not support \"publickey\" authentication"); |         error_setg(errp, | ||||||
|  |                 "remote server does not support \"publickey\" authentication"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -426,17 +459,18 @@ static int authenticate(BDRVSSHState *s, const char *user) | |||||||
|     agent = libssh2_agent_init(s->session); |     agent = libssh2_agent_init(s->session); | ||||||
|     if (!agent) { |     if (!agent) { | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "failed to initialize ssh-agent support"); |         session_error_setg(errp, s, "failed to initialize ssh-agent support"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|     if (libssh2_agent_connect(agent)) { |     if (libssh2_agent_connect(agent)) { | ||||||
|         ret = -ECONNREFUSED; |         ret = -ECONNREFUSED; | ||||||
|         session_error_report(s, "failed to connect to ssh-agent"); |         session_error_setg(errp, s, "failed to connect to ssh-agent"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|     if (libssh2_agent_list_identities(agent)) { |     if (libssh2_agent_list_identities(agent)) { | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "failed requesting identities from ssh-agent"); |         session_error_setg(errp, s, | ||||||
|  |                            "failed requesting identities from ssh-agent"); | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -447,7 +481,8 @@ static int authenticate(BDRVSSHState *s, const char *user) | |||||||
|         } |         } | ||||||
|         if (r < 0) { |         if (r < 0) { | ||||||
|             ret = -EINVAL; |             ret = -EINVAL; | ||||||
|             session_error_report(s, "failed to obtain identity from ssh-agent"); |             session_error_setg(errp, s, | ||||||
|  |                                "failed to obtain identity from ssh-agent"); | ||||||
|             goto out; |             goto out; | ||||||
|         } |         } | ||||||
|         r = libssh2_agent_userauth(agent, user, identity); |         r = libssh2_agent_userauth(agent, user, identity); | ||||||
| @@ -461,7 +496,7 @@ static int authenticate(BDRVSSHState *s, const char *user) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     ret = -EPERM; |     ret = -EPERM; | ||||||
|     error_report("failed to authenticate using publickey authentication " |     error_setg(errp, "failed to authenticate using publickey authentication " | ||||||
|                "and the identities held by your ssh-agent"); |                "and the identities held by your ssh-agent"); | ||||||
|  |  | ||||||
|  out: |  out: | ||||||
| @@ -476,10 +511,9 @@ static int authenticate(BDRVSSHState *s, const char *user) | |||||||
| } | } | ||||||
|  |  | ||||||
| static int connect_to_ssh(BDRVSSHState *s, QDict *options, | static int connect_to_ssh(BDRVSSHState *s, QDict *options, | ||||||
|                           int ssh_flags, int creat_mode) |                           int ssh_flags, int creat_mode, Error **errp) | ||||||
| { | { | ||||||
|     int r, ret; |     int r, ret; | ||||||
|     Error *err = NULL; |  | ||||||
|     const char *host, *user, *path, *host_key_check; |     const char *host, *user, *path, *host_key_check; | ||||||
|     int port; |     int port; | ||||||
|  |  | ||||||
| @@ -498,6 +532,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, | |||||||
|     } else { |     } else { | ||||||
|         user = g_get_user_name(); |         user = g_get_user_name(); | ||||||
|         if (!user) { |         if (!user) { | ||||||
|  |             error_setg_errno(errp, errno, "Can't get user name"); | ||||||
|             ret = -errno; |             ret = -errno; | ||||||
|             goto err; |             goto err; | ||||||
|         } |         } | ||||||
| @@ -514,11 +549,9 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, | |||||||
|     s->hostport = g_strdup_printf("%s:%d", host, port); |     s->hostport = g_strdup_printf("%s:%d", host, port); | ||||||
|  |  | ||||||
|     /* Open the socket and connect. */ |     /* Open the socket and connect. */ | ||||||
|     s->sock = inet_connect(s->hostport, &err); |     s->sock = inet_connect(s->hostport, errp); | ||||||
|     if (err != NULL) { |     if (s->sock < 0) { | ||||||
|         ret = -errno; |         ret = -errno; | ||||||
|         qerror_report_err(err); |  | ||||||
|         error_free(err); |  | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -526,7 +559,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, | |||||||
|     s->session = libssh2_session_init(); |     s->session = libssh2_session_init(); | ||||||
|     if (!s->session) { |     if (!s->session) { | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "failed to initialize libssh2 session"); |         session_error_setg(errp, s, "failed to initialize libssh2 session"); | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -537,18 +570,18 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, | |||||||
|     r = libssh2_session_handshake(s->session, s->sock); |     r = libssh2_session_handshake(s->session, s->sock); | ||||||
|     if (r != 0) { |     if (r != 0) { | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         session_error_report(s, "failed to establish SSH session"); |         session_error_setg(errp, s, "failed to establish SSH session"); | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Check the remote host's key against known_hosts. */ |     /* Check the remote host's key against known_hosts. */ | ||||||
|     ret = check_host_key(s, host, port, host_key_check); |     ret = check_host_key(s, host, port, host_key_check, errp); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Authenticate. */ |     /* Authenticate. */ | ||||||
|     ret = authenticate(s, user); |     ret = authenticate(s, user, errp); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
| @@ -556,7 +589,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, | |||||||
|     /* Start SFTP. */ |     /* Start SFTP. */ | ||||||
|     s->sftp = libssh2_sftp_init(s->session); |     s->sftp = libssh2_sftp_init(s->session); | ||||||
|     if (!s->sftp) { |     if (!s->sftp) { | ||||||
|         session_error_report(s, "failed to initialize sftp handle"); |         session_error_setg(errp, s, "failed to initialize sftp handle"); | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
| @@ -566,14 +599,14 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, | |||||||
|             path, ssh_flags, creat_mode); |             path, ssh_flags, creat_mode); | ||||||
|     s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode); |     s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode); | ||||||
|     if (!s->sftp_handle) { |     if (!s->sftp_handle) { | ||||||
|         session_error_report(s, "failed to open remote file '%s'", path); |         session_error_setg(errp, s, "failed to open remote file '%s'", path); | ||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs); |     r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs); | ||||||
|     if (r < 0) { |     if (r < 0) { | ||||||
|         sftp_error_report(s, "failed to read file attributes"); |         sftp_error_setg(errp, s, "failed to read file attributes"); | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -623,7 +656,7 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Start up SSH. */ |     /* Start up SSH. */ | ||||||
|     ret = connect_to_ssh(s, options, ssh_flags, 0); |     ret = connect_to_ssh(s, options, ssh_flags, 0, errp); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
| @@ -655,7 +688,6 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options, | |||||||
|                       Error **errp) |                       Error **errp) | ||||||
| { | { | ||||||
|     int r, ret; |     int r, ret; | ||||||
|     Error *local_err = NULL; |  | ||||||
|     int64_t total_size = 0; |     int64_t total_size = 0; | ||||||
|     QDict *uri_options = NULL; |     QDict *uri_options = NULL; | ||||||
|     BDRVSSHState s; |     BDRVSSHState s; | ||||||
| @@ -674,17 +706,16 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options, | |||||||
|     DPRINTF("total_size=%" PRIi64, total_size); |     DPRINTF("total_size=%" PRIi64, total_size); | ||||||
|  |  | ||||||
|     uri_options = qdict_new(); |     uri_options = qdict_new(); | ||||||
|     r = parse_uri(filename, uri_options, &local_err); |     r = parse_uri(filename, uri_options, errp); | ||||||
|     if (r < 0) { |     if (r < 0) { | ||||||
|         qerror_report_err(local_err); |  | ||||||
|         error_free(local_err); |  | ||||||
|         ret = r; |         ret = r; | ||||||
|         goto out; |         goto out; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     r = connect_to_ssh(&s, uri_options, |     r = connect_to_ssh(&s, uri_options, | ||||||
|                        LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE| |                        LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE| | ||||||
|                        LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 0644); |                        LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, | ||||||
|  |                        0644, errp); | ||||||
|     if (r < 0) { |     if (r < 0) { | ||||||
|         ret = r; |         ret = r; | ||||||
|         goto out; |         goto out; | ||||||
| @@ -694,7 +725,7 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options, | |||||||
|         libssh2_sftp_seek64(s.sftp_handle, total_size-1); |         libssh2_sftp_seek64(s.sftp_handle, total_size-1); | ||||||
|         r2 = libssh2_sftp_write(s.sftp_handle, c, 1); |         r2 = libssh2_sftp_write(s.sftp_handle, c, 1); | ||||||
|         if (r2 < 0) { |         if (r2 < 0) { | ||||||
|             sftp_error_report(&s, "truncate failed"); |             sftp_error_setg(errp, &s, "truncate failed"); | ||||||
|             ret = -EINVAL; |             ret = -EINVAL; | ||||||
|             goto out; |             goto out; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -60,7 +60,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base, | |||||||
|     /* Must assign before bdrv_delete() to prevent traversing dangling pointer |     /* Must assign before bdrv_delete() to prevent traversing dangling pointer | ||||||
|      * while we delete backing image instances. |      * while we delete backing image instances. | ||||||
|      */ |      */ | ||||||
|     top->backing_hd = base; |     bdrv_set_backing_hd(top, base); | ||||||
|  |  | ||||||
|     while (intermediate) { |     while (intermediate) { | ||||||
|         BlockDriverState *unused; |         BlockDriverState *unused; | ||||||
| @@ -72,7 +72,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base, | |||||||
|  |  | ||||||
|         unused = intermediate; |         unused = intermediate; | ||||||
|         intermediate = intermediate->backing_hd; |         intermediate = intermediate->backing_hd; | ||||||
|         unused->backing_hd = NULL; |         bdrv_set_backing_hd(unused, NULL); | ||||||
|         bdrv_unref(unused); |         bdrv_unref(unused); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -472,10 +472,17 @@ static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s, | |||||||
|             s->curr_header = 0; |             s->curr_header = 0; | ||||||
|         } else if (h2_seq > h1_seq) { |         } else if (h2_seq > h1_seq) { | ||||||
|             s->curr_header = 1; |             s->curr_header = 1; | ||||||
|  |         } else { | ||||||
|  |             /* The Microsoft Disk2VHD tool will create 2 identical | ||||||
|  |              * headers, with identical sequence numbers.  If the headers are | ||||||
|  |              * identical, don't consider the file corrupt */ | ||||||
|  |             if (!memcmp(header1, header2, sizeof(VHDXHeader))) { | ||||||
|  |                 s->curr_header = 0; | ||||||
|             } else { |             } else { | ||||||
|                 goto fail; |                 goto fail; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     vhdx_region_register(s, s->headers[s->curr_header]->log_offset, |     vhdx_region_register(s, s->headers[s->curr_header]->log_offset, | ||||||
|                             s->headers[s->curr_header]->log_length); |                             s->headers[s->curr_header]->log_length); | ||||||
|   | |||||||
| @@ -831,7 +831,8 @@ static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num) | |||||||
| } | } | ||||||
|  |  | ||||||
| static int init_directories(BDRVVVFATState* s, | static int init_directories(BDRVVVFATState* s, | ||||||
|                             const char *dirname, int heads, int secs) |                             const char *dirname, int heads, int secs, | ||||||
|  |                             Error **errp) | ||||||
| { | { | ||||||
|     bootsector_t* bootsector; |     bootsector_t* bootsector; | ||||||
|     mapping_t* mapping; |     mapping_t* mapping; | ||||||
| @@ -892,7 +893,7 @@ static int init_directories(BDRVVVFATState* s, | |||||||
|         if (mapping->mode & MODE_DIRECTORY) { |         if (mapping->mode & MODE_DIRECTORY) { | ||||||
| 	    mapping->begin = cluster; | 	    mapping->begin = cluster; | ||||||
| 	    if(read_directory(s, i)) { | 	    if(read_directory(s, i)) { | ||||||
| 		fprintf(stderr, "Could not read directory %s\n", |                 error_setg(errp, "Could not read directory %s", | ||||||
|                            mapping->path); |                            mapping->path); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	    } | 	    } | ||||||
| @@ -919,9 +920,10 @@ static int init_directories(BDRVVVFATState* s, | |||||||
| 	cluster = mapping->end; | 	cluster = mapping->end; | ||||||
|  |  | ||||||
| 	if(cluster > s->cluster_count) { | 	if(cluster > s->cluster_count) { | ||||||
| 	    fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n", |             error_setg(errp, | ||||||
|  |                        "Directory does not fit in FAT%d (capacity %.2f MB)", | ||||||
|                        s->fat_type, s->sector_count / 2000.0); |                        s->fat_type, s->sector_count / 2000.0); | ||||||
| 	    return -EINVAL; |             return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* fix fat for entry */ | 	/* fix fat for entry */ | ||||||
| @@ -979,7 +981,7 @@ static int init_directories(BDRVVVFATState* s, | |||||||
| static BDRVVVFATState *vvv = NULL; | static BDRVVVFATState *vvv = NULL; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| static int enable_write_target(BDRVVVFATState *s); | static int enable_write_target(BDRVVVFATState *s, Error **errp); | ||||||
| static int is_consistent(BDRVVVFATState *s); | static int is_consistent(BDRVVVFATState *s); | ||||||
|  |  | ||||||
| static void vvfat_rebind(BlockDriverState *bs) | static void vvfat_rebind(BlockDriverState *bs) | ||||||
| @@ -1160,7 +1162,7 @@ DLOG(if (stderr == NULL) { | |||||||
|     s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1); |     s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1); | ||||||
|  |  | ||||||
|     if (qemu_opt_get_bool(opts, "rw", false)) { |     if (qemu_opt_get_bool(opts, "rw", false)) { | ||||||
|         ret = enable_write_target(s); |         ret = enable_write_target(s, errp); | ||||||
|         if (ret < 0) { |         if (ret < 0) { | ||||||
|             goto fail; |             goto fail; | ||||||
|         } |         } | ||||||
| @@ -1169,7 +1171,7 @@ DLOG(if (stderr == NULL) { | |||||||
|  |  | ||||||
|     bs->total_sectors = cyls * heads * secs; |     bs->total_sectors = cyls * heads * secs; | ||||||
|  |  | ||||||
|     if (init_directories(s, dirname, heads, secs)) { |     if (init_directories(s, dirname, heads, secs, errp)) { | ||||||
|         ret = -EIO; |         ret = -EIO; | ||||||
|         goto fail; |         goto fail; | ||||||
|     } |     } | ||||||
| @@ -2904,11 +2906,10 @@ static BlockDriver vvfat_write_target = { | |||||||
|     .bdrv_close         = write_target_close, |     .bdrv_close         = write_target_close, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int enable_write_target(BDRVVVFATState *s) | static int enable_write_target(BDRVVVFATState *s, Error **errp) | ||||||
| { | { | ||||||
|     BlockDriver *bdrv_qcow; |     BlockDriver *bdrv_qcow; | ||||||
|     QEMUOptionParameter *options; |     QEMUOptionParameter *options; | ||||||
|     Error *local_err = NULL; |  | ||||||
|     int ret; |     int ret; | ||||||
|     int size = sector2cluster(s, s->sector_count); |     int size = sector2cluster(s, s->sector_count); | ||||||
|     s->used_clusters = calloc(size, 1); |     s->used_clusters = calloc(size, 1); | ||||||
| @@ -2918,6 +2919,7 @@ static int enable_write_target(BDRVVVFATState *s) | |||||||
|     s->qcow_filename = g_malloc(1024); |     s->qcow_filename = g_malloc(1024); | ||||||
|     ret = get_tmp_filename(s->qcow_filename, 1024); |     ret = get_tmp_filename(s->qcow_filename, 1024); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|  |         error_setg_errno(errp, -ret, "can't create temporary file"); | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2926,20 +2928,16 @@ static int enable_write_target(BDRVVVFATState *s) | |||||||
|     set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512); |     set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512); | ||||||
|     set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:"); |     set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:"); | ||||||
|  |  | ||||||
|     ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, &local_err); |     ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, errp); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         qerror_report_err(local_err); |  | ||||||
|         error_free(local_err); |  | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     s->qcow = NULL; |     s->qcow = NULL; | ||||||
|     ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL, |     ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL, | ||||||
|             BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow, |                     BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, | ||||||
|             &local_err); |                     bdrv_qcow, errp); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         qerror_report_err(local_err); |  | ||||||
|         error_free(local_err); |  | ||||||
|         goto err; |         goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2947,7 +2945,7 @@ static int enable_write_target(BDRVVVFATState *s) | |||||||
|     unlink(s->qcow_filename); |     unlink(s->qcow_filename); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     s->bs->backing_hd = bdrv_new("", &error_abort); |     bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort)); | ||||||
|     s->bs->backing_hd->drv = &vvfat_write_target; |     s->bs->backing_hd->drv = &vvfat_write_target; | ||||||
|     s->bs->backing_hd->opaque = g_malloc(sizeof(void*)); |     s->bs->backing_hd->opaque = g_malloc(sizeof(void*)); | ||||||
|     *(void**)s->bs->backing_hd->opaque = s; |     *(void**)s->bs->backing_hd->opaque = s; | ||||||
|   | |||||||
| @@ -27,8 +27,8 @@ static void nbd_accept(void *opaque) | |||||||
|     socklen_t addr_len = sizeof(addr); |     socklen_t addr_len = sizeof(addr); | ||||||
|  |  | ||||||
|     int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); |     int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); | ||||||
|     if (fd >= 0) { |     if (fd >= 0 && !nbd_client_new(NULL, fd, nbd_client_put)) { | ||||||
|         nbd_client_new(NULL, fd, nbd_client_put); |         close(fd); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								blockdev.c
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								blockdev.c
									
									
									
									
									
								
							| @@ -34,7 +34,6 @@ | |||||||
| #include "hw/block/block.h" | #include "hw/block/block.h" | ||||||
| #include "block/blockjob.h" | #include "block/blockjob.h" | ||||||
| #include "monitor/monitor.h" | #include "monitor/monitor.h" | ||||||
| #include "qapi/qmp/qerror.h" |  | ||||||
| #include "qemu/option.h" | #include "qemu/option.h" | ||||||
| #include "qemu/config-file.h" | #include "qemu/config-file.h" | ||||||
| #include "qapi/qmp/types.h" | #include "qapi/qmp/types.h" | ||||||
| @@ -288,6 +287,25 @@ static int parse_block_error_action(const char *buf, bool is_read, Error **errp) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static inline int parse_enum_option(const char *lookup[], const char *buf, | ||||||
|  |                                     int max, int def, Error **errp) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |  | ||||||
|  |     if (!buf) { | ||||||
|  |         return def; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     for (i = 0; i < max; i++) { | ||||||
|  |         if (!strcmp(buf, lookup[i])) { | ||||||
|  |             return i; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     error_setg(errp, "invalid parameter value: %s", buf); | ||||||
|  |     return def; | ||||||
|  | } | ||||||
|  |  | ||||||
| static bool check_throttle_config(ThrottleConfig *cfg, Error **errp) | static bool check_throttle_config(ThrottleConfig *cfg, Error **errp) | ||||||
| { | { | ||||||
|     if (throttle_conflicting(cfg)) { |     if (throttle_conflicting(cfg)) { | ||||||
| @@ -324,6 +342,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, | |||||||
|     QemuOpts *opts; |     QemuOpts *opts; | ||||||
|     const char *id; |     const char *id; | ||||||
|     bool has_driver_specific_opts; |     bool has_driver_specific_opts; | ||||||
|  |     BlockdevDetectZeroesOptions detect_zeroes; | ||||||
|     BlockDriver *drv = NULL; |     BlockDriver *drv = NULL; | ||||||
|  |  | ||||||
|     /* Check common options by copying from bs_opts to opts, all other options |     /* Check common options by copying from bs_opts to opts, all other options | ||||||
| @@ -452,6 +471,24 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     detect_zeroes = | ||||||
|  |         parse_enum_option(BlockdevDetectZeroesOptions_lookup, | ||||||
|  |                           qemu_opt_get(opts, "detect-zeroes"), | ||||||
|  |                           BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX, | ||||||
|  |                           BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF, | ||||||
|  |                           &error); | ||||||
|  |     if (error) { | ||||||
|  |         error_propagate(errp, error); | ||||||
|  |         goto early_err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP && | ||||||
|  |         !(bdrv_flags & BDRV_O_UNMAP)) { | ||||||
|  |         error_setg(errp, "setting detect-zeroes to unmap is not allowed " | ||||||
|  |                          "without setting discard operation to unmap"); | ||||||
|  |         goto early_err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* init */ |     /* init */ | ||||||
|     dinfo = g_malloc0(sizeof(*dinfo)); |     dinfo = g_malloc0(sizeof(*dinfo)); | ||||||
|     dinfo->id = g_strdup(qemu_opts_id(opts)); |     dinfo->id = g_strdup(qemu_opts_id(opts)); | ||||||
| @@ -462,6 +499,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, | |||||||
|     } |     } | ||||||
|     dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; |     dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; | ||||||
|     dinfo->bdrv->read_only = ro; |     dinfo->bdrv->read_only = ro; | ||||||
|  |     dinfo->bdrv->detect_zeroes = detect_zeroes; | ||||||
|     dinfo->refcount = 1; |     dinfo->refcount = 1; | ||||||
|     if (serial != NULL) { |     if (serial != NULL) { | ||||||
|         dinfo->serial = g_strdup(serial); |         dinfo->serial = g_strdup(serial); | ||||||
| @@ -691,7 +729,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) | |||||||
|                                    &error_abort); |                                    &error_abort); | ||||||
|     qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err); |     qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err); | ||||||
|     if (local_err) { |     if (local_err) { | ||||||
|         qerror_report_err(local_err); |         error_report("%s", error_get_pretty(local_err)); | ||||||
|         error_free(local_err); |         error_free(local_err); | ||||||
|         goto fail; |         goto fail; | ||||||
|     } |     } | ||||||
| @@ -903,7 +941,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) | |||||||
|     dinfo = blockdev_init(filename, bs_opts, &local_err); |     dinfo = blockdev_init(filename, bs_opts, &local_err); | ||||||
|     if (dinfo == NULL) { |     if (dinfo == NULL) { | ||||||
|         if (local_err) { |         if (local_err) { | ||||||
|             qerror_report_err(local_err); |             error_report("%s", error_get_pretty(local_err)); | ||||||
|             error_free(local_err); |             error_free(local_err); | ||||||
|         } |         } | ||||||
|         goto fail; |         goto fail; | ||||||
| @@ -1295,8 +1333,8 @@ static void external_snapshot_prepare(BlkTransactionState *common, | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (bdrv_in_use(state->old_bs)) { |     if (bdrv_op_is_blocked(state->old_bs, | ||||||
|         error_set(errp, QERR_DEVICE_IN_USE, device); |                            BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1518,8 +1556,7 @@ exit: | |||||||
|  |  | ||||||
| static void eject_device(BlockDriverState *bs, int force, Error **errp) | static void eject_device(BlockDriverState *bs, int force, Error **errp) | ||||||
| { | { | ||||||
|     if (bdrv_in_use(bs)) { |     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { | ||||||
|         error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs)); |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (!bdrv_dev_has_removable_media(bs)) { |     if (!bdrv_dev_has_removable_media(bs)) { | ||||||
| @@ -1721,14 +1758,16 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) | |||||||
| { | { | ||||||
|     const char *id = qdict_get_str(qdict, "id"); |     const char *id = qdict_get_str(qdict, "id"); | ||||||
|     BlockDriverState *bs; |     BlockDriverState *bs; | ||||||
|  |     Error *local_err = NULL; | ||||||
|  |  | ||||||
|     bs = bdrv_find(id); |     bs = bdrv_find(id); | ||||||
|     if (!bs) { |     if (!bs) { | ||||||
|         qerror_report(QERR_DEVICE_NOT_FOUND, id); |         error_report("Device '%s' not found", id); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     if (bdrv_in_use(bs)) { |     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) { | ||||||
|         qerror_report(QERR_DEVICE_IN_USE, id); |         error_report("%s", error_get_pretty(local_err)); | ||||||
|  |         error_free(local_err); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1849,6 +1888,10 @@ void qmp_block_stream(const char *device, bool has_base, | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (base) { |     if (base) { | ||||||
|         base_bs = bdrv_find_backing_image(bs, base); |         base_bs = bdrv_find_backing_image(bs, base); | ||||||
|         if (base_bs == NULL) { |         if (base_bs == NULL) { | ||||||
| @@ -1893,6 +1936,10 @@ void qmp_block_commit(const char *device, | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT, errp)) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* default top_bs is the active layer */ |     /* default top_bs is the active layer */ | ||||||
|     top_bs = bs; |     top_bs = bs; | ||||||
|  |  | ||||||
| @@ -1984,8 +2031,7 @@ void qmp_drive_backup(const char *device, const char *target, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (bdrv_in_use(bs)) { |     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) { | ||||||
|         error_set(errp, QERR_DEVICE_IN_USE, device); |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2118,8 +2164,7 @@ void qmp_drive_mirror(const char *device, const char *target, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (bdrv_in_use(bs)) { |     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR, errp)) { | ||||||
|         error_set(errp, QERR_DEVICE_IN_USE, device); |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2455,6 +2500,10 @@ QemuOptsList qemu_common_drive_opts = { | |||||||
|             .name = "copy-on-read", |             .name = "copy-on-read", | ||||||
|             .type = QEMU_OPT_BOOL, |             .type = QEMU_OPT_BOOL, | ||||||
|             .help = "copy read data from backing file into image file", |             .help = "copy read data from backing file into image file", | ||||||
|  |         },{ | ||||||
|  |             .name = "detect-zeroes", | ||||||
|  |             .type = QEMU_OPT_STRING, | ||||||
|  |             .help = "try to optimize zero writes (off, on, unmap)", | ||||||
|         }, |         }, | ||||||
|         { /* end of list */ } |         { /* end of list */ } | ||||||
|     }, |     }, | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								blockjob.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								blockjob.c
									
									
									
									
									
								
							| @@ -41,14 +41,16 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, | |||||||
| { | { | ||||||
|     BlockJob *job; |     BlockJob *job; | ||||||
|  |  | ||||||
|     if (bs->job || bdrv_in_use(bs)) { |     if (bs->job) { | ||||||
|         error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs)); |         error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs)); | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|     bdrv_ref(bs); |     bdrv_ref(bs); | ||||||
|     bdrv_set_in_use(bs, 1); |  | ||||||
|  |  | ||||||
|     job = g_malloc0(driver->instance_size); |     job = g_malloc0(driver->instance_size); | ||||||
|  |     error_setg(&job->blocker, "block device is in use by block job: %s", | ||||||
|  |                BlockJobType_lookup[driver->job_type]); | ||||||
|  |     bdrv_op_block_all(bs, job->blocker); | ||||||
|  |  | ||||||
|     job->driver        = driver; |     job->driver        = driver; | ||||||
|     job->bs            = bs; |     job->bs            = bs; | ||||||
|     job->cb            = cb; |     job->cb            = cb; | ||||||
| @@ -63,8 +65,9 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, | |||||||
|         block_job_set_speed(job, speed, &local_err); |         block_job_set_speed(job, speed, &local_err); | ||||||
|         if (local_err) { |         if (local_err) { | ||||||
|             bs->job = NULL; |             bs->job = NULL; | ||||||
|  |             bdrv_op_unblock_all(bs, job->blocker); | ||||||
|  |             error_free(job->blocker); | ||||||
|             g_free(job); |             g_free(job); | ||||||
|             bdrv_set_in_use(bs, 0); |  | ||||||
|             error_propagate(errp, local_err); |             error_propagate(errp, local_err); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
| @@ -79,8 +82,9 @@ void block_job_completed(BlockJob *job, int ret) | |||||||
|     assert(bs->job == job); |     assert(bs->job == job); | ||||||
|     job->cb(job->opaque, ret); |     job->cb(job->opaque, ret); | ||||||
|     bs->job = NULL; |     bs->job = NULL; | ||||||
|  |     bdrv_op_unblock_all(bs, job->blocker); | ||||||
|  |     error_free(job->blocker); | ||||||
|     g_free(job); |     g_free(job); | ||||||
|     bdrv_set_in_use(bs, 0); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) | void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -2,26 +2,28 @@ | |||||||
| # | # | ||||||
| # qemu configure script (c) 2003 Fabrice Bellard | # qemu configure script (c) 2003 Fabrice Bellard | ||||||
| # | # | ||||||
| # set temporary file name |  | ||||||
| if test ! -z "$TMPDIR" ; then | # Temporary directory used for files created while | ||||||
|     TMPDIR1="${TMPDIR}" | # configure runs. Since it is in the build directory | ||||||
| elif test ! -z "$TEMPDIR" ; then | # we can safely blow away any previous version of it | ||||||
|     TMPDIR1="${TEMPDIR}" | # (and we need not jump through hoops to try to delete | ||||||
| else | # it when configure exits.) | ||||||
|     TMPDIR1="/tmp" | TMPDIR1="config-temp" | ||||||
|  | rm -rf "${TMPDIR1}" | ||||||
|  | mkdir -p "${TMPDIR1}" | ||||||
|  | if [ $? -ne 0 ]; then | ||||||
|  |     echo "ERROR: failed to create temporary directory" | ||||||
|  |     exit 1 | ||||||
| fi | fi | ||||||
|  |  | ||||||
| TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c" | TMPB="qemu-conf" | ||||||
| TMPB="qemu-conf-${RANDOM}-$$-${RANDOM}" | TMPC="${TMPDIR1}/${TMPB}.c" | ||||||
| TMPO="${TMPDIR1}/${TMPB}.o" | TMPO="${TMPDIR1}/${TMPB}.o" | ||||||
| TMPCXX="${TMPDIR1}/${TMPB}.cxx" | TMPCXX="${TMPDIR1}/${TMPB}.cxx" | ||||||
| TMPL="${TMPDIR1}/${TMPB}.lo" | TMPL="${TMPDIR1}/${TMPB}.lo" | ||||||
| TMPA="${TMPDIR1}/lib${TMPB}.la" | TMPA="${TMPDIR1}/lib${TMPB}.la" | ||||||
| TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe" | TMPE="${TMPDIR1}/${TMPB}.exe" | ||||||
|  |  | ||||||
| # NB: do not call "exit" in the trap handler; this is buggy with some shells; |  | ||||||
| # see <1285349658-3122-1-git-send-email-loic.minier@linaro.org> |  | ||||||
| trap "rm -f $TMPC $TMPO $TMPCXX $TMPE" EXIT INT QUIT TERM |  | ||||||
| rm -f config.log | rm -f config.log | ||||||
|  |  | ||||||
| # Print a helpful header at the top of config.log | # Print a helpful header at the top of config.log | ||||||
| @@ -317,7 +319,7 @@ glusterfs_discard="no" | |||||||
| glusterfs_zerofill="no" | glusterfs_zerofill="no" | ||||||
| virtio_blk_data_plane="" | virtio_blk_data_plane="" | ||||||
| gtk="" | gtk="" | ||||||
| gtkabi="2.0" | gtkabi="" | ||||||
| vte="" | vte="" | ||||||
| tpm="no" | tpm="no" | ||||||
| libssh2="" | libssh2="" | ||||||
| @@ -1970,6 +1972,18 @@ fi | |||||||
| ########################################## | ########################################## | ||||||
| # GTK probe | # GTK probe | ||||||
|  |  | ||||||
|  | if test "$gtkabi" = ""; then | ||||||
|  |     # The GTK ABI was not specified explicitly, so try whether 2.0 is available. | ||||||
|  |     # Use 3.0 as a fallback if that is available. | ||||||
|  |     if $pkg_config --exists "gtk+-2.0 >= 2.18.0"; then | ||||||
|  |         gtkabi=2.0 | ||||||
|  |     elif $pkg_config --exists "gtk+-3.0 >= 3.0.0"; then | ||||||
|  |         gtkabi=3.0 | ||||||
|  |     else | ||||||
|  |         gtkabi=2.0 | ||||||
|  |     fi | ||||||
|  | fi | ||||||
|  |  | ||||||
| if test "$gtk" != "no"; then | if test "$gtk" != "no"; then | ||||||
|     gtkpackage="gtk+-$gtkabi" |     gtkpackage="gtk+-$gtkabi" | ||||||
|     if test "$gtkabi" = "3.0" ; then |     if test "$gtkabi" = "3.0" ; then | ||||||
| @@ -1983,7 +1997,7 @@ if test "$gtk" != "no"; then | |||||||
|         libs_softmmu="$gtk_libs $libs_softmmu" |         libs_softmmu="$gtk_libs $libs_softmmu" | ||||||
|         gtk="yes" |         gtk="yes" | ||||||
|     elif test "$gtk" = "yes"; then |     elif test "$gtk" = "yes"; then | ||||||
|         feature_not_found "gtk" "Install gtk2 or gtk3 (requires --with-gtkabi=3.0 option to configure) devel" |         feature_not_found "gtk" "Install gtk2 or gtk3 devel" | ||||||
|     else |     else | ||||||
|         gtk="no" |         gtk="no" | ||||||
|     fi |     fi | ||||||
| @@ -2006,7 +2020,11 @@ if test "$vte" != "no"; then | |||||||
|         libs_softmmu="$vte_libs $libs_softmmu" |         libs_softmmu="$vte_libs $libs_softmmu" | ||||||
|         vte="yes" |         vte="yes" | ||||||
|     elif test "$vte" = "yes"; then |     elif test "$vte" = "yes"; then | ||||||
|         feature_not_found "vte" "Install libvte or libvte-2.90 (requires --with-gtkabi=3.0 option to configure) devel" |         if test "$gtkabi" = "3.0"; then | ||||||
|  |             feature_not_found "vte" "Install libvte-2.90 devel" | ||||||
|  |         else | ||||||
|  |             feature_not_found "vte" "Install libvte devel" | ||||||
|  |         fi | ||||||
|     else |     else | ||||||
|         vte="no" |         vte="no" | ||||||
|     fi |     fi | ||||||
| @@ -4029,11 +4047,14 @@ fi | |||||||
| if test "$pie" = "no" ; then | if test "$pie" = "no" ; then | ||||||
|   textseg_addr= |   textseg_addr= | ||||||
|   case "$cpu" in |   case "$cpu" in | ||||||
|     arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64 | x32) |     arm | i386 | ppc* | s390* | sparc* | x86_64 | x32) | ||||||
|  |       # ??? Rationale for choosing this address | ||||||
|       textseg_addr=0x60000000 |       textseg_addr=0x60000000 | ||||||
|       ;; |       ;; | ||||||
|     mips) |     mips) | ||||||
|       textseg_addr=0x400000 |       # A 256M aligned address, high in the address space, with enough | ||||||
|  |       # room for the code_gen_buffer above it before the stack. | ||||||
|  |       textseg_addr=0x60000000 | ||||||
|       ;; |       ;; | ||||||
|   esac |   esac | ||||||
|   if [ -n "$textseg_addr" ]; then |   if [ -n "$textseg_addr" ]; then | ||||||
| @@ -5219,3 +5240,4 @@ printf " '%s'" "$0" "$@" >>config.status | |||||||
| echo >>config.status | echo >>config.status | ||||||
| chmod +x config.status | chmod +x config.status | ||||||
|  |  | ||||||
|  | rm -r "$TMPDIR1" | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
| CONFIG_VIRTIO=y | CONFIG_VIRTIO=y | ||||||
| CONFIG_SCLPCONSOLE=y | CONFIG_SCLPCONSOLE=y | ||||||
| CONFIG_S390_FLIC=$(CONFIG_KVM) | CONFIG_S390_FLIC=y | ||||||
|  | CONFIG_S390_FLIC_KVM=$(CONFIG_KVM) | ||||||
|   | |||||||
| @@ -143,12 +143,12 @@ static void dma_bdrv_cb(void *opaque, int ret) | |||||||
|  |  | ||||||
|     dbs->acb = NULL; |     dbs->acb = NULL; | ||||||
|     dbs->sector_num += dbs->iov.size / 512; |     dbs->sector_num += dbs->iov.size / 512; | ||||||
|     dma_bdrv_unmap(dbs); |  | ||||||
|  |  | ||||||
|     if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) { |     if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) { | ||||||
|         dma_complete(dbs, ret); |         dma_complete(dbs, ret); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |     dma_bdrv_unmap(dbs); | ||||||
|  |  | ||||||
|     while (dbs->sg_cur_index < dbs->sg->nsg) { |     while (dbs->sg_cur_index < dbs->sg->nsg) { | ||||||
|         cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte; |         cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte; | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								docs/multiseat.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								docs/multiseat.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  |  | ||||||
|  | multiseat howto (with some multihead coverage) | ||||||
|  | ============================================== | ||||||
|  |  | ||||||
|  | host side | ||||||
|  | --------- | ||||||
|  |  | ||||||
|  | First you must compile qemu with a user interface supporting | ||||||
|  | multihead/multiseat and input event routing.  Right now this list is | ||||||
|  | pretty short: sdl2. | ||||||
|  |  | ||||||
|  |   ./configure --enable-sdl --with-sdlabi=2.0 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Next put together the qemu command line: | ||||||
|  |  | ||||||
|  | qemu	-enable-kvm -usb $memory $disk $whatever \ | ||||||
|  | 	-display sdl \ | ||||||
|  | 	-vga std \ | ||||||
|  | 	-device usb-tablet | ||||||
|  |  | ||||||
|  | That is it for the first head, which will use the standard vga, the | ||||||
|  | standard ps/2 keyboard (implicitly there) and the usb-tablet.  Now the | ||||||
|  | additional switches for the second head: | ||||||
|  |  | ||||||
|  | 	-device pci-bridge,addr=12.0,chassis_nr=2,id=head.2 \ | ||||||
|  | 	-device secondary-vga,bus=head.2,addr=02.0,id=video.2 \ | ||||||
|  | 	-device nec-usb-xhci,bus=head.2,addr=0f.0,id=usb.2 \ | ||||||
|  | 	-device usb-kbd,bus=usb.2.0,port=1,display=video.2 \ | ||||||
|  | 	-device usb-tablet,bus=usb.2.0,port=2,display=video.2 | ||||||
|  |  | ||||||
|  | This places a pci bridge in slot 12, connects a display adapter and | ||||||
|  | xhci (usb) controller to the bridge.  Then it adds a usb keyboard and | ||||||
|  | usb mouse, both connected to the xhci and linked to the display. | ||||||
|  |  | ||||||
|  | The "display=video2" sets up the input routing.  Any input coming from | ||||||
|  | the window which belongs to the video.2 display adapter will be routed | ||||||
|  | to these input devices. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | guest side | ||||||
|  | ---------- | ||||||
|  |  | ||||||
|  | You need a pretty recent linux guest.  systemd with loginctl.  kernel | ||||||
|  | 3.14+ with CONFIG_DRM_BOCHS enabled.  Fedora 20 will do.  Must be | ||||||
|  | fully updated for the new kernel though, i.e. the live iso doesn't cut | ||||||
|  | it. | ||||||
|  |  | ||||||
|  | Now we'll have to configure the guest.  Boot and login.  By default | ||||||
|  | all devices belong to seat0.  You can use "loginctl seat-status seat0" | ||||||
|  | to list them all (and to get the sysfs paths for cut+paste).  Now | ||||||
|  | we'll go assign all pci devices connected the pci bridge in slot 12 to | ||||||
|  | a new head: | ||||||
|  |  | ||||||
|  | loginctl attach seat-qemu \ | ||||||
|  | 	 /sys/devices/pci0000:00/0000:00:12.0/0000:01:02.0/drm/card1 | ||||||
|  | loginctl attach seat-qemu \ | ||||||
|  | 	 /sys/devices/pci0000:00/0000:00:12.0/0000:01:02.0/graphics/fb1 | ||||||
|  | loginctl attach seat-qemu \ | ||||||
|  | 	 /sys/devices/pci0000:00/0000:00:12.0/0000:01:0f.0/usb2 | ||||||
|  |  | ||||||
|  | Use "loginctl seat-status seat-qemu" to check the result.  It isn't | ||||||
|  | needed to assign the usb devices to the head individually, assigning a | ||||||
|  | usb (root) hub will automatically assign all usb devices connected to | ||||||
|  | it too. | ||||||
|  |  | ||||||
|  | BTW: loginctl writes udev rules to /etc/udev/rules.d to make these | ||||||
|  | device assignments permanent, so you need to do this only once. | ||||||
|  |  | ||||||
|  | Now simply restart gdm (rebooting will do too), and a login screen | ||||||
|  | should show up on the second head. | ||||||
|  |  | ||||||
|  | Enjoy! | ||||||
|  |  | ||||||
|  | -- | ||||||
|  | Gerd Hoffmann <kraxel@redhat.com> | ||||||
| @@ -48,7 +48,7 @@ The QAPI schema definitions can be modularized using the 'include' directive: | |||||||
|  { 'include': 'path/to/file.json'} |  { 'include': 'path/to/file.json'} | ||||||
|  |  | ||||||
| The directive is evaluated recursively, and include paths are relative to the | The directive is evaluated recursively, and include paths are relative to the | ||||||
| file using the directive. | file using the directive. Multiple includes of the same file are safe. | ||||||
|  |  | ||||||
|  |  | ||||||
| === Complex types === | === Complex types === | ||||||
| @@ -230,14 +230,13 @@ node structure that can be used to chain together a list of such types in | |||||||
| case we want to accept/return a list of this type with a command), and a | case we want to accept/return a list of this type with a command), and a | ||||||
| command which takes that type as a parameter and returns the same type: | command which takes that type as a parameter and returns the same type: | ||||||
|  |  | ||||||
|     mdroth@illuin:~/w/qemu2.git$ cat example-schema.json |     $ cat example-schema.json | ||||||
|     { 'type': 'UserDefOne', |     { 'type': 'UserDefOne', | ||||||
|       'data': { 'integer': 'int', 'string': 'str' } } |       'data': { 'integer': 'int', 'string': 'str' } } | ||||||
|  |  | ||||||
|     { 'command': 'my-command', |     { 'command': 'my-command', | ||||||
|       'data':    {'arg1': 'UserDefOne'}, |       'data':    {'arg1': 'UserDefOne'}, | ||||||
|       'returns': 'UserDefOne' } |       'returns': 'UserDefOne' } | ||||||
|     mdroth@illuin:~/w/qemu2.git$ |  | ||||||
|  |  | ||||||
| === scripts/qapi-types.py === | === scripts/qapi-types.py === | ||||||
|  |  | ||||||
| @@ -255,14 +254,25 @@ created code. | |||||||
|  |  | ||||||
| Example: | Example: | ||||||
|  |  | ||||||
|     mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \ |     $ python scripts/qapi-types.py --output-dir="qapi-generated" \ | ||||||
|       --output-dir="qapi-generated" --prefix="example-" --input-file=example-schema.json |     --prefix="example-" --input-file=example-schema.json | ||||||
|     mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c |     $ cat qapi-generated/example-qapi-types.c | ||||||
|     /* AUTOMATICALLY GENERATED, DO NOT MODIFY */ | [Uninteresting stuff omitted...] | ||||||
|  |  | ||||||
|     #include "qapi/qapi-dealloc-visitor.h" |     void qapi_free_UserDefOneList(UserDefOneList * obj) | ||||||
|     #include "example-qapi-types.h" |     { | ||||||
|     #include "example-qapi-visit.h" |         QapiDeallocVisitor *md; | ||||||
|  |         Visitor *v; | ||||||
|  |  | ||||||
|  |         if (!obj) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         md = qapi_dealloc_visitor_new(); | ||||||
|  |         v = qapi_dealloc_get_visitor(md); | ||||||
|  |         visit_type_UserDefOneList(v, &obj, NULL, NULL); | ||||||
|  |         qapi_dealloc_visitor_cleanup(md); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     void qapi_free_UserDefOne(UserDefOne * obj) |     void qapi_free_UserDefOne(UserDefOne * obj) | ||||||
|     { |     { | ||||||
| @@ -279,32 +289,38 @@ Example: | |||||||
|         qapi_dealloc_visitor_cleanup(md); |         qapi_dealloc_visitor_cleanup(md); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h |     $ cat qapi-generated/example-qapi-types.h | ||||||
|     /* AUTOMATICALLY GENERATED, DO NOT MODIFY */ | [Uninteresting stuff omitted...] | ||||||
|     #ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES |  | ||||||
|     #define QAPI_GENERATED_EXAMPLE_QAPI_TYPES |  | ||||||
|  |  | ||||||
|     #include "qapi/qapi-types-core.h" |     #ifndef EXAMPLE_QAPI_TYPES_H | ||||||
|  |     #define EXAMPLE_QAPI_TYPES_H | ||||||
|  |  | ||||||
|  | [Builtin types omitted...] | ||||||
|  |  | ||||||
|     typedef struct UserDefOne UserDefOne; |     typedef struct UserDefOne UserDefOne; | ||||||
|  |  | ||||||
|     typedef struct UserDefOneList |     typedef struct UserDefOneList | ||||||
|     { |     { | ||||||
|  |         union { | ||||||
|             UserDefOne *value; |             UserDefOne *value; | ||||||
|  |             uint64_t padding; | ||||||
|  |         }; | ||||||
|         struct UserDefOneList *next; |         struct UserDefOneList *next; | ||||||
|     } UserDefOneList; |     } UserDefOneList; | ||||||
|  |  | ||||||
|  | [Functions on builtin types omitted...] | ||||||
|  |  | ||||||
|     struct UserDefOne |     struct UserDefOne | ||||||
|     { |     { | ||||||
|         int64_t integer; |         int64_t integer; | ||||||
|         char * string; |         char * string; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     void qapi_free_UserDefOneList(UserDefOneList * obj); | ||||||
|     void qapi_free_UserDefOne(UserDefOne * obj); |     void qapi_free_UserDefOne(UserDefOne * obj); | ||||||
|  |  | ||||||
|     #endif |     #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| === scripts/qapi-visit.py === | === scripts/qapi-visit.py === | ||||||
|  |  | ||||||
| Used to generate the visitor functions used to walk through and convert | Used to generate the visitor functions used to walk through and convert | ||||||
| @@ -325,51 +341,78 @@ $(prefix)qapi-visit.h: declarations for previously mentioned visitor | |||||||
|  |  | ||||||
| Example: | Example: | ||||||
|  |  | ||||||
|     mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \ |     $ python scripts/qapi-visit.py --output-dir="qapi-generated" | ||||||
|         --output-dir="qapi-generated" --prefix="example-" --input-file=example-schema.json |     --prefix="example-" --input-file=example-schema.json | ||||||
|     mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c |     $ cat qapi-generated/example-qapi-visit.c | ||||||
|     /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ | [Uninteresting stuff omitted...] | ||||||
|  |  | ||||||
|     #include "example-qapi-visit.h" |     static void visit_type_UserDefOne_fields(Visitor *m, UserDefOne ** obj, Error **errp) | ||||||
|  |     { | ||||||
|  |         Error *err = NULL; | ||||||
|  |         visit_type_int(m, &(*obj)->integer, "integer", &err); | ||||||
|  |         if (err) { | ||||||
|  |             goto out; | ||||||
|  |         } | ||||||
|  |         visit_type_str(m, &(*obj)->string, "string", &err); | ||||||
|  |         if (err) { | ||||||
|  |             goto out; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     out: | ||||||
|  |         error_propagate(errp, err); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp) |     void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp) | ||||||
|     { |     { | ||||||
|         visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp); |         Error *err = NULL; | ||||||
|         visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp); |  | ||||||
|         visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp); |         visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), &err); | ||||||
|         visit_end_struct(m, errp); |         if (!err) { | ||||||
|  |             if (*obj) { | ||||||
|  |                 visit_type_UserDefOne_fields(m, obj, errp); | ||||||
|  |             } | ||||||
|  |             visit_end_struct(m, &err); | ||||||
|  |         } | ||||||
|  |         error_propagate(errp, err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp) |     void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp) | ||||||
|     { |     { | ||||||
|         GenericList *i, **prev = (GenericList **)obj; |         Error *err = NULL; | ||||||
|  |         GenericList *i, **prev; | ||||||
|  |  | ||||||
|         visit_start_list(m, name, errp); |         visit_start_list(m, name, &err); | ||||||
|  |         if (err) { | ||||||
|  |             goto out; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) { |         for (prev = (GenericList **)obj; | ||||||
|  |              !err && (i = visit_next_list(m, prev, &err)) != NULL; | ||||||
|  |              prev = &i) { | ||||||
|             UserDefOneList *native_i = (UserDefOneList *)i; |             UserDefOneList *native_i = (UserDefOneList *)i; | ||||||
|             visit_type_UserDefOne(m, &native_i->value, NULL, errp); |             visit_type_UserDefOne(m, &native_i->value, NULL, &err); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         visit_end_list(m, errp); |         error_propagate(errp, err); | ||||||
|  |         err = NULL; | ||||||
|  |         visit_end_list(m, &err); | ||||||
|  |     out: | ||||||
|  |         error_propagate(errp, err); | ||||||
|     } |     } | ||||||
|     mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h |     $ python scripts/qapi-commands.py --output-dir="qapi-generated" \ | ||||||
|     /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ |     --prefix="example-" --input-file=example-schema.json | ||||||
|  |     $ cat qapi-generated/example-qapi-visit.h | ||||||
|  | [Uninteresting stuff omitted...] | ||||||
|  |  | ||||||
|     #ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT |     #ifndef EXAMPLE_QAPI_VISIT_H | ||||||
|     #define QAPI_GENERATED_EXAMPLE_QAPI_VISIT |     #define EXAMPLE_QAPI_VISIT_H | ||||||
|  |  | ||||||
|     #include "qapi/qapi-visit-core.h" | [Visitors for builtin types omitted...] | ||||||
|     #include "example-qapi-types.h" |  | ||||||
|  |  | ||||||
|     void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp); |     void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp); | ||||||
|     void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp); |     void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp); | ||||||
|  |  | ||||||
|     #endif |     #endif | ||||||
|     mdroth@illuin:~/w/qemu2.git$ |  | ||||||
|  |  | ||||||
| (The actual structure of the visit_type_* functions is a bit more complex |  | ||||||
| in order to propagate errors correctly and avoid leaking memory). |  | ||||||
|  |  | ||||||
| === scripts/qapi-commands.py === | === scripts/qapi-commands.py === | ||||||
|  |  | ||||||
| @@ -390,77 +433,80 @@ $(prefix)qmp-commands.h: Function prototypes for the QMP commands | |||||||
|  |  | ||||||
| Example: | Example: | ||||||
|  |  | ||||||
|     mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c |     $ cat qapi-generated/example-qmp-marshal.c | ||||||
|     /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ | [Uninteresting stuff omitted...] | ||||||
|  |  | ||||||
|     #include "qemu-objects.h" |  | ||||||
|     #include "qapi/qmp-core.h" |  | ||||||
|     #include "qapi/qapi-visit-core.h" |  | ||||||
|     #include "qapi/qmp-output-visitor.h" |  | ||||||
|     #include "qapi/qmp-input-visitor.h" |  | ||||||
|     #include "qapi/qapi-dealloc-visitor.h" |  | ||||||
|     #include "example-qapi-types.h" |  | ||||||
|     #include "example-qapi-visit.h" |  | ||||||
|  |  | ||||||
|     #include "example-qmp-commands.h" |  | ||||||
|     static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp) |     static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp) | ||||||
|     { |     { | ||||||
|         QapiDeallocVisitor *md = qapi_dealloc_visitor_new(); |         Error *local_err = NULL; | ||||||
|         QmpOutputVisitor *mo = qmp_output_visitor_new(); |         QmpOutputVisitor *mo = qmp_output_visitor_new(); | ||||||
|  |         QapiDeallocVisitor *md; | ||||||
|         Visitor *v; |         Visitor *v; | ||||||
|  |  | ||||||
|         v = qmp_output_get_visitor(mo); |         v = qmp_output_get_visitor(mo); | ||||||
|         visit_type_UserDefOne(v, &ret_in, "unused", errp); |         visit_type_UserDefOne(v, &ret_in, "unused", &local_err); | ||||||
|         v = qapi_dealloc_get_visitor(md); |         if (local_err) { | ||||||
|         visit_type_UserDefOne(v, &ret_in, "unused", errp); |             goto out; | ||||||
|         qapi_dealloc_visitor_cleanup(md); |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         *ret_out = qmp_output_get_qobject(mo); |         *ret_out = qmp_output_get_qobject(mo); | ||||||
|  |  | ||||||
|  |     out: | ||||||
|  |         error_propagate(errp, local_err); | ||||||
|  |         qmp_output_visitor_cleanup(mo); | ||||||
|  |         md = qapi_dealloc_visitor_new(); | ||||||
|  |         v = qapi_dealloc_get_visitor(md); | ||||||
|  |         visit_type_UserDefOne(v, &ret_in, "unused", NULL); | ||||||
|  |         qapi_dealloc_visitor_cleanup(md); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp) |     static void qmp_marshal_input_my_command(QDict *args, QObject **ret, Error **errp) | ||||||
|     { |     { | ||||||
|  |         Error *local_err = NULL; | ||||||
|         UserDefOne * retval = NULL; |         UserDefOne * retval = NULL; | ||||||
|         QmpInputVisitor *mi; |         QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args)); | ||||||
|         QapiDeallocVisitor *md; |         QapiDeallocVisitor *md; | ||||||
|         Visitor *v; |         Visitor *v; | ||||||
|         UserDefOne * arg1 = NULL; |         UserDefOne * arg1 = NULL; | ||||||
|  |  | ||||||
|         mi = qmp_input_visitor_new(QOBJECT(args)); |  | ||||||
|         v = qmp_input_get_visitor(mi); |         v = qmp_input_get_visitor(mi); | ||||||
|         visit_type_UserDefOne(v, &arg1, "arg1", errp); |         visit_type_UserDefOne(v, &arg1, "arg1", &local_err); | ||||||
|  |         if (local_err) { | ||||||
|         if (error_is_set(errp)) { |  | ||||||
|             goto out; |             goto out; | ||||||
|         } |         } | ||||||
|         retval = qmp_my_command(arg1, errp); |  | ||||||
|         qmp_marshal_output_my_command(retval, ret, errp); |         retval = qmp_my_command(arg1, &local_err); | ||||||
|  |         if (local_err) { | ||||||
|  |             goto out; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         qmp_marshal_output_my_command(retval, ret, &local_err); | ||||||
|  |  | ||||||
|     out: |     out: | ||||||
|  |         error_propagate(errp, local_err); | ||||||
|  |         qmp_input_visitor_cleanup(mi); | ||||||
|         md = qapi_dealloc_visitor_new(); |         md = qapi_dealloc_visitor_new(); | ||||||
|         v = qapi_dealloc_get_visitor(md); |         v = qapi_dealloc_get_visitor(md); | ||||||
|         visit_type_UserDefOne(v, &arg1, "arg1", errp); |         visit_type_UserDefOne(v, &arg1, "arg1", NULL); | ||||||
|         qapi_dealloc_visitor_cleanup(md); |         qapi_dealloc_visitor_cleanup(md); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static void qmp_init_marshal(void) |     static void qmp_init_marshal(void) | ||||||
|     { |     { | ||||||
|         qmp_register_command("my-command", qmp_marshal_input_my_command); |         qmp_register_command("my-command", qmp_marshal_input_my_command, QCO_NO_OPTIONS); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     qapi_init(qmp_init_marshal); |     qapi_init(qmp_init_marshal); | ||||||
|     mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h |     $ cat qapi-generated/example-qmp-commands.h | ||||||
|     /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ | [Uninteresting stuff omitted...] | ||||||
|  |  | ||||||
|     #ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS |     #ifndef EXAMPLE_QMP_COMMANDS_H | ||||||
|     #define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS |     #define EXAMPLE_QMP_COMMANDS_H | ||||||
|  |  | ||||||
|     #include "example-qapi-types.h" |     #include "example-qapi-types.h" | ||||||
|     #include "error.h" |     #include "qapi/qmp/qdict.h" | ||||||
|  |     #include "qapi/error.h" | ||||||
|  |  | ||||||
|     UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp); |     UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp); | ||||||
|  |  | ||||||
|     #endif |     #endif | ||||||
|     mdroth@illuin:~/w/qemu2.git$ |  | ||||||
|   | |||||||
| @@ -107,8 +107,9 @@ in the description of a field. | |||||||
|  |  | ||||||
|          96 -  99:  refcount_order |          96 -  99:  refcount_order | ||||||
|                     Describes the width of a reference count block entry (width |                     Describes the width of a reference count block entry (width | ||||||
|                     in bits = 1 << refcount_order). For version 2 images, the |                     in bits: refcount_bits = 1 << refcount_order). For version 2 | ||||||
|                     order is always assumed to be 4 (i.e. the width is 16 bits). |                     images, the order is always assumed to be 4 | ||||||
|  |                     (i.e. refcount_bits = 16). | ||||||
|  |  | ||||||
|         100 - 103:  header_length |         100 - 103:  header_length | ||||||
|                     Length of the header structure in bytes. For version 2 |                     Length of the header structure in bytes. For version 2 | ||||||
|   | |||||||
| @@ -556,6 +556,7 @@ ETEXI | |||||||
|         .params     = "keys [hold_ms]", |         .params     = "keys [hold_ms]", | ||||||
|         .help       = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)", |         .help       = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)", | ||||||
|         .mhandler.cmd = hmp_send_key, |         .mhandler.cmd = hmp_send_key, | ||||||
|  |         .command_completion = sendkey_completion, | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| STEXI | STEXI | ||||||
| @@ -1233,9 +1234,10 @@ ETEXI | |||||||
|     { |     { | ||||||
|         .name       = "netdev_add", |         .name       = "netdev_add", | ||||||
|         .args_type  = "netdev:O", |         .args_type  = "netdev:O", | ||||||
|         .params     = "[user|tap|socket|hubport|netmap],id=str[,prop=value][,...]", |         .params     = "[user|tap|socket|vde|bridge|hubport|netmap],id=str[,prop=value][,...]", | ||||||
|         .help       = "add host network device", |         .help       = "add host network device", | ||||||
|         .mhandler.cmd = hmp_netdev_add, |         .mhandler.cmd = hmp_netdev_add, | ||||||
|  |         .command_completion = netdev_add_completion, | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| STEXI | STEXI | ||||||
| @@ -1250,6 +1252,7 @@ ETEXI | |||||||
|         .params     = "id", |         .params     = "id", | ||||||
|         .help       = "remove host network device", |         .help       = "remove host network device", | ||||||
|         .mhandler.cmd = hmp_netdev_del, |         .mhandler.cmd = hmp_netdev_del, | ||||||
|  |         .command_completion = netdev_del_completion, | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| STEXI | STEXI | ||||||
| @@ -1339,6 +1342,7 @@ ETEXI | |||||||
|         .params     = "name on|off", |         .params     = "name on|off", | ||||||
|         .help       = "change the link status of a network adapter", |         .help       = "change the link status of a network adapter", | ||||||
|         .mhandler.cmd = hmp_set_link, |         .mhandler.cmd = hmp_set_link, | ||||||
|  |         .command_completion = set_link_completion, | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| STEXI | STEXI | ||||||
| @@ -1622,6 +1626,7 @@ ETEXI | |||||||
|         .params     = "args", |         .params     = "args", | ||||||
|         .help       = "add chardev", |         .help       = "add chardev", | ||||||
|         .mhandler.cmd = hmp_chardev_add, |         .mhandler.cmd = hmp_chardev_add, | ||||||
|  |         .command_completion = chardev_add_completion, | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| STEXI | STEXI | ||||||
| @@ -1638,6 +1643,7 @@ ETEXI | |||||||
|         .params     = "id", |         .params     = "id", | ||||||
|         .help       = "remove chardev", |         .help       = "remove chardev", | ||||||
|         .mhandler.cmd = hmp_chardev_remove, |         .mhandler.cmd = hmp_chardev_remove, | ||||||
|  |         .command_completion = chardev_remove_completion, | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| STEXI | STEXI | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								hmp.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								hmp.c
									
									
									
									
									
								
							| @@ -341,6 +341,11 @@ void hmp_info_block(Monitor *mon, const QDict *qdict) | |||||||
|                            info->value->inserted->backing_file_depth); |                            info->value->inserted->backing_file_depth); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (info->value->inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) { | ||||||
|  |             monitor_printf(mon, "    Detect zeroes:    %s\n", | ||||||
|  |                            BlockdevDetectZeroesOptions_lookup[info->value->inserted->detect_zeroes]); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (info->value->inserted->bps |         if (info->value->inserted->bps | ||||||
|             || info->value->inserted->bps_rd |             || info->value->inserted->bps_rd | ||||||
|             || info->value->inserted->bps_wr |             || info->value->inserted->bps_wr | ||||||
| @@ -1388,6 +1393,7 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict) | |||||||
| void hmp_object_add(Monitor *mon, const QDict *qdict) | void hmp_object_add(Monitor *mon, const QDict *qdict) | ||||||
| { | { | ||||||
|     Error *err = NULL; |     Error *err = NULL; | ||||||
|  |     Error *err_end = NULL; | ||||||
|     QemuOpts *opts; |     QemuOpts *opts; | ||||||
|     char *type = NULL; |     char *type = NULL; | ||||||
|     char *id = NULL; |     char *id = NULL; | ||||||
| @@ -1411,24 +1417,23 @@ void hmp_object_add(Monitor *mon, const QDict *qdict) | |||||||
|     qdict_del(pdict, "qom-type"); |     qdict_del(pdict, "qom-type"); | ||||||
|     visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err); |     visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err); | ||||||
|     if (err) { |     if (err) { | ||||||
|         goto out_clean; |         goto out_end; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     qdict_del(pdict, "id"); |     qdict_del(pdict, "id"); | ||||||
|     visit_type_str(opts_get_visitor(ov), &id, "id", &err); |     visit_type_str(opts_get_visitor(ov), &id, "id", &err); | ||||||
|     if (err) { |     if (err) { | ||||||
|         goto out_clean; |         goto out_end; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     object_add(type, id, pdict, opts_get_visitor(ov), &err); |     object_add(type, id, pdict, opts_get_visitor(ov), &err); | ||||||
|     if (err) { |  | ||||||
|         goto out_clean; | out_end: | ||||||
|     } |     visit_end_struct(opts_get_visitor(ov), &err_end); | ||||||
|     visit_end_struct(opts_get_visitor(ov), &err); |     if (!err && err_end) { | ||||||
|     if (err) { |  | ||||||
|         qmp_object_del(id, NULL); |         qmp_object_del(id, NULL); | ||||||
|     } |     } | ||||||
|  |     error_propagate(&err, err_end); | ||||||
| out_clean: | out_clean: | ||||||
|     opts_visitor_cleanup(ov); |     opts_visitor_cleanup(ov); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								hmp.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								hmp.h
									
									
									
									
									
								
							| @@ -97,5 +97,11 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str); | |||||||
| void object_del_completion(ReadLineState *rs, int nb_args, const char *str); | void object_del_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
| void device_add_completion(ReadLineState *rs, int nb_args, const char *str); | void device_add_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
| void device_del_completion(ReadLineState *rs, int nb_args, const char *str); | void device_del_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
|  | void sendkey_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
|  | void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
|  | void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
|  | void set_link_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
|  | void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
|  | void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -43,13 +43,13 @@ static int clipper_pci_map_irq(PCIDevice *d, int irq_num) | |||||||
|     return (slot + 1) * 4 + irq_num; |     return (slot + 1) * 4 + irq_num; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void clipper_init(QEMUMachineInitArgs *args) | static void clipper_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     AlphaCPU *cpus[4]; |     AlphaCPU *cpus[4]; | ||||||
|     PCIBus *pci_bus; |     PCIBus *pci_bus; | ||||||
|     ISABus *isa_bus; |     ISABus *isa_bus; | ||||||
|   | |||||||
| @@ -23,12 +23,12 @@ static struct arm_boot_info collie_binfo = { | |||||||
|     .ram_size = 0x20000000, |     .ram_size = 0x20000000, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void collie_init(QEMUMachineInitArgs *args) | static void collie_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     StrongARMState *s; |     StrongARMState *s; | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ typedef struct CubieBoardState { | |||||||
|     MemoryRegion sdram; |     MemoryRegion sdram; | ||||||
| } CubieBoardState; | } CubieBoardState; | ||||||
|  |  | ||||||
| static void cubieboard_init(QEMUMachineInitArgs *args) | static void cubieboard_init(MachineState *machine) | ||||||
| { | { | ||||||
|     CubieBoardState *s = g_new(CubieBoardState, 1); |     CubieBoardState *s = g_new(CubieBoardState, 1); | ||||||
|     Error *err = NULL; |     Error *err = NULL; | ||||||
| @@ -63,14 +63,15 @@ static void cubieboard_init(QEMUMachineInitArgs *args) | |||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     memory_region_init_ram(&s->sdram, NULL, "cubieboard.ram", args->ram_size); |     memory_region_init_ram(&s->sdram, NULL, "cubieboard.ram", | ||||||
|  |                            machine->ram_size); | ||||||
|     vmstate_register_ram_global(&s->sdram); |     vmstate_register_ram_global(&s->sdram); | ||||||
|     memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE, |     memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE, | ||||||
|                                 &s->sdram); |                                 &s->sdram); | ||||||
|  |  | ||||||
|     cubieboard_binfo.ram_size = args->ram_size; |     cubieboard_binfo.ram_size = machine->ram_size; | ||||||
|     cubieboard_binfo.kernel_filename = args->kernel_filename; |     cubieboard_binfo.kernel_filename = machine->kernel_filename; | ||||||
|     cubieboard_binfo.kernel_cmdline = args->kernel_cmdline; |     cubieboard_binfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     arm_load_kernel(&s->a10->cpu, &cubieboard_binfo); |     arm_load_kernel(&s->a10->cpu, &cubieboard_binfo); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -143,7 +143,7 @@ static DigicBoard digic4_board_canon_a1100 = { | |||||||
|     .rom1_def_filename = "canon-a1100-rom1.bin", |     .rom1_def_filename = "canon-a1100-rom1.bin", | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void canon_a1100_init(QEMUMachineInitArgs *args) | static void canon_a1100_init(MachineState *machine) | ||||||
| { | { | ||||||
|     digic4_board_init(&digic4_board_canon_a1100); |     digic4_board_init(&digic4_board_canon_a1100); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -94,7 +94,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args, | static Exynos4210State *exynos4_boards_init_common(MachineState *machine, | ||||||
|                                                    Exynos4BoardType board_type) |                                                    Exynos4BoardType board_type) | ||||||
| { | { | ||||||
|     if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) { |     if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) { | ||||||
| @@ -108,9 +108,9 @@ static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args, | |||||||
|     exynos4_board_binfo.board_id = exynos4_board_id[board_type]; |     exynos4_board_binfo.board_id = exynos4_board_id[board_type]; | ||||||
|     exynos4_board_binfo.smp_bootreg_addr = |     exynos4_board_binfo.smp_bootreg_addr = | ||||||
|             exynos4_board_smp_bootreg_addr[board_type]; |             exynos4_board_smp_bootreg_addr[board_type]; | ||||||
|     exynos4_board_binfo.kernel_filename = args->kernel_filename; |     exynos4_board_binfo.kernel_filename = machine->kernel_filename; | ||||||
|     exynos4_board_binfo.initrd_filename = args->initrd_filename; |     exynos4_board_binfo.initrd_filename = machine->initrd_filename; | ||||||
|     exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline; |     exynos4_board_binfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     exynos4_board_binfo.gic_cpu_if_addr = |     exynos4_board_binfo.gic_cpu_if_addr = | ||||||
|             EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100; |             EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100; | ||||||
|  |  | ||||||
| @@ -120,24 +120,24 @@ static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args, | |||||||
|             " initrd_filename: %s\n", |             " initrd_filename: %s\n", | ||||||
|             exynos4_board_ram_size[board_type] / 1048576, |             exynos4_board_ram_size[board_type] / 1048576, | ||||||
|             exynos4_board_ram_size[board_type], |             exynos4_board_ram_size[board_type], | ||||||
|             args->kernel_filename, |             machine->kernel_filename, | ||||||
|             args->kernel_cmdline, |             machine->kernel_cmdline, | ||||||
|             args->initrd_filename); |             machine->initrd_filename); | ||||||
|  |  | ||||||
|     return exynos4210_init(get_system_memory(), |     return exynos4210_init(get_system_memory(), | ||||||
|             exynos4_board_ram_size[board_type]); |             exynos4_board_ram_size[board_type]); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void nuri_init(QEMUMachineInitArgs *args) | static void nuri_init(MachineState *machine) | ||||||
| { | { | ||||||
|     exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI); |     exynos4_boards_init_common(machine, EXYNOS4_BOARD_NURI); | ||||||
|  |  | ||||||
|     arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo); |     arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void smdkc210_init(QEMUMachineInitArgs *args) | static void smdkc210_init(MachineState *machine) | ||||||
| { | { | ||||||
|     Exynos4210State *s = exynos4_boards_init_common(args, |     Exynos4210State *s = exynos4_boards_init_common(machine, | ||||||
|                                                     EXYNOS4_BOARD_SMDKC210); |                                                     EXYNOS4_BOARD_SMDKC210); | ||||||
|  |  | ||||||
|     lan9215_init(SMDK_LAN9118_BASE_ADDR, |     lan9215_init(SMDK_LAN9118_BASE_ADDR, | ||||||
|   | |||||||
| @@ -46,7 +46,7 @@ | |||||||
|  |  | ||||||
| static const int sector_len = 128 * 1024; | static const int sector_len = 128 * 1024; | ||||||
|  |  | ||||||
| static void connex_init(QEMUMachineInitArgs *args) | static void connex_init(MachineState *machine) | ||||||
| { | { | ||||||
|     PXA2xxState *cpu; |     PXA2xxState *cpu; | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
| @@ -83,9 +83,9 @@ static void connex_init(QEMUMachineInitArgs *args) | |||||||
|                     qdev_get_gpio_in(cpu->gpio, 36)); |                     qdev_get_gpio_in(cpu->gpio, 36)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void verdex_init(QEMUMachineInitArgs *args) | static void verdex_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     PXA2xxState *cpu; |     PXA2xxState *cpu; | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
|     int be; |     int be; | ||||||
|   | |||||||
| @@ -199,13 +199,13 @@ enum cxmachines { | |||||||
|  * 32-bit host, set the reg value of memory to 0xf7ff00000 in the |  * 32-bit host, set the reg value of memory to 0xf7ff00000 in the | ||||||
|  * device tree and pass -m 2047 to QEMU. |  * device tree and pass -m 2047 to QEMU. | ||||||
|  */ |  */ | ||||||
| static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) | static void calxeda_init(MachineState *machine, enum cxmachines machine_id) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     DeviceState *dev = NULL; |     DeviceState *dev = NULL; | ||||||
|     SysBusDevice *busdev; |     SysBusDevice *busdev; | ||||||
|     qemu_irq pic[128]; |     qemu_irq pic[128]; | ||||||
| @@ -217,7 +217,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) | |||||||
|     char *sysboot_filename; |     char *sysboot_filename; | ||||||
|  |  | ||||||
|     if (!cpu_model) { |     if (!cpu_model) { | ||||||
|         switch (machine) { |         switch (machine_id) { | ||||||
|         case CALXEDA_HIGHBANK: |         case CALXEDA_HIGHBANK: | ||||||
|             cpu_model = "cortex-a9"; |             cpu_model = "cortex-a9"; | ||||||
|             break; |             break; | ||||||
| @@ -274,7 +274,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     switch (machine) { |     switch (machine_id) { | ||||||
|     case CALXEDA_HIGHBANK: |     case CALXEDA_HIGHBANK: | ||||||
|         dev = qdev_create(NULL, "l2x0"); |         dev = qdev_create(NULL, "l2x0"); | ||||||
|         qdev_init_nofail(dev); |         qdev_init_nofail(dev); | ||||||
| @@ -359,14 +359,14 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) | |||||||
|     arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo); |     arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void highbank_init(QEMUMachineInitArgs *args) | static void highbank_init(MachineState *machine) | ||||||
| { | { | ||||||
|     calxeda_init(args, CALXEDA_HIGHBANK); |     calxeda_init(machine, CALXEDA_HIGHBANK); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void midway_init(QEMUMachineInitArgs *args) | static void midway_init(MachineState *machine) | ||||||
| { | { | ||||||
|     calxeda_init(args, CALXEDA_MIDWAY); |     calxeda_init(machine, CALXEDA_MIDWAY); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine highbank_machine = { | static QEMUMachine highbank_machine = { | ||||||
|   | |||||||
| @@ -461,13 +461,13 @@ static struct arm_boot_info integrator_binfo = { | |||||||
|     .board_id = 0x113, |     .board_id = 0x113, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void integratorcp_init(QEMUMachineInitArgs *args) | static void integratorcp_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     ARMCPU *cpu; |     ARMCPU *cpu; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								hw/arm/kzm.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								hw/arm/kzm.c
									
									
									
									
									
								
							| @@ -70,13 +70,13 @@ static struct arm_boot_info kzm_binfo = { | |||||||
|     .board_id = 1722, |     .board_id = 1722, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void kzm_init(QEMUMachineInitArgs *args) | static void kzm_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     ARMCPU *cpu; |     ARMCPU *cpu; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|   | |||||||
| @@ -105,7 +105,7 @@ static struct arm_boot_info mainstone_binfo = { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| static void mainstone_common_init(MemoryRegion *address_space_mem, | static void mainstone_common_init(MemoryRegion *address_space_mem, | ||||||
|                                   QEMUMachineInitArgs *args, |                                   MachineState *machine, | ||||||
|                                   enum mainstone_model_e model, int arm_id) |                                   enum mainstone_model_e model, int arm_id) | ||||||
| { | { | ||||||
|     uint32_t sector_len = 256 * 1024; |     uint32_t sector_len = 256 * 1024; | ||||||
| @@ -116,7 +116,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, | |||||||
|     int i; |     int i; | ||||||
|     int be; |     int be; | ||||||
|     MemoryRegion *rom = g_new(MemoryRegion, 1); |     MemoryRegion *rom = g_new(MemoryRegion, 1); | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|  |  | ||||||
|     if (!cpu_model) |     if (!cpu_model) | ||||||
|         cpu_model = "pxa270-c5"; |         cpu_model = "pxa270-c5"; | ||||||
| @@ -175,16 +175,16 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, | |||||||
|     smc91c111_init(&nd_table[0], MST_ETH_PHYS, |     smc91c111_init(&nd_table[0], MST_ETH_PHYS, | ||||||
|                     qdev_get_gpio_in(mst_irq, ETHERNET_IRQ)); |                     qdev_get_gpio_in(mst_irq, ETHERNET_IRQ)); | ||||||
|  |  | ||||||
|     mainstone_binfo.kernel_filename = args->kernel_filename; |     mainstone_binfo.kernel_filename = machine->kernel_filename; | ||||||
|     mainstone_binfo.kernel_cmdline = args->kernel_cmdline; |     mainstone_binfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     mainstone_binfo.initrd_filename = args->initrd_filename; |     mainstone_binfo.initrd_filename = machine->initrd_filename; | ||||||
|     mainstone_binfo.board_id = arm_id; |     mainstone_binfo.board_id = arm_id; | ||||||
|     arm_load_kernel(mpu->cpu, &mainstone_binfo); |     arm_load_kernel(mpu->cpu, &mainstone_binfo); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void mainstone_init(QEMUMachineInitArgs *args) | static void mainstone_init(MachineState *machine) | ||||||
| { | { | ||||||
|     mainstone_common_init(get_system_memory(), args, mainstone, 0x196); |     mainstone_common_init(get_system_memory(), machine, mainstone, 0x196); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine mainstone2_machine = { | static QEMUMachine mainstone2_machine = { | ||||||
|   | |||||||
| @@ -1569,12 +1569,12 @@ static struct arm_boot_info musicpal_binfo = { | |||||||
|     .board_id = 0x20e, |     .board_id = 0x20e, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void musicpal_init(QEMUMachineInitArgs *args) | static void musicpal_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     ARMCPU *cpu; |     ARMCPU *cpu; | ||||||
|     qemu_irq pic[32]; |     qemu_irq pic[32]; | ||||||
|     DeviceState *dev; |     DeviceState *dev; | ||||||
|   | |||||||
| @@ -1278,14 +1278,14 @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p) | |||||||
|     return n8x0_atag_setup(p, 810); |     return n8x0_atag_setup(p, 810); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void n8x0_init(QEMUMachineInitArgs *args, | static void n8x0_init(MachineState *machine, | ||||||
|                       struct arm_boot_info *binfo, int model) |                       struct arm_boot_info *binfo, int model) | ||||||
| { | { | ||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
|     struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s)); |     struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s)); | ||||||
|     int sdram_size = binfo->ram_size; |     int sdram_size = binfo->ram_size; | ||||||
|  |  | ||||||
|     s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model); |     s->mpu = omap2420_mpu_init(sysmem, sdram_size, machine->cpu_model); | ||||||
|  |  | ||||||
|     /* Setup peripherals |     /* Setup peripherals | ||||||
|      * |      * | ||||||
| @@ -1329,18 +1329,18 @@ static void n8x0_init(QEMUMachineInitArgs *args, | |||||||
|         n8x0_usb_setup(s); |         n8x0_usb_setup(s); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (args->kernel_filename) { |     if (machine->kernel_filename) { | ||||||
|         /* Or at the linux loader.  */ |         /* Or at the linux loader.  */ | ||||||
|         binfo->kernel_filename = args->kernel_filename; |         binfo->kernel_filename = machine->kernel_filename; | ||||||
|         binfo->kernel_cmdline = args->kernel_cmdline; |         binfo->kernel_cmdline = machine->kernel_cmdline; | ||||||
|         binfo->initrd_filename = args->initrd_filename; |         binfo->initrd_filename = machine->initrd_filename; | ||||||
|         arm_load_kernel(s->mpu->cpu, binfo); |         arm_load_kernel(s->mpu->cpu, binfo); | ||||||
|  |  | ||||||
|         qemu_register_reset(n8x0_boot_init, s); |         qemu_register_reset(n8x0_boot_init, s); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (option_rom[0].name && |     if (option_rom[0].name && | ||||||
|         (args->boot_order[0] == 'n' || !args->kernel_filename)) { |         (machine->boot_order[0] == 'n' || !machine->kernel_filename)) { | ||||||
|         uint8_t nolo_tags[0x10000]; |         uint8_t nolo_tags[0x10000]; | ||||||
|         /* No, wait, better start at the ROM.  */ |         /* No, wait, better start at the ROM.  */ | ||||||
|         s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000; |         s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000; | ||||||
| @@ -1382,14 +1382,14 @@ static struct arm_boot_info n810_binfo = { | |||||||
|     .atag_board = n810_atag_setup, |     .atag_board = n810_atag_setup, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void n800_init(QEMUMachineInitArgs *args) | static void n800_init(MachineState *machine) | ||||||
| { | { | ||||||
|     return n8x0_init(args, &n800_binfo, 800); |     return n8x0_init(machine, &n800_binfo, 800); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void n810_init(QEMUMachineInitArgs *args) | static void n810_init(MachineState *machine) | ||||||
| { | { | ||||||
|     return n8x0_init(args, &n810_binfo, 810); |     return n8x0_init(machine, &n810_binfo, 810); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine n800_machine = { | static QEMUMachine n800_machine = { | ||||||
|   | |||||||
| @@ -98,7 +98,7 @@ static struct arm_boot_info sx1_binfo = { | |||||||
|     .board_id = 0x265, |     .board_id = 0x265, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void sx1_init(QEMUMachineInitArgs *args, const int version) | static void sx1_init(MachineState *machine, const int version) | ||||||
| { | { | ||||||
|     struct omap_mpu_state_s *mpu; |     struct omap_mpu_state_s *mpu; | ||||||
|     MemoryRegion *address_space = get_system_memory(); |     MemoryRegion *address_space = get_system_memory(); | ||||||
| @@ -118,7 +118,8 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version) | |||||||
|         flash_size = flash2_size; |         flash_size = flash2_size; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model); |     mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, | ||||||
|  |                            machine->cpu_model); | ||||||
|  |  | ||||||
|     /* External Flash (EMIFS) */ |     /* External Flash (EMIFS) */ | ||||||
|     memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size); |     memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size); | ||||||
| @@ -189,29 +190,29 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version) | |||||||
|                                 OMAP_CS1_BASE, &cs[1]); |                                 OMAP_CS1_BASE, &cs[1]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!args->kernel_filename && !fl_idx && !qtest_enabled()) { |     if (!machine->kernel_filename && !fl_idx && !qtest_enabled()) { | ||||||
|         fprintf(stderr, "Kernel or Flash image must be specified\n"); |         fprintf(stderr, "Kernel or Flash image must be specified\n"); | ||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Load the kernel.  */ |     /* Load the kernel.  */ | ||||||
|     sx1_binfo.kernel_filename = args->kernel_filename; |     sx1_binfo.kernel_filename = machine->kernel_filename; | ||||||
|     sx1_binfo.kernel_cmdline = args->kernel_cmdline; |     sx1_binfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     sx1_binfo.initrd_filename = args->initrd_filename; |     sx1_binfo.initrd_filename = machine->initrd_filename; | ||||||
|     arm_load_kernel(mpu->cpu, &sx1_binfo); |     arm_load_kernel(mpu->cpu, &sx1_binfo); | ||||||
|  |  | ||||||
|     /* TODO: fix next line */ |     /* TODO: fix next line */ | ||||||
|     //~ qemu_console_resize(ds, 640, 480); |     //~ qemu_console_resize(ds, 640, 480); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void sx1_init_v1(QEMUMachineInitArgs *args) | static void sx1_init_v1(MachineState *machine) | ||||||
| { | { | ||||||
|     sx1_init(args, 1); |     sx1_init(machine, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void sx1_init_v2(QEMUMachineInitArgs *args) | static void sx1_init_v2(MachineState *machine) | ||||||
| { | { | ||||||
|     sx1_init(args, 2); |     sx1_init(machine, 2); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine sx1_machine_v2 = { | static QEMUMachine sx1_machine_v2 = { | ||||||
|   | |||||||
| @@ -191,12 +191,12 @@ static struct arm_boot_info palmte_binfo = { | |||||||
|     .board_id = 0x331, |     .board_id = 0x331, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void palmte_init(QEMUMachineInitArgs *args) | static void palmte_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     struct omap_mpu_state_s *mpu; |     struct omap_mpu_state_s *mpu; | ||||||
|     int flash_size = 0x00800000; |     int flash_size = 0x00800000; | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ static const int realview_board_id[] = { | |||||||
|     0x76d |     0x76d | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void realview_init(QEMUMachineInitArgs *args, | static void realview_init(MachineState *machine, | ||||||
|                           enum realview_board_type board_type) |                           enum realview_board_type board_type) | ||||||
| { | { | ||||||
|     ARMCPU *cpu = NULL; |     ARMCPU *cpu = NULL; | ||||||
| @@ -71,7 +71,7 @@ static void realview_init(QEMUMachineInitArgs *args, | |||||||
|     uint32_t proc_id = 0; |     uint32_t proc_id = 0; | ||||||
|     uint32_t sys_id; |     uint32_t sys_id; | ||||||
|     ram_addr_t low_ram_size; |     ram_addr_t low_ram_size; | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     hwaddr periphbase = 0; |     hwaddr periphbase = 0; | ||||||
|  |  | ||||||
|     switch (board_type) { |     switch (board_type) { | ||||||
| @@ -91,7 +91,7 @@ static void realview_init(QEMUMachineInitArgs *args, | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, args->cpu_model); |     cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, machine->cpu_model); | ||||||
|     if (!cpu_oc) { |     if (!cpu_oc) { | ||||||
|         fprintf(stderr, "Unable to find CPU definition\n"); |         fprintf(stderr, "Unable to find CPU definition\n"); | ||||||
|         exit(1); |         exit(1); | ||||||
| @@ -342,45 +342,45 @@ static void realview_init(QEMUMachineInitArgs *args, | |||||||
|     memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack); |     memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack); | ||||||
|  |  | ||||||
|     realview_binfo.ram_size = ram_size; |     realview_binfo.ram_size = ram_size; | ||||||
|     realview_binfo.kernel_filename = args->kernel_filename; |     realview_binfo.kernel_filename = machine->kernel_filename; | ||||||
|     realview_binfo.kernel_cmdline = args->kernel_cmdline; |     realview_binfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     realview_binfo.initrd_filename = args->initrd_filename; |     realview_binfo.initrd_filename = machine->initrd_filename; | ||||||
|     realview_binfo.nb_cpus = smp_cpus; |     realview_binfo.nb_cpus = smp_cpus; | ||||||
|     realview_binfo.board_id = realview_board_id[board_type]; |     realview_binfo.board_id = realview_board_id[board_type]; | ||||||
|     realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); |     realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); | ||||||
|     arm_load_kernel(ARM_CPU(first_cpu), &realview_binfo); |     arm_load_kernel(ARM_CPU(first_cpu), &realview_binfo); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void realview_eb_init(QEMUMachineInitArgs *args) | static void realview_eb_init(MachineState *machine) | ||||||
| { | { | ||||||
|     if (!args->cpu_model) { |     if (!machine->cpu_model) { | ||||||
|         args->cpu_model = "arm926"; |         machine->cpu_model = "arm926"; | ||||||
|     } |     } | ||||||
|     realview_init(args, BOARD_EB); |     realview_init(machine, BOARD_EB); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void realview_eb_mpcore_init(QEMUMachineInitArgs *args) | static void realview_eb_mpcore_init(MachineState *machine) | ||||||
| { | { | ||||||
|     if (!args->cpu_model) { |     if (!machine->cpu_model) { | ||||||
|         args->cpu_model = "arm11mpcore"; |         machine->cpu_model = "arm11mpcore"; | ||||||
|     } |     } | ||||||
|     realview_init(args, BOARD_EB_MPCORE); |     realview_init(machine, BOARD_EB_MPCORE); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void realview_pb_a8_init(QEMUMachineInitArgs *args) | static void realview_pb_a8_init(MachineState *machine) | ||||||
| { | { | ||||||
|     if (!args->cpu_model) { |     if (!machine->cpu_model) { | ||||||
|         args->cpu_model = "cortex-a8"; |         machine->cpu_model = "cortex-a8"; | ||||||
|     } |     } | ||||||
|     realview_init(args, BOARD_PB_A8); |     realview_init(machine, BOARD_PB_A8); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void realview_pbx_a9_init(QEMUMachineInitArgs *args) | static void realview_pbx_a9_init(MachineState *machine) | ||||||
| { | { | ||||||
|     if (!args->cpu_model) { |     if (!machine->cpu_model) { | ||||||
|         args->cpu_model = "cortex-a9"; |         machine->cpu_model = "cortex-a9"; | ||||||
|     } |     } | ||||||
|     realview_init(args, BOARD_PBX_A9); |     realview_init(machine, BOARD_PBX_A9); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine realview_eb_machine = { | static QEMUMachine realview_eb_machine = { | ||||||
|   | |||||||
| @@ -887,14 +887,14 @@ static struct arm_boot_info spitz_binfo = { | |||||||
|     .ram_size = 0x04000000, |     .ram_size = 0x04000000, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void spitz_common_init(QEMUMachineInitArgs *args, | static void spitz_common_init(MachineState *machine, | ||||||
|                               enum spitz_model_e model, int arm_id) |                               enum spitz_model_e model, int arm_id) | ||||||
| { | { | ||||||
|     PXA2xxState *mpu; |     PXA2xxState *mpu; | ||||||
|     DeviceState *scp0, *scp1 = NULL; |     DeviceState *scp0, *scp1 = NULL; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *rom = g_new(MemoryRegion, 1); |     MemoryRegion *rom = g_new(MemoryRegion, 1); | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|  |  | ||||||
|     if (!cpu_model) |     if (!cpu_model) | ||||||
|         cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0"; |         cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0"; | ||||||
| @@ -935,32 +935,32 @@ static void spitz_common_init(QEMUMachineInitArgs *args, | |||||||
|         /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */ |         /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */ | ||||||
|         spitz_microdrive_attach(mpu, 0); |         spitz_microdrive_attach(mpu, 0); | ||||||
|  |  | ||||||
|     spitz_binfo.kernel_filename = args->kernel_filename; |     spitz_binfo.kernel_filename = machine->kernel_filename; | ||||||
|     spitz_binfo.kernel_cmdline = args->kernel_cmdline; |     spitz_binfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     spitz_binfo.initrd_filename = args->initrd_filename; |     spitz_binfo.initrd_filename = machine->initrd_filename; | ||||||
|     spitz_binfo.board_id = arm_id; |     spitz_binfo.board_id = arm_id; | ||||||
|     arm_load_kernel(mpu->cpu, &spitz_binfo); |     arm_load_kernel(mpu->cpu, &spitz_binfo); | ||||||
|     sl_bootparam_write(SL_PXA_PARAM_BASE); |     sl_bootparam_write(SL_PXA_PARAM_BASE); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void spitz_init(QEMUMachineInitArgs *args) | static void spitz_init(MachineState *machine) | ||||||
| { | { | ||||||
|     spitz_common_init(args, spitz, 0x2c9); |     spitz_common_init(machine, spitz, 0x2c9); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void borzoi_init(QEMUMachineInitArgs *args) | static void borzoi_init(MachineState *machine) | ||||||
| { | { | ||||||
|     spitz_common_init(args, borzoi, 0x33f); |     spitz_common_init(machine, borzoi, 0x33f); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void akita_init(QEMUMachineInitArgs *args) | static void akita_init(MachineState *machine) | ||||||
| { | { | ||||||
|     spitz_common_init(args, akita, 0x2e8); |     spitz_common_init(machine, akita, 0x2e8); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void terrier_init(QEMUMachineInitArgs *args) | static void terrier_init(MachineState *machine) | ||||||
| { | { | ||||||
|     spitz_common_init(args, terrier, 0x33f); |     spitz_common_init(machine, terrier, 0x33f); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine akitapda_machine = { | static QEMUMachine akitapda_machine = { | ||||||
|   | |||||||
| @@ -1290,9 +1290,10 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, | |||||||
|  |  | ||||||
|             sddev = ssi_create_slave(bus, "ssi-sd"); |             sddev = ssi_create_slave(bus, "ssi-sd"); | ||||||
|             ssddev = ssi_create_slave(bus, "ssd0323"); |             ssddev = ssi_create_slave(bus, "ssd0323"); | ||||||
|             gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0), |             gpio_out[GPIO_D][0] = qemu_irq_split( | ||||||
|                                                  qdev_get_gpio_in(ssddev, 0)); |                     qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0), | ||||||
|             gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1); |                     qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0)); | ||||||
|  |             gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0); | ||||||
|  |  | ||||||
|             /* Make sure the select pin is high.  */ |             /* Make sure the select pin is high.  */ | ||||||
|             qemu_irq_raise(gpio_out[GPIO_D][0]); |             qemu_irq_raise(gpio_out[GPIO_D][0]); | ||||||
| @@ -1333,17 +1334,17 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, | |||||||
| } | } | ||||||
|  |  | ||||||
| /* FIXME: Figure out how to generate these from stellaris_boards.  */ | /* FIXME: Figure out how to generate these from stellaris_boards.  */ | ||||||
| static void lm3s811evb_init(QEMUMachineInitArgs *args) | static void lm3s811evb_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]); |     stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void lm3s6965evb_init(QEMUMachineInitArgs *args) | static void lm3s6965evb_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]); |     stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -211,12 +211,12 @@ static struct arm_boot_info tosa_binfo = { | |||||||
|     .ram_size = 0x04000000, |     .ram_size = 0x04000000, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void tosa_init(QEMUMachineInitArgs *args) | static void tosa_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *rom = g_new(MemoryRegion, 1); |     MemoryRegion *rom = g_new(MemoryRegion, 1); | ||||||
|     PXA2xxState *mpu; |     PXA2xxState *mpu; | ||||||
|   | |||||||
| @@ -173,7 +173,7 @@ static int vpb_sic_init(SysBusDevice *sbd) | |||||||
|  |  | ||||||
| static struct arm_boot_info versatile_binfo; | static struct arm_boot_info versatile_binfo; | ||||||
|  |  | ||||||
| static void versatile_init(QEMUMachineInitArgs *args, int board_id) | static void versatile_init(MachineState *machine, int board_id) | ||||||
| { | { | ||||||
|     ARMCPU *cpu; |     ARMCPU *cpu; | ||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
| @@ -190,15 +190,15 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id) | |||||||
|     int done_smc = 0; |     int done_smc = 0; | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
|  |  | ||||||
|     if (!args->cpu_model) { |     if (!machine->cpu_model) { | ||||||
|         args->cpu_model = "arm926"; |         machine->cpu_model = "arm926"; | ||||||
|     } |     } | ||||||
|     cpu = cpu_arm_init(args->cpu_model); |     cpu = cpu_arm_init(machine->cpu_model); | ||||||
|     if (!cpu) { |     if (!cpu) { | ||||||
|         fprintf(stderr, "Unable to find CPU definition\n"); |         fprintf(stderr, "Unable to find CPU definition\n"); | ||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
|     memory_region_init_ram(ram, NULL, "versatile.ram", args->ram_size); |     memory_region_init_ram(ram, NULL, "versatile.ram", machine->ram_size); | ||||||
|     vmstate_register_ram_global(ram); |     vmstate_register_ram_global(ram); | ||||||
|     /* ??? RAM should repeat to fill physical memory space.  */ |     /* ??? RAM should repeat to fill physical memory space.  */ | ||||||
|     /* SDRAM at address zero.  */ |     /* SDRAM at address zero.  */ | ||||||
| @@ -344,22 +344,22 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id) | |||||||
|         fprintf(stderr, "qemu: Error registering flash memory.\n"); |         fprintf(stderr, "qemu: Error registering flash memory.\n"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     versatile_binfo.ram_size = args->ram_size; |     versatile_binfo.ram_size = machine->ram_size; | ||||||
|     versatile_binfo.kernel_filename = args->kernel_filename; |     versatile_binfo.kernel_filename = machine->kernel_filename; | ||||||
|     versatile_binfo.kernel_cmdline = args->kernel_cmdline; |     versatile_binfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     versatile_binfo.initrd_filename = args->initrd_filename; |     versatile_binfo.initrd_filename = machine->initrd_filename; | ||||||
|     versatile_binfo.board_id = board_id; |     versatile_binfo.board_id = board_id; | ||||||
|     arm_load_kernel(cpu, &versatile_binfo); |     arm_load_kernel(cpu, &versatile_binfo); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void vpb_init(QEMUMachineInitArgs *args) | static void vpb_init(MachineState *machine) | ||||||
| { | { | ||||||
|     versatile_init(args, 0x183); |     versatile_init(machine, 0x183); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void vab_init(QEMUMachineInitArgs *args) | static void vab_init(MachineState *machine) | ||||||
| { | { | ||||||
|     versatile_init(args, 0x25e); |     versatile_init(machine, 0x25e); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine versatilepb_machine = { | static QEMUMachine versatilepb_machine = { | ||||||
|   | |||||||
| @@ -509,7 +509,7 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name, | |||||||
| } | } | ||||||
|  |  | ||||||
| static void vexpress_common_init(VEDBoardInfo *daughterboard, | static void vexpress_common_init(VEDBoardInfo *daughterboard, | ||||||
|                                  QEMUMachineInitArgs *args) |                                  MachineState *machine) | ||||||
| { | { | ||||||
|     DeviceState *dev, *sysctl, *pl041; |     DeviceState *dev, *sysctl, *pl041; | ||||||
|     qemu_irq pic[64]; |     qemu_irq pic[64]; | ||||||
| @@ -525,7 +525,8 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard, | |||||||
|     const hwaddr *map = daughterboard->motherboard_map; |     const hwaddr *map = daughterboard->motherboard_map; | ||||||
|     int i; |     int i; | ||||||
|  |  | ||||||
|     daughterboard->init(daughterboard, args->ram_size, args->cpu_model, pic); |     daughterboard->init(daughterboard, machine->ram_size, machine->cpu_model, | ||||||
|  |                         pic); | ||||||
|  |  | ||||||
|     /* Motherboard peripherals: the wiring is the same but the |     /* Motherboard peripherals: the wiring is the same but the | ||||||
|      * addresses vary between the legacy and A-Series memory maps. |      * addresses vary between the legacy and A-Series memory maps. | ||||||
| @@ -639,10 +640,10 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard, | |||||||
|                              pic[40 + i]); |                              pic[40 + i]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     daughterboard->bootinfo.ram_size = args->ram_size; |     daughterboard->bootinfo.ram_size = machine->ram_size; | ||||||
|     daughterboard->bootinfo.kernel_filename = args->kernel_filename; |     daughterboard->bootinfo.kernel_filename = machine->kernel_filename; | ||||||
|     daughterboard->bootinfo.kernel_cmdline = args->kernel_cmdline; |     daughterboard->bootinfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     daughterboard->bootinfo.initrd_filename = args->initrd_filename; |     daughterboard->bootinfo.initrd_filename = machine->initrd_filename; | ||||||
|     daughterboard->bootinfo.nb_cpus = smp_cpus; |     daughterboard->bootinfo.nb_cpus = smp_cpus; | ||||||
|     daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID; |     daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID; | ||||||
|     daughterboard->bootinfo.loader_start = daughterboard->loader_start; |     daughterboard->bootinfo.loader_start = daughterboard->loader_start; | ||||||
| @@ -653,14 +654,14 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard, | |||||||
|     arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo); |     arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void vexpress_a9_init(QEMUMachineInitArgs *args) | static void vexpress_a9_init(MachineState *machine) | ||||||
| { | { | ||||||
|     vexpress_common_init(&a9_daughterboard, args); |     vexpress_common_init(&a9_daughterboard, machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void vexpress_a15_init(QEMUMachineInitArgs *args) | static void vexpress_a15_init(MachineState *machine) | ||||||
| { | { | ||||||
|     vexpress_common_init(&a15_daughterboard, args); |     vexpress_common_init(&a15_daughterboard, machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine vexpress_a9_machine = { | static QEMUMachine vexpress_a9_machine = { | ||||||
|   | |||||||
| @@ -383,13 +383,13 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) | |||||||
|     return board->fdt; |     return board->fdt; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void machvirt_init(QEMUMachineInitArgs *args) | static void machvirt_init(MachineState *machine) | ||||||
| { | { | ||||||
|     qemu_irq pic[NUM_IRQS]; |     qemu_irq pic[NUM_IRQS]; | ||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
|     int n; |     int n; | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     VirtBoardInfo *vbi; |     VirtBoardInfo *vbi; | ||||||
|  |  | ||||||
|     if (!cpu_model) { |     if (!cpu_model) { | ||||||
| @@ -415,7 +415,7 @@ static void machvirt_init(QEMUMachineInitArgs *args) | |||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (args->ram_size > vbi->memmap[VIRT_MEM].size) { |     if (machine->ram_size > vbi->memmap[VIRT_MEM].size) { | ||||||
|         error_report("mach-virt: cannot model more than 30GB RAM"); |         error_report("mach-virt: cannot model more than 30GB RAM"); | ||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
| @@ -447,7 +447,7 @@ static void machvirt_init(QEMUMachineInitArgs *args) | |||||||
|     } |     } | ||||||
|     fdt_add_cpu_nodes(vbi); |     fdt_add_cpu_nodes(vbi); | ||||||
|  |  | ||||||
|     memory_region_init_ram(ram, NULL, "mach-virt.ram", args->ram_size); |     memory_region_init_ram(ram, NULL, "mach-virt.ram", machine->ram_size); | ||||||
|     vmstate_register_ram_global(ram); |     vmstate_register_ram_global(ram); | ||||||
|     memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram); |     memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram); | ||||||
|  |  | ||||||
| @@ -461,10 +461,10 @@ static void machvirt_init(QEMUMachineInitArgs *args) | |||||||
|      */ |      */ | ||||||
|     create_virtio_devices(vbi, pic); |     create_virtio_devices(vbi, pic); | ||||||
|  |  | ||||||
|     vbi->bootinfo.ram_size = args->ram_size; |     vbi->bootinfo.ram_size = machine->ram_size; | ||||||
|     vbi->bootinfo.kernel_filename = args->kernel_filename; |     vbi->bootinfo.kernel_filename = machine->kernel_filename; | ||||||
|     vbi->bootinfo.kernel_cmdline = args->kernel_cmdline; |     vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline; | ||||||
|     vbi->bootinfo.initrd_filename = args->initrd_filename; |     vbi->bootinfo.initrd_filename = machine->initrd_filename; | ||||||
|     vbi->bootinfo.nb_cpus = smp_cpus; |     vbi->bootinfo.nb_cpus = smp_cpus; | ||||||
|     vbi->bootinfo.board_id = -1; |     vbi->bootinfo.board_id = -1; | ||||||
|     vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base; |     vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base; | ||||||
|   | |||||||
| @@ -94,20 +94,20 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq, | |||||||
|         for (j = 0; j < num_ss; ++j) { |         for (j = 0; j < num_ss; ++j) { | ||||||
|             flash_dev = ssi_create_slave(spi, "n25q128"); |             flash_dev = ssi_create_slave(spi, "n25q128"); | ||||||
|  |  | ||||||
|             cs_line = qdev_get_gpio_in(flash_dev, 0); |             cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); | ||||||
|             sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line); |             sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void zynq_init(QEMUMachineInitArgs *args) | static void zynq_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     ObjectClass *cpu_oc; |     ObjectClass *cpu_oc; | ||||||
|     ARMCPU *cpu; |     ARMCPU *cpu; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								hw/arm/z2.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								hw/arm/z2.c
									
									
									
									
									
								
							| @@ -300,12 +300,12 @@ static const TypeInfo aer915_info = { | |||||||
|     .class_init    = aer915_class_init, |     .class_init    = aer915_class_init, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void z2_init(QEMUMachineInitArgs *args) | static void z2_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     uint32_t sector_len = 0x10000; |     uint32_t sector_len = 0x10000; | ||||||
|     PXA2xxState *mpu; |     PXA2xxState *mpu; | ||||||
|   | |||||||
| @@ -245,7 +245,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d) | |||||||
|  |  | ||||||
|     /* update global status */ |     /* update global status */ | ||||||
|     if (sts & d->int_ctl) { |     if (sts & d->int_ctl) { | ||||||
|         sts |= (1 << 31); |         sts |= (1U << 31); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     d->int_sts = sts; |     d->int_sts = sts; | ||||||
| @@ -257,7 +257,7 @@ static void intel_hda_update_irq(IntelHDAState *d) | |||||||
|     int level; |     int level; | ||||||
|  |  | ||||||
|     intel_hda_update_int_sts(d); |     intel_hda_update_int_sts(d); | ||||||
|     if (d->int_sts & (1 << 31) && d->int_ctl & (1 << 31)) { |     if (d->int_sts & (1U << 31) && d->int_ctl & (1U << 31)) { | ||||||
|         level = 1; |         level = 1; | ||||||
|     } else { |     } else { | ||||||
|         level = 0; |         level = 0; | ||||||
| @@ -574,7 +574,7 @@ static void intel_hda_set_st_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint3 | |||||||
|     if (st->ctl & 0x01) { |     if (st->ctl & 0x01) { | ||||||
|         /* reset */ |         /* reset */ | ||||||
|         dprint(d, 1, "st #%d: reset\n", reg->stream); |         dprint(d, 1, "st #%d: reset\n", reg->stream); | ||||||
|         st->ctl = 0; |         st->ctl = SD_STS_FIFO_READY << 24; | ||||||
|     } |     } | ||||||
|     if ((st->ctl & 0x02) != (old & 0x02)) { |     if ((st->ctl & 0x02) != (old & 0x02)) { | ||||||
|         uint32_t stnr = (st->ctl >> 20) & 0x0f; |         uint32_t stnr = (st->ctl >> 20) & 0x0f; | ||||||
| @@ -829,6 +829,7 @@ static const struct IntelHDAReg regtab[] = { | |||||||
|         .wclear   = 0x1c000000,                                       \ |         .wclear   = 0x1c000000,                                       \ | ||||||
|         .offset   = offsetof(IntelHDAState, st[_i].ctl),              \ |         .offset   = offsetof(IntelHDAState, st[_i].ctl),              \ | ||||||
|         .whandler = intel_hda_set_st_ctl,                             \ |         .whandler = intel_hda_set_st_ctl,                             \ | ||||||
|  |         .reset    = SD_STS_FIFO_READY << 24                           \ | ||||||
|     },                                                                \ |     },                                                                \ | ||||||
|     [ ST_REG(_i, ICH6_REG_SD_LPIB) ] = {                              \ |     [ ST_REG(_i, ICH6_REG_SD_LPIB) ] = {                              \ | ||||||
|         .stream   = _i,                                               \ |         .stream   = _i,                                               \ | ||||||
|   | |||||||
| @@ -70,6 +70,9 @@ struct VirtIOBlockDataPlane { | |||||||
|                                              queue */ |                                              queue */ | ||||||
|  |  | ||||||
|     unsigned int num_reqs; |     unsigned int num_reqs; | ||||||
|  |  | ||||||
|  |     /* Operation blocker on BDS */ | ||||||
|  |     Error *blocker; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* Raise an interrupt to signal guest, if necessary */ | /* Raise an interrupt to signal guest, if necessary */ | ||||||
| @@ -350,6 +353,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, | |||||||
| { | { | ||||||
|     VirtIOBlockDataPlane *s; |     VirtIOBlockDataPlane *s; | ||||||
|     int fd; |     int fd; | ||||||
|  |     Error *local_err = NULL; | ||||||
|  |  | ||||||
|     *dataplane = NULL; |     *dataplane = NULL; | ||||||
|  |  | ||||||
| @@ -372,9 +376,10 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, | |||||||
|     /* If dataplane is (re-)enabled while the guest is running there could be |     /* If dataplane is (re-)enabled while the guest is running there could be | ||||||
|      * block jobs that can conflict. |      * block jobs that can conflict. | ||||||
|      */ |      */ | ||||||
|     if (bdrv_in_use(blk->conf.bs)) { |     if (bdrv_op_is_blocked(blk->conf.bs, BLOCK_OP_TYPE_DATAPLANE, &local_err)) { | ||||||
|         error_setg(errp, |         error_report("cannot start dataplane thread: %s", | ||||||
|                    "cannot start dataplane thread while device is in use"); |                       error_get_pretty(local_err)); | ||||||
|  |         error_free(local_err); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -406,8 +411,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, | |||||||
|     } |     } | ||||||
|     s->ctx = iothread_get_aio_context(s->iothread); |     s->ctx = iothread_get_aio_context(s->iothread); | ||||||
|  |  | ||||||
|     /* Prevent block operations that conflict with data plane thread */ |     error_setg(&s->blocker, "block device is in use by data plane"); | ||||||
|     bdrv_set_in_use(blk->conf.bs, 1); |     bdrv_op_block_all(blk->conf.bs, s->blocker); | ||||||
|  |  | ||||||
|     *dataplane = s; |     *dataplane = s; | ||||||
| } | } | ||||||
| @@ -420,7 +425,8 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     virtio_blk_data_plane_stop(s); |     virtio_blk_data_plane_stop(s); | ||||||
|     bdrv_set_in_use(s->blk->conf.bs, 0); |     bdrv_op_unblock_all(s->blk->conf.bs, s->blocker); | ||||||
|  |     error_free(s->blocker); | ||||||
|     object_unref(OBJECT(s->iothread)); |     object_unref(OBJECT(s->iothread)); | ||||||
|     g_free(s); |     g_free(s); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,6 +11,284 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "hw/boards.h" | #include "hw/boards.h" | ||||||
|  | #include "qapi/visitor.h" | ||||||
|  |  | ||||||
|  | static char *machine_get_accel(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return g_strdup(ms->accel); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_accel(Object *obj, const char *value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->accel = g_strdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool machine_get_kernel_irqchip(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return ms->kernel_irqchip; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_kernel_irqchip(Object *obj, bool value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->kernel_irqchip = value; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v, | ||||||
|  |                                        void *opaque, const char *name, | ||||||
|  |                                        Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |     int64_t value = ms->kvm_shadow_mem; | ||||||
|  |  | ||||||
|  |     visit_type_int(v, &value, name, errp); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v, | ||||||
|  |                                        void *opaque, const char *name, | ||||||
|  |                                        Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |     Error *error = NULL; | ||||||
|  |     int64_t value; | ||||||
|  |  | ||||||
|  |     visit_type_int(v, &value, name, &error); | ||||||
|  |     if (error) { | ||||||
|  |         error_propagate(errp, error); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ms->kvm_shadow_mem = value; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *machine_get_kernel(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return g_strdup(ms->kernel_filename); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_kernel(Object *obj, const char *value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->kernel_filename = g_strdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *machine_get_initrd(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return g_strdup(ms->initrd_filename); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_initrd(Object *obj, const char *value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->initrd_filename = g_strdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *machine_get_append(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return g_strdup(ms->kernel_cmdline); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_append(Object *obj, const char *value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->kernel_cmdline = g_strdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *machine_get_dtb(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return g_strdup(ms->dtb); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_dtb(Object *obj, const char *value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->dtb = g_strdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *machine_get_dumpdtb(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return g_strdup(ms->dumpdtb); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->dumpdtb = g_strdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_get_phandle_start(Object *obj, Visitor *v, | ||||||
|  |                                        void *opaque, const char *name, | ||||||
|  |                                        Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |     int64_t value = ms->phandle_start; | ||||||
|  |  | ||||||
|  |     visit_type_int(v, &value, name, errp); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_phandle_start(Object *obj, Visitor *v, | ||||||
|  |                                        void *opaque, const char *name, | ||||||
|  |                                        Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |     Error *error = NULL; | ||||||
|  |     int64_t value; | ||||||
|  |  | ||||||
|  |     visit_type_int(v, &value, name, &error); | ||||||
|  |     if (error) { | ||||||
|  |         error_propagate(errp, error); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ms->phandle_start = value; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *machine_get_dt_compatible(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return g_strdup(ms->dt_compatible); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->dt_compatible = g_strdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool machine_get_dump_guest_core(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return ms->dump_guest_core; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->dump_guest_core = value; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool machine_get_mem_merge(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return ms->mem_merge; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_mem_merge(Object *obj, bool value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->mem_merge = value; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool machine_get_usb(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return ms->usb; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_usb(Object *obj, bool value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->usb = value; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *machine_get_firmware(Object *obj, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     return g_strdup(ms->firmware); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_set_firmware(Object *obj, const char *value, Error **errp) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     ms->firmware = g_strdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_initfn(Object *obj) | ||||||
|  | { | ||||||
|  |     object_property_add_str(obj, "accel", | ||||||
|  |                             machine_get_accel, machine_set_accel, NULL); | ||||||
|  |     object_property_add_bool(obj, "kernel_irqchip", | ||||||
|  |                              machine_get_kernel_irqchip, | ||||||
|  |                              machine_set_kernel_irqchip, | ||||||
|  |                              NULL); | ||||||
|  |     object_property_add(obj, "kvm_shadow_mem", "int", | ||||||
|  |                         machine_get_kvm_shadow_mem, | ||||||
|  |                         machine_set_kvm_shadow_mem, | ||||||
|  |                         NULL, NULL, NULL); | ||||||
|  |     object_property_add_str(obj, "kernel", | ||||||
|  |                             machine_get_kernel, machine_set_kernel, NULL); | ||||||
|  |     object_property_add_str(obj, "initrd", | ||||||
|  |                             machine_get_initrd, machine_set_initrd, NULL); | ||||||
|  |     object_property_add_str(obj, "append", | ||||||
|  |                             machine_get_append, machine_set_append, NULL); | ||||||
|  |     object_property_add_str(obj, "dtb", | ||||||
|  |                             machine_get_dtb, machine_set_dtb, NULL); | ||||||
|  |     object_property_add_str(obj, "dumpdtb", | ||||||
|  |                             machine_get_dumpdtb, machine_set_dumpdtb, NULL); | ||||||
|  |     object_property_add(obj, "phandle_start", "int", | ||||||
|  |                         machine_get_phandle_start, | ||||||
|  |                         machine_set_phandle_start, | ||||||
|  |                         NULL, NULL, NULL); | ||||||
|  |     object_property_add_str(obj, "dt_compatible", | ||||||
|  |                             machine_get_dt_compatible, | ||||||
|  |                             machine_set_dt_compatible, | ||||||
|  |                             NULL); | ||||||
|  |     object_property_add_bool(obj, "dump-guest-core", | ||||||
|  |                              machine_get_dump_guest_core, | ||||||
|  |                              machine_set_dump_guest_core, | ||||||
|  |                              NULL); | ||||||
|  |     object_property_add_bool(obj, "mem-merge", | ||||||
|  |                              machine_get_mem_merge, machine_set_mem_merge, NULL); | ||||||
|  |     object_property_add_bool(obj, "usb", machine_get_usb, machine_set_usb, NULL); | ||||||
|  |     object_property_add_str(obj, "firmware", | ||||||
|  |                             machine_get_firmware, machine_set_firmware, NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void machine_finalize(Object *obj) | ||||||
|  | { | ||||||
|  |     MachineState *ms = MACHINE(obj); | ||||||
|  |  | ||||||
|  |     g_free(ms->accel); | ||||||
|  |     g_free(ms->kernel_filename); | ||||||
|  |     g_free(ms->initrd_filename); | ||||||
|  |     g_free(ms->kernel_cmdline); | ||||||
|  |     g_free(ms->dtb); | ||||||
|  |     g_free(ms->dumpdtb); | ||||||
|  |     g_free(ms->dt_compatible); | ||||||
|  |     g_free(ms->firmware); | ||||||
|  | } | ||||||
|  |  | ||||||
| static const TypeInfo machine_info = { | static const TypeInfo machine_info = { | ||||||
|     .name = TYPE_MACHINE, |     .name = TYPE_MACHINE, | ||||||
| @@ -18,6 +296,8 @@ static const TypeInfo machine_info = { | |||||||
|     .abstract = true, |     .abstract = true, | ||||||
|     .class_size = sizeof(MachineClass), |     .class_size = sizeof(MachineClass), | ||||||
|     .instance_size = sizeof(MachineState), |     .instance_size = sizeof(MachineState), | ||||||
|  |     .instance_init = machine_initfn, | ||||||
|  |     .instance_finalize = machine_finalize, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void machine_register_types(void) | static void machine_register_types(void) | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ | |||||||
| #include "hw/hw.h" | #include "hw/hw.h" | ||||||
| #include "hw/boards.h" | #include "hw/boards.h" | ||||||
|  |  | ||||||
| static void machine_none_init(QEMUMachineInitArgs *args) | static void machine_none_init(MachineState *machine) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -312,30 +312,82 @@ BusState *qdev_get_parent_bus(DeviceState *dev) | |||||||
|     return dev->parent_bus; |     return dev->parent_bus; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev, | ||||||
|  |                                                const char *name) | ||||||
|  | { | ||||||
|  |     NamedGPIOList *ngl; | ||||||
|  |  | ||||||
|  |     QLIST_FOREACH(ngl, &dev->gpios, node) { | ||||||
|  |         /* NULL is a valid and matchable name, otherwise do a normal | ||||||
|  |          * strcmp match. | ||||||
|  |          */ | ||||||
|  |         if ((!ngl->name && !name) || | ||||||
|  |                 (name && ngl->name && strcmp(name, ngl->name) == 0)) { | ||||||
|  |             return ngl; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ngl = g_malloc0(sizeof(*ngl)); | ||||||
|  |     ngl->name = g_strdup(name); | ||||||
|  |     QLIST_INSERT_HEAD(&dev->gpios, ngl, node); | ||||||
|  |     return ngl; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler, | ||||||
|  |                              const char *name, int n) | ||||||
|  | { | ||||||
|  |     NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); | ||||||
|  |  | ||||||
|  |     gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler, | ||||||
|  |                                      dev, n); | ||||||
|  |     gpio_list->num_in += n; | ||||||
|  | } | ||||||
|  |  | ||||||
| void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) | void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) | ||||||
| { | { | ||||||
|     dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler, |     qdev_init_gpio_in_named(dev, handler, NULL, n); | ||||||
|                                         dev, n); | } | ||||||
|     dev->num_gpio_in += n; |  | ||||||
|  | void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, | ||||||
|  |                               const char *name, int n) | ||||||
|  | { | ||||||
|  |     NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); | ||||||
|  |  | ||||||
|  |     assert(gpio_list->num_out == 0); | ||||||
|  |     gpio_list->num_out = n; | ||||||
|  |     gpio_list->out = pins; | ||||||
| } | } | ||||||
|  |  | ||||||
| void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) | void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) | ||||||
| { | { | ||||||
|     assert(dev->num_gpio_out == 0); |     qdev_init_gpio_out_named(dev, pins, NULL, n); | ||||||
|     dev->num_gpio_out = n; | } | ||||||
|     dev->gpio_out = pins; |  | ||||||
|  | qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n) | ||||||
|  | { | ||||||
|  |     NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); | ||||||
|  |  | ||||||
|  |     assert(n >= 0 && n < gpio_list->num_in); | ||||||
|  |     return gpio_list->in[n]; | ||||||
| } | } | ||||||
|  |  | ||||||
| qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) | qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) | ||||||
| { | { | ||||||
|     assert(n >= 0 && n < dev->num_gpio_in); |     return qdev_get_gpio_in_named(dev, NULL, n); | ||||||
|     return dev->gpio_in[n]; | } | ||||||
|  |  | ||||||
|  | void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, | ||||||
|  |                                  qemu_irq pin) | ||||||
|  | { | ||||||
|  |     NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); | ||||||
|  |  | ||||||
|  |     assert(n >= 0 && n < gpio_list->num_out); | ||||||
|  |     gpio_list->out[n] = pin; | ||||||
| } | } | ||||||
|  |  | ||||||
| void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) | void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) | ||||||
| { | { | ||||||
|     assert(n >= 0 && n < dev->num_gpio_out); |     qdev_connect_gpio_out_named(dev, NULL, n, pin); | ||||||
|     dev->gpio_out[n] = pin; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| BusState *qdev_get_child_bus(DeviceState *dev, const char *name) | BusState *qdev_get_child_bus(DeviceState *dev, const char *name) | ||||||
| @@ -844,6 +896,7 @@ static void device_initfn(Object *obj) | |||||||
|     object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS, |     object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS, | ||||||
|                              (Object **)&dev->parent_bus, NULL, 0, |                              (Object **)&dev->parent_bus, NULL, 0, | ||||||
|                              &error_abort); |                              &error_abort); | ||||||
|  |     QLIST_INIT(&dev->gpios); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void device_post_init(Object *obj) | static void device_post_init(Object *obj) | ||||||
| @@ -854,10 +907,22 @@ static void device_post_init(Object *obj) | |||||||
| /* Unlink device from bus and free the structure.  */ | /* Unlink device from bus and free the structure.  */ | ||||||
| static void device_finalize(Object *obj) | static void device_finalize(Object *obj) | ||||||
| { | { | ||||||
|  |     NamedGPIOList *ngl, *next; | ||||||
|  |  | ||||||
|     DeviceState *dev = DEVICE(obj); |     DeviceState *dev = DEVICE(obj); | ||||||
|     if (dev->opts) { |     if (dev->opts) { | ||||||
|         qemu_opts_del(dev->opts); |         qemu_opts_del(dev->opts); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) { | ||||||
|  |         QLIST_REMOVE(ngl, node); | ||||||
|  |         qemu_free_irqs(ngl->in); | ||||||
|  |         g_free(ngl->name); | ||||||
|  |         g_free(ngl); | ||||||
|  |         /* ngl->out irqs are owned by the other end and should not be freed | ||||||
|  |          * here | ||||||
|  |          */ | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void device_class_base_init(ObjectClass *class, void *data) | static void device_class_base_init(ObjectClass *class, void *data) | ||||||
|   | |||||||
| @@ -243,12 +243,12 @@ static const MemoryRegionOps gpio_ops = { | |||||||
| static struct cris_load_info li; | static struct cris_load_info li; | ||||||
|  |  | ||||||
| static | static | ||||||
| void axisdev88_init(QEMUMachineInitArgs *args) | void axisdev88_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     CRISCPU *cpu; |     CRISCPU *cpu; | ||||||
|     CPUCRISState *env; |     CPUCRISState *env; | ||||||
|     DeviceState *dev; |     DeviceState *dev; | ||||||
|   | |||||||
| @@ -173,6 +173,7 @@ static void jazz_led_update_display(void *opaque) | |||||||
|             case 16: |             case 16: | ||||||
|                 color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa); |                 color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa); | ||||||
|                 color_led = rgb_to_pixel16(0x00, 0xff, 0x00); |                 color_led = rgb_to_pixel16(0x00, 0xff, 0x00); | ||||||
|  |                 break; | ||||||
|             case 24: |             case 24: | ||||||
|                 color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa); |                 color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa); | ||||||
|                 color_led = rgb_to_pixel24(0x00, 0xff, 0x00); |                 color_led = rgb_to_pixel24(0x00, 0xff, 0x00); | ||||||
|   | |||||||
| @@ -620,17 +620,6 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp) | |||||||
|             src += 2; |             src += 2; | ||||||
|             break; |             break; | ||||||
|         case 1: /* 16 bpp plus transparency */ |         case 1: /* 16 bpp plus transparency */ | ||||||
|             alpha = *(uint16_t *) src & (1 << 24); |  | ||||||
|             if (s->control[0] & LCCR0_CMS) |  | ||||||
|                 r = g = b = *(uint16_t *) src & 0xff; |  | ||||||
|             else { |  | ||||||
|                 r = (*(uint16_t *) src & 0xf800) >> 8; |  | ||||||
|                 g = (*(uint16_t *) src & 0x07e0) >> 3; |  | ||||||
|                 b = (*(uint16_t *) src & 0x001f) << 3; |  | ||||||
|             } |  | ||||||
|             src += 2; |  | ||||||
|             break; |  | ||||||
|         case 2: /* 18 bpp plus transparency */ |  | ||||||
|             alpha = *(uint32_t *) src & (1 << 24); |             alpha = *(uint32_t *) src & (1 << 24); | ||||||
|             if (s->control[0] & LCCR0_CMS) |             if (s->control[0] & LCCR0_CMS) | ||||||
|                 r = g = b = *(uint32_t *) src & 0xff; |                 r = g = b = *(uint32_t *) src & 0xff; | ||||||
| @@ -641,6 +630,17 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp) | |||||||
|             } |             } | ||||||
|             src += 4; |             src += 4; | ||||||
|             break; |             break; | ||||||
|  |         case 2: /* 18 bpp plus transparency */ | ||||||
|  |             alpha = *(uint32_t *) src & (1 << 24); | ||||||
|  |             if (s->control[0] & LCCR0_CMS) | ||||||
|  |                 r = g = b = *(uint32_t *) src & 0xff; | ||||||
|  |             else { | ||||||
|  |                 r = (*(uint32_t *) src & 0xfc0000) >> 16; | ||||||
|  |                 g = (*(uint32_t *) src & 0x00fc00) >> 8; | ||||||
|  |                 b = (*(uint32_t *) src & 0x0000fc); | ||||||
|  |             } | ||||||
|  |             src += 4; | ||||||
|  |             break; | ||||||
|         case 3: /* 24 bpp plus transparency */ |         case 3: /* 24 bpp plus transparency */ | ||||||
|             alpha = *(uint32_t *) src & (1 << 24); |             alpha = *(uint32_t *) src & (1 << 24); | ||||||
|             if (s->control[0] & LCCR0_CMS) |             if (s->control[0] & LCCR0_CMS) | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ static bool smbios_legacy_mode; | |||||||
| static bool gigabyte_align = true; | static bool gigabyte_align = true; | ||||||
|  |  | ||||||
| /* PC hardware initialisation */ | /* PC hardware initialisation */ | ||||||
| static void pc_init1(QEMUMachineInitArgs *args, | static void pc_init1(MachineState *machine, | ||||||
|                      int pci_enabled, |                      int pci_enabled, | ||||||
|                      int kvmclock_enabled) |                      int kvmclock_enabled) | ||||||
| { | { | ||||||
| @@ -106,7 +106,7 @@ static void pc_init1(QEMUMachineInitArgs *args, | |||||||
|     object_property_add_child(qdev_get_machine(), "icc-bridge", |     object_property_add_child(qdev_get_machine(), "icc-bridge", | ||||||
|                               OBJECT(icc_bridge), NULL); |                               OBJECT(icc_bridge), NULL); | ||||||
|  |  | ||||||
|     pc_cpus_init(args->cpu_model, icc_bridge); |     pc_cpus_init(machine->cpu_model, icc_bridge); | ||||||
|  |  | ||||||
|     if (kvm_enabled() && kvmclock_enabled) { |     if (kvm_enabled() && kvmclock_enabled) { | ||||||
|         kvmclock_create(); |         kvmclock_create(); | ||||||
| @@ -119,13 +119,13 @@ static void pc_init1(QEMUMachineInitArgs *args, | |||||||
|      * For old machine types, use whatever split we used historically to avoid |      * For old machine types, use whatever split we used historically to avoid | ||||||
|      * breaking migration. |      * breaking migration. | ||||||
|      */ |      */ | ||||||
|     if (args->ram_size >= 0xe0000000) { |     if (machine->ram_size >= 0xe0000000) { | ||||||
|         ram_addr_t lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000; |         ram_addr_t lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000; | ||||||
|         above_4g_mem_size = args->ram_size - lowmem; |         above_4g_mem_size = machine->ram_size - lowmem; | ||||||
|         below_4g_mem_size = lowmem; |         below_4g_mem_size = lowmem; | ||||||
|     } else { |     } else { | ||||||
|         above_4g_mem_size = 0; |         above_4g_mem_size = 0; | ||||||
|         below_4g_mem_size = args->ram_size; |         below_4g_mem_size = machine->ram_size; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (pci_enabled) { |     if (pci_enabled) { | ||||||
| @@ -145,16 +145,17 @@ static void pc_init1(QEMUMachineInitArgs *args, | |||||||
|     guest_info->isapc_ram_fw = !pci_enabled; |     guest_info->isapc_ram_fw = !pci_enabled; | ||||||
|  |  | ||||||
|     if (smbios_defaults) { |     if (smbios_defaults) { | ||||||
|  |         MachineClass *mc = MACHINE_GET_CLASS(machine); | ||||||
|         /* These values are guest ABI, do not change */ |         /* These values are guest ABI, do not change */ | ||||||
|         smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", |         smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", | ||||||
|                             args->machine->name, smbios_legacy_mode); |                             mc->name, smbios_legacy_mode); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* allocate ram and load rom/bios */ |     /* allocate ram and load rom/bios */ | ||||||
|     if (!xen_enabled()) { |     if (!xen_enabled()) { | ||||||
|         fw_cfg = pc_memory_init(system_memory, |         fw_cfg = pc_memory_init(system_memory, | ||||||
|                        args->kernel_filename, args->kernel_cmdline, |                        machine->kernel_filename, machine->kernel_cmdline, | ||||||
|                        args->initrd_filename, |                        machine->initrd_filename, | ||||||
|                        below_4g_mem_size, above_4g_mem_size, |                        below_4g_mem_size, above_4g_mem_size, | ||||||
|                        rom_memory, &ram_memory, guest_info); |                        rom_memory, &ram_memory, guest_info); | ||||||
|     } |     } | ||||||
| @@ -170,7 +171,7 @@ static void pc_init1(QEMUMachineInitArgs *args, | |||||||
|  |  | ||||||
|     if (pci_enabled) { |     if (pci_enabled) { | ||||||
|         pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi, |         pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi, | ||||||
|                               system_memory, system_io, args->ram_size, |                               system_memory, system_io, machine->ram_size, | ||||||
|                               below_4g_mem_size, |                               below_4g_mem_size, | ||||||
|                               above_4g_mem_size, |                               above_4g_mem_size, | ||||||
|                               pci_memory, ram_memory); |                               pci_memory, ram_memory); | ||||||
| @@ -235,7 +236,7 @@ static void pc_init1(QEMUMachineInitArgs *args, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_order, |     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order, | ||||||
|                  floppy, idebus[0], idebus[1], rtc_state); |                  floppy, idebus[0], idebus[1], rtc_state); | ||||||
|  |  | ||||||
|     if (pci_enabled && usb_enabled(false)) { |     if (pci_enabled && usb_enabled(false)) { | ||||||
| @@ -258,131 +259,131 @@ static void pc_init1(QEMUMachineInitArgs *args, | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_pci(QEMUMachineInitArgs *args) | static void pc_init_pci(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_init1(args, 1, 1); |     pc_init1(machine, 1, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_2_0(QEMUMachineInitArgs *args) | static void pc_compat_2_0(MachineState *machine) | ||||||
| { | { | ||||||
|     smbios_legacy_mode = true; |     smbios_legacy_mode = true; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_7(QEMUMachineInitArgs *args) | static void pc_compat_1_7(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_2_0(args); |     pc_compat_2_0(machine); | ||||||
|     smbios_defaults = false; |     smbios_defaults = false; | ||||||
|     gigabyte_align = false; |     gigabyte_align = false; | ||||||
|     option_rom_has_mr = true; |     option_rom_has_mr = true; | ||||||
|     x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC); |     x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_6(QEMUMachineInitArgs *args) | static void pc_compat_1_6(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_7(args); |     pc_compat_1_7(machine); | ||||||
|     has_pci_info = false; |     has_pci_info = false; | ||||||
|     rom_file_has_mr = false; |     rom_file_has_mr = false; | ||||||
|     has_acpi_build = false; |     has_acpi_build = false; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_5(QEMUMachineInitArgs *args) | static void pc_compat_1_5(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_6(args); |     pc_compat_1_6(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_4(QEMUMachineInitArgs *args) | static void pc_compat_1_4(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_5(args); |     pc_compat_1_5(machine); | ||||||
|     x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); |     x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); | ||||||
|     x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); |     x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_3(QEMUMachineInitArgs *args) | static void pc_compat_1_3(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_4(args); |     pc_compat_1_4(machine); | ||||||
|     enable_compat_apic_id_mode(); |     enable_compat_apic_id_mode(); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* PC compat function for pc-0.14 to pc-1.2 */ | /* PC compat function for pc-0.14 to pc-1.2 */ | ||||||
| static void pc_compat_1_2(QEMUMachineInitArgs *args) | static void pc_compat_1_2(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_3(args); |     pc_compat_1_3(machine); | ||||||
|     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI); |     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_pci_2_0(QEMUMachineInitArgs *args) | static void pc_init_pci_2_0(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_2_0(args); |     pc_compat_2_0(machine); | ||||||
|     pc_init_pci(args); |     pc_init_pci(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_pci_1_7(QEMUMachineInitArgs *args) | static void pc_init_pci_1_7(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_7(args); |     pc_compat_1_7(machine); | ||||||
|     pc_init_pci(args); |     pc_init_pci(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_pci_1_6(QEMUMachineInitArgs *args) | static void pc_init_pci_1_6(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_6(args); |     pc_compat_1_6(machine); | ||||||
|     pc_init_pci(args); |     pc_init_pci(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_pci_1_5(QEMUMachineInitArgs *args) | static void pc_init_pci_1_5(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_5(args); |     pc_compat_1_5(machine); | ||||||
|     pc_init_pci(args); |     pc_init_pci(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_pci_1_4(QEMUMachineInitArgs *args) | static void pc_init_pci_1_4(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_4(args); |     pc_compat_1_4(machine); | ||||||
|     pc_init_pci(args); |     pc_init_pci(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_pci_1_3(QEMUMachineInitArgs *args) | static void pc_init_pci_1_3(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_3(args); |     pc_compat_1_3(machine); | ||||||
|     pc_init_pci(args); |     pc_init_pci(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* PC machine init function for pc-0.14 to pc-1.2 */ | /* PC machine init function for pc-0.14 to pc-1.2 */ | ||||||
| static void pc_init_pci_1_2(QEMUMachineInitArgs *args) | static void pc_init_pci_1_2(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_2(args); |     pc_compat_1_2(machine); | ||||||
|     pc_init_pci(args); |     pc_init_pci(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */ | /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */ | ||||||
| static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args) | static void pc_init_pci_no_kvmclock(MachineState *machine) | ||||||
| { | { | ||||||
|     has_pci_info = false; |     has_pci_info = false; | ||||||
|     has_acpi_build = false; |     has_acpi_build = false; | ||||||
|     smbios_defaults = false; |     smbios_defaults = false; | ||||||
|     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI); |     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI); | ||||||
|     enable_compat_apic_id_mode(); |     enable_compat_apic_id_mode(); | ||||||
|     pc_init1(args, 1, 0); |     pc_init1(machine, 1, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_isa(QEMUMachineInitArgs *args) | static void pc_init_isa(MachineState *machine) | ||||||
| { | { | ||||||
|     has_pci_info = false; |     has_pci_info = false; | ||||||
|     has_acpi_build = false; |     has_acpi_build = false; | ||||||
|     smbios_defaults = false; |     smbios_defaults = false; | ||||||
|     if (!args->cpu_model) { |     if (!machine->cpu_model) { | ||||||
|         args->cpu_model = "486"; |         machine->cpu_model = "486"; | ||||||
|     } |     } | ||||||
|     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI); |     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI); | ||||||
|     enable_compat_apic_id_mode(); |     enable_compat_apic_id_mode(); | ||||||
|     pc_init1(args, 0, 1); |     pc_init1(machine, 0, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| #ifdef CONFIG_XEN | #ifdef CONFIG_XEN | ||||||
| static void pc_xen_hvm_init(QEMUMachineInitArgs *args) | static void pc_xen_hvm_init(MachineState *machine) | ||||||
| { | { | ||||||
|     PCIBus *bus; |     PCIBus *bus; | ||||||
|  |  | ||||||
|     pc_init_pci(args); |     pc_init_pci(machine); | ||||||
|  |  | ||||||
|     bus = pci_find_primary_bus(); |     bus = pci_find_primary_bus(); | ||||||
|     if (bus != NULL) { |     if (bus != NULL) { | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ static bool smbios_legacy_mode; | |||||||
| static bool gigabyte_align = true; | static bool gigabyte_align = true; | ||||||
|  |  | ||||||
| /* PC hardware initialisation */ | /* PC hardware initialisation */ | ||||||
| static void pc_q35_init(QEMUMachineInitArgs *args) | static void pc_q35_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t below_4g_mem_size, above_4g_mem_size; |     ram_addr_t below_4g_mem_size, above_4g_mem_size; | ||||||
|     Q35PCIHost *q35_host; |     Q35PCIHost *q35_host; | ||||||
| @@ -93,7 +93,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) | |||||||
|     object_property_add_child(qdev_get_machine(), "icc-bridge", |     object_property_add_child(qdev_get_machine(), "icc-bridge", | ||||||
|                               OBJECT(icc_bridge), NULL); |                               OBJECT(icc_bridge), NULL); | ||||||
|  |  | ||||||
|     pc_cpus_init(args->cpu_model, icc_bridge); |     pc_cpus_init(machine->cpu_model, icc_bridge); | ||||||
|     pc_acpi_init("q35-acpi-dsdt.aml"); |     pc_acpi_init("q35-acpi-dsdt.aml"); | ||||||
|  |  | ||||||
|     kvmclock_create(); |     kvmclock_create(); | ||||||
| @@ -107,13 +107,13 @@ static void pc_q35_init(QEMUMachineInitArgs *args) | |||||||
|      * For old machine types, use whatever split we used historically to avoid |      * For old machine types, use whatever split we used historically to avoid | ||||||
|      * breaking migration. |      * breaking migration. | ||||||
|      */ |      */ | ||||||
|     if (args->ram_size >= 0xb0000000) { |     if (machine->ram_size >= 0xb0000000) { | ||||||
|         ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000; |         ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000; | ||||||
|         above_4g_mem_size = args->ram_size - lowmem; |         above_4g_mem_size = machine->ram_size - lowmem; | ||||||
|         below_4g_mem_size = lowmem; |         below_4g_mem_size = lowmem; | ||||||
|     } else { |     } else { | ||||||
|         above_4g_mem_size = 0; |         above_4g_mem_size = 0; | ||||||
|         below_4g_mem_size = args->ram_size; |         below_4g_mem_size = machine->ram_size; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* pci enabled */ |     /* pci enabled */ | ||||||
| @@ -132,16 +132,17 @@ static void pc_q35_init(QEMUMachineInitArgs *args) | |||||||
|     guest_info->has_acpi_build = has_acpi_build; |     guest_info->has_acpi_build = has_acpi_build; | ||||||
|  |  | ||||||
|     if (smbios_defaults) { |     if (smbios_defaults) { | ||||||
|  |         MachineClass *mc = MACHINE_GET_CLASS(machine); | ||||||
|         /* These values are guest ABI, do not change */ |         /* These values are guest ABI, do not change */ | ||||||
|         smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", |         smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", | ||||||
|                             args->machine->name, smbios_legacy_mode); |                             mc->name, smbios_legacy_mode); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* allocate ram and load rom/bios */ |     /* allocate ram and load rom/bios */ | ||||||
|     if (!xen_enabled()) { |     if (!xen_enabled()) { | ||||||
|         pc_memory_init(get_system_memory(), |         pc_memory_init(get_system_memory(), | ||||||
|                        args->kernel_filename, args->kernel_cmdline, |                        machine->kernel_filename, machine->kernel_cmdline, | ||||||
|                        args->initrd_filename, |                        machine->initrd_filename, | ||||||
|                        below_4g_mem_size, above_4g_mem_size, |                        below_4g_mem_size, above_4g_mem_size, | ||||||
|                        rom_memory, &ram_memory, guest_info); |                        rom_memory, &ram_memory, guest_info); | ||||||
|     } |     } | ||||||
| @@ -230,7 +231,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) | |||||||
|                                     0xb100), |                                     0xb100), | ||||||
|                       8, NULL, 0); |                       8, NULL, 0); | ||||||
|  |  | ||||||
|     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_order, |     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order, | ||||||
|                  floppy, idebus[0], idebus[1], rtc_state); |                  floppy, idebus[0], idebus[1], rtc_state); | ||||||
|  |  | ||||||
|     /* the rest devices to which pci devfn is automatically assigned */ |     /* the rest devices to which pci devfn is automatically assigned */ | ||||||
| @@ -241,68 +242,68 @@ static void pc_q35_init(QEMUMachineInitArgs *args) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_2_0(QEMUMachineInitArgs *args) | static void pc_compat_2_0(MachineState *machine) | ||||||
| { | { | ||||||
|     smbios_legacy_mode = true; |     smbios_legacy_mode = true; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_7(QEMUMachineInitArgs *args) | static void pc_compat_1_7(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_2_0(args); |     pc_compat_2_0(machine); | ||||||
|     smbios_defaults = false; |     smbios_defaults = false; | ||||||
|     gigabyte_align = false; |     gigabyte_align = false; | ||||||
|     option_rom_has_mr = true; |     option_rom_has_mr = true; | ||||||
|     x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC); |     x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_6(QEMUMachineInitArgs *args) | static void pc_compat_1_6(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_7(args); |     pc_compat_1_7(machine); | ||||||
|     has_pci_info = false; |     has_pci_info = false; | ||||||
|     rom_file_has_mr = false; |     rom_file_has_mr = false; | ||||||
|     has_acpi_build = false; |     has_acpi_build = false; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_5(QEMUMachineInitArgs *args) | static void pc_compat_1_5(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_6(args); |     pc_compat_1_6(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_compat_1_4(QEMUMachineInitArgs *args) | static void pc_compat_1_4(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_5(args); |     pc_compat_1_5(machine); | ||||||
|     x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); |     x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); | ||||||
|     x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); |     x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_q35_init_2_0(QEMUMachineInitArgs *args) | static void pc_q35_init_2_0(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_2_0(args); |     pc_compat_2_0(machine); | ||||||
|     pc_q35_init(args); |     pc_q35_init(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_q35_init_1_7(QEMUMachineInitArgs *args) | static void pc_q35_init_1_7(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_7(args); |     pc_compat_1_7(machine); | ||||||
|     pc_q35_init(args); |     pc_q35_init(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_q35_init_1_6(QEMUMachineInitArgs *args) | static void pc_q35_init_1_6(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_6(args); |     pc_compat_1_6(machine); | ||||||
|     pc_q35_init(args); |     pc_q35_init(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_q35_init_1_5(QEMUMachineInitArgs *args) | static void pc_q35_init_1_5(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_5(args); |     pc_compat_1_5(machine); | ||||||
|     pc_q35_init(args); |     pc_q35_init(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_q35_init_1_4(QEMUMachineInitArgs *args) | static void pc_q35_init_1_4(MachineState *machine) | ||||||
| { | { | ||||||
|     pc_compat_1_4(args); |     pc_compat_1_4(machine); | ||||||
|     pc_q35_init(args); |     pc_q35_init(machine); | ||||||
| } | } | ||||||
|  |  | ||||||
| #define PC_Q35_MACHINE_OPTIONS \ | #define PC_Q35_MACHINE_OPTIONS \ | ||||||
|   | |||||||
							
								
								
									
										214
									
								
								hw/input/hid.c
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								hw/input/hid.c
									
									
									
									
									
								
							| @@ -105,70 +105,135 @@ void hid_set_next_idle(HIDState *hs) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void hid_pointer_event_clear(HIDPointerEvent *e, int buttons) | static void hid_pointer_event(DeviceState *dev, QemuConsole *src, | ||||||
|  |                               InputEvent *evt) | ||||||
| { | { | ||||||
|     e->xdx = e->ydy = e->dz = 0; |     static const int bmap[INPUT_BUTTON_MAX] = { | ||||||
|     e->buttons_state = buttons; |         [INPUT_BUTTON_LEFT]   = 0x01, | ||||||
| } |         [INPUT_BUTTON_RIGHT]  = 0x02, | ||||||
|  |         [INPUT_BUTTON_MIDDLE] = 0x04, | ||||||
|  |     }; | ||||||
|  |     HIDState *hs = (HIDState *)dev; | ||||||
|  |     HIDPointerEvent *e; | ||||||
|  |  | ||||||
| static void hid_pointer_event_combine(HIDPointerEvent *e, int xyrel, |     assert(hs->n < QUEUE_LENGTH); | ||||||
|                                       int x1, int y1, int z1) { |     e = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK]; | ||||||
|     if (xyrel) { |  | ||||||
|         e->xdx += x1; |     switch (evt->kind) { | ||||||
|         e->ydy += y1; |     case INPUT_EVENT_KIND_REL: | ||||||
|  |         if (evt->rel->axis == INPUT_AXIS_X) { | ||||||
|  |             e->xdx += evt->rel->value; | ||||||
|  |         } else if (evt->rel->axis == INPUT_AXIS_Y) { | ||||||
|  |             e->ydy -= evt->rel->value; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |     case INPUT_EVENT_KIND_ABS: | ||||||
|  |         if (evt->rel->axis == INPUT_AXIS_X) { | ||||||
|  |             e->xdx = evt->rel->value; | ||||||
|  |         } else if (evt->rel->axis == INPUT_AXIS_Y) { | ||||||
|  |             e->ydy = evt->rel->value; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |     case INPUT_EVENT_KIND_BTN: | ||||||
|  |         if (evt->btn->down) { | ||||||
|  |             e->buttons_state |= bmap[evt->btn->button]; | ||||||
|  |             if (evt->btn->button == INPUT_BUTTON_WHEEL_UP) { | ||||||
|  |                 e->dz--; | ||||||
|  |             } else if (evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) { | ||||||
|  |                 e->dz++; | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|         e->xdx = x1; |             e->buttons_state &= ~bmap[evt->btn->button]; | ||||||
|         e->ydy = y1; |  | ||||||
|         /* Windows drivers do not like the 0/0 position and ignore such |  | ||||||
|          * events. */ |  | ||||||
|         if (!(x1 | y1)) { |  | ||||||
|             e->xdx = 1; |  | ||||||
|         } |         } | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |     default: | ||||||
|  |         /* keep gcc happy */ | ||||||
|  |         break; | ||||||
|     } |     } | ||||||
|     e->dz += z1; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void hid_pointer_event(void *opaque, | static void hid_pointer_sync(DeviceState *dev) | ||||||
|                               int x1, int y1, int z1, int buttons_state) |  | ||||||
| { | { | ||||||
|     HIDState *hs = opaque; |     HIDState *hs = (HIDState *)dev; | ||||||
|     unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK; |     HIDPointerEvent *prev, *curr, *next; | ||||||
|     unsigned previous_slot = (use_slot - 1) & QUEUE_MASK; |     bool event_compression = false; | ||||||
|  |  | ||||||
|     /* We combine events where feasible to keep the queue small.  We shouldn't |     if (hs->n == QUEUE_LENGTH-1) { | ||||||
|      * combine anything with the first event of a particular button state, as |         /* | ||||||
|      * that would change the location of the button state change.  When the |          * Queue full.  We are loosing information, but we at least | ||||||
|      * queue is empty, a second event is needed because we don't know if |          * keep track of most recent button state. | ||||||
|      * the first event changed the button state.  */ |          */ | ||||||
|     if (hs->n == QUEUE_LENGTH) { |         return; | ||||||
|         /* Queue full.  Discard old button state, combine motion normally.  */ |     } | ||||||
|         hs->ptr.queue[use_slot].buttons_state = buttons_state; |  | ||||||
|     } else if (hs->n < 2 || |     prev = &hs->ptr.queue[(hs->head + hs->n - 1) & QUEUE_MASK]; | ||||||
|                hs->ptr.queue[use_slot].buttons_state != buttons_state || |     curr = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK]; | ||||||
|                hs->ptr.queue[previous_slot].buttons_state != |     next = &hs->ptr.queue[(hs->head + hs->n + 1) & QUEUE_MASK]; | ||||||
|                hs->ptr.queue[use_slot].buttons_state) { |  | ||||||
|         /* Cannot or should not combine, so add an empty item to the queue.  */ |     if (hs->n > 0) { | ||||||
|         QUEUE_INCR(use_slot); |         /* | ||||||
|  |          * No button state change between previous and current event | ||||||
|  |          * (and previous wasn't seen by the guest yet), so there is | ||||||
|  |          * motion information only and we can combine the two event | ||||||
|  |          * into one. | ||||||
|  |          */ | ||||||
|  |         if (curr->buttons_state == prev->buttons_state) { | ||||||
|  |             event_compression = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (event_compression) { | ||||||
|  |         /* add current motion to previous, clear current */ | ||||||
|  |         if (hs->kind == HID_MOUSE) { | ||||||
|  |             prev->xdx += curr->xdx; | ||||||
|  |             curr->xdx = 0; | ||||||
|  |             prev->ydy -= curr->ydy; | ||||||
|  |             curr->ydy = 0; | ||||||
|  |         } else { | ||||||
|  |             prev->xdx = curr->xdx; | ||||||
|  |             prev->ydy = curr->ydy; | ||||||
|  |         } | ||||||
|  |         prev->dz += curr->dz; | ||||||
|  |         curr->dz = 0; | ||||||
|  |     } else { | ||||||
|  |         /* prepate next (clear rel, copy abs + btns) */ | ||||||
|  |         if (hs->kind == HID_MOUSE) { | ||||||
|  |             next->xdx = 0; | ||||||
|  |             next->ydy = 0; | ||||||
|  |         } else { | ||||||
|  |             next->xdx = curr->xdx; | ||||||
|  |             next->ydy = curr->ydy; | ||||||
|  |         } | ||||||
|  |         next->dz = 0; | ||||||
|  |         next->buttons_state = curr->buttons_state; | ||||||
|  |         /* make current guest visible, notify guest */ | ||||||
|         hs->n++; |         hs->n++; | ||||||
|         hid_pointer_event_clear(&hs->ptr.queue[use_slot], buttons_state); |  | ||||||
|     } |  | ||||||
|     hid_pointer_event_combine(&hs->ptr.queue[use_slot], |  | ||||||
|                               hs->kind == HID_MOUSE, |  | ||||||
|                               x1, y1, z1); |  | ||||||
|         hs->event(hs); |         hs->event(hs); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void hid_keyboard_event(void *opaque, int keycode) | static void hid_keyboard_event(DeviceState *dev, QemuConsole *src, | ||||||
|  |                                InputEvent *evt) | ||||||
| { | { | ||||||
|     HIDState *hs = opaque; |     HIDState *hs = (HIDState *)dev; | ||||||
|  |     int scancodes[3], i, count; | ||||||
|     int slot; |     int slot; | ||||||
|  |  | ||||||
|     if (hs->n == QUEUE_LENGTH) { |     count = qemu_input_key_value_to_scancode(evt->key->key, | ||||||
|  |                                              evt->key->down, | ||||||
|  |                                              scancodes); | ||||||
|  |     if (hs->n + count > QUEUE_LENGTH) { | ||||||
|         fprintf(stderr, "usb-kbd: warning: key event queue full\n"); |         fprintf(stderr, "usb-kbd: warning: key event queue full\n"); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |     for (i = 0; i < count; i++) { | ||||||
|         slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++; |         slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++; | ||||||
|     hs->kbd.keycodes[slot] = keycode; |         hs->kbd.keycodes[slot] = scancodes[i]; | ||||||
|  |     } | ||||||
|     hs->event(hs); |     hs->event(hs); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -247,14 +312,14 @@ static inline int int_clamp(int val, int vmin, int vmax) | |||||||
| void hid_pointer_activate(HIDState *hs) | void hid_pointer_activate(HIDState *hs) | ||||||
| { | { | ||||||
|     if (!hs->ptr.mouse_grabbed) { |     if (!hs->ptr.mouse_grabbed) { | ||||||
|         qemu_activate_mouse_event_handler(hs->ptr.eh_entry); |         qemu_input_handler_activate(hs->s); | ||||||
|         hs->ptr.mouse_grabbed = 1; |         hs->ptr.mouse_grabbed = 1; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len) | int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len) | ||||||
| { | { | ||||||
|     int dx, dy, dz, b, l; |     int dx, dy, dz, l; | ||||||
|     int index; |     int index; | ||||||
|     HIDPointerEvent *e; |     HIDPointerEvent *e; | ||||||
|  |  | ||||||
| @@ -279,17 +344,6 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len) | |||||||
|     dz = int_clamp(e->dz, -127, 127); |     dz = int_clamp(e->dz, -127, 127); | ||||||
|     e->dz -= dz; |     e->dz -= dz; | ||||||
|  |  | ||||||
|     b = 0; |  | ||||||
|     if (e->buttons_state & MOUSE_EVENT_LBUTTON) { |  | ||||||
|         b |= 0x01; |  | ||||||
|     } |  | ||||||
|     if (e->buttons_state & MOUSE_EVENT_RBUTTON) { |  | ||||||
|         b |= 0x02; |  | ||||||
|     } |  | ||||||
|     if (e->buttons_state & MOUSE_EVENT_MBUTTON) { |  | ||||||
|         b |= 0x04; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (hs->n && |     if (hs->n && | ||||||
|         !e->dz && |         !e->dz && | ||||||
|         (hs->kind == HID_TABLET || (!e->xdx && !e->ydy))) { |         (hs->kind == HID_TABLET || (!e->xdx && !e->ydy))) { | ||||||
| @@ -304,7 +358,7 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len) | |||||||
|     switch (hs->kind) { |     switch (hs->kind) { | ||||||
|     case HID_MOUSE: |     case HID_MOUSE: | ||||||
|         if (len > l) { |         if (len > l) { | ||||||
|             buf[l++] = b; |             buf[l++] = e->buttons_state; | ||||||
|         } |         } | ||||||
|         if (len > l) { |         if (len > l) { | ||||||
|             buf[l++] = dx; |             buf[l++] = dx; | ||||||
| @@ -319,7 +373,7 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len) | |||||||
|  |  | ||||||
|     case HID_TABLET: |     case HID_TABLET: | ||||||
|         if (len > l) { |         if (len > l) { | ||||||
|             buf[l++] = b; |             buf[l++] = e->buttons_state; | ||||||
|         } |         } | ||||||
|         if (len > l) { |         if (len > l) { | ||||||
|             buf[l++] = dx & 0xff; |             buf[l++] = dx & 0xff; | ||||||
| @@ -413,31 +467,45 @@ void hid_reset(HIDState *hs) | |||||||
|  |  | ||||||
| void hid_free(HIDState *hs) | void hid_free(HIDState *hs) | ||||||
| { | { | ||||||
|     switch (hs->kind) { |     qemu_input_handler_unregister(hs->s); | ||||||
|     case HID_KEYBOARD: |  | ||||||
|         qemu_remove_kbd_event_handler(hs->kbd.eh_entry); |  | ||||||
|         break; |  | ||||||
|     case HID_MOUSE: |  | ||||||
|     case HID_TABLET: |  | ||||||
|         qemu_remove_mouse_event_handler(hs->ptr.eh_entry); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     hid_del_idle_timer(hs); |     hid_del_idle_timer(hs); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static QemuInputHandler hid_keyboard_handler = { | ||||||
|  |     .name  = "QEMU HID Keyboard", | ||||||
|  |     .mask  = INPUT_EVENT_MASK_KEY, | ||||||
|  |     .event = hid_keyboard_event, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static QemuInputHandler hid_mouse_handler = { | ||||||
|  |     .name  = "QEMU HID Mouse", | ||||||
|  |     .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, | ||||||
|  |     .event = hid_pointer_event, | ||||||
|  |     .sync  = hid_pointer_sync, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static QemuInputHandler hid_tablet_handler = { | ||||||
|  |     .name  = "QEMU HID Tablet", | ||||||
|  |     .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS, | ||||||
|  |     .event = hid_pointer_event, | ||||||
|  |     .sync  = hid_pointer_sync, | ||||||
|  | }; | ||||||
|  |  | ||||||
| void hid_init(HIDState *hs, int kind, HIDEventFunc event) | void hid_init(HIDState *hs, int kind, HIDEventFunc event) | ||||||
| { | { | ||||||
|     hs->kind = kind; |     hs->kind = kind; | ||||||
|     hs->event = event; |     hs->event = event; | ||||||
|  |  | ||||||
|     if (hs->kind == HID_KEYBOARD) { |     if (hs->kind == HID_KEYBOARD) { | ||||||
|         hs->kbd.eh_entry = qemu_add_kbd_event_handler(hid_keyboard_event, hs); |         hs->s = qemu_input_handler_register((DeviceState *)hs, | ||||||
|  |                                             &hid_keyboard_handler); | ||||||
|  |         qemu_input_handler_activate(hs->s); | ||||||
|     } else if (hs->kind == HID_MOUSE) { |     } else if (hs->kind == HID_MOUSE) { | ||||||
|         hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs, |         hs->s = qemu_input_handler_register((DeviceState *)hs, | ||||||
|                                                         0, "QEMU HID Mouse"); |                                             &hid_mouse_handler); | ||||||
|     } else if (hs->kind == HID_TABLET) { |     } else if (hs->kind == HID_TABLET) { | ||||||
|         hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs, |         hs->s = qemu_input_handler_register((DeviceState *)hs, | ||||||
|                                                         1, "QEMU HID Tablet"); |                                             &hid_tablet_handler); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,3 +26,4 @@ obj-$(CONFIG_XICS) += xics.o | |||||||
| obj-$(CONFIG_XICS_KVM) += xics_kvm.o | obj-$(CONFIG_XICS_KVM) += xics_kvm.o | ||||||
| obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o | obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o | ||||||
| obj-$(CONFIG_S390_FLIC) += s390_flic.o | obj-$(CONFIG_S390_FLIC) += s390_flic.o | ||||||
|  | obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o | ||||||
|   | |||||||
| @@ -1,322 +1,103 @@ | |||||||
| /* | /* | ||||||
|  * QEMU S390x KVM floating interrupt controller (flic) |  * QEMU S390x floating interrupt controller (flic) | ||||||
|  * |  * | ||||||
|  * Copyright 2014 IBM Corp. |  * Copyright 2014 IBM Corp. | ||||||
|  * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com> |  * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com> | ||||||
|  |  *            Cornelia Huck <cornelia.huck@de.ibm.com> | ||||||
|  * |  * | ||||||
|  * This work is licensed under the terms of the GNU GPL, version 2 or (at |  * This work is licensed under the terms of the GNU GPL, version 2 or (at | ||||||
|  * your option) any later version. See the COPYING file in the top-level |  * your option) any later version. See the COPYING file in the top-level | ||||||
|  * directory. |  * directory. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <sys/ioctl.h> |  | ||||||
| #include "qemu/error-report.h" | #include "qemu/error-report.h" | ||||||
| #include "hw/sysbus.h" | #include "hw/sysbus.h" | ||||||
| #include "sysemu/kvm.h" |  | ||||||
| #include "migration/qemu-file.h" | #include "migration/qemu-file.h" | ||||||
| #include "hw/s390x/s390_flic.h" | #include "hw/s390x/s390_flic.h" | ||||||
| #include "trace.h" | #include "trace.h" | ||||||
|  |  | ||||||
| #define FLIC_SAVE_INITIAL_SIZE getpagesize() | S390FLICState *s390_get_flic(void) | ||||||
| #define FLIC_FAILED (-1UL) | { | ||||||
| #define FLIC_SAVEVM_VERSION 1 |     S390FLICState *fs; | ||||||
|  |  | ||||||
|  |     fs = S390_FLIC_COMMON(object_resolve_path(TYPE_KVM_S390_FLIC, NULL)); | ||||||
|  |     if (!fs) { | ||||||
|  |         fs = S390_FLIC_COMMON(object_resolve_path(TYPE_QEMU_S390_FLIC, NULL)); | ||||||
|  |     } | ||||||
|  |     return fs; | ||||||
|  | } | ||||||
|  |  | ||||||
| void s390_flic_init(void) | void s390_flic_init(void) | ||||||
| { | { | ||||||
|     DeviceState *dev; |     DeviceState *dev; | ||||||
|     int r; |     int r; | ||||||
|  |  | ||||||
|     if (kvm_enabled()) { |     dev = s390_flic_kvm_create(); | ||||||
|         dev = qdev_create(NULL, "s390-flic"); |     if (!dev) { | ||||||
|         object_property_add_child(qdev_get_machine(), "s390-flic", |         dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC); | ||||||
|  |         object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC, | ||||||
|                                   OBJECT(dev), NULL); |                                   OBJECT(dev), NULL); | ||||||
|  |     } | ||||||
|     r = qdev_init(dev); |     r = qdev_init(dev); | ||||||
|     if (r) { |     if (r) { | ||||||
|         error_report("flic: couldn't create qdev"); |         error_report("flic: couldn't create qdev"); | ||||||
|     } |     } | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id, | ||||||
|  * flic_get_all_irqs - store all pending irqs in buffer |                                          uint8_t isc, bool swap, | ||||||
|  * @buf: pointer to buffer which is passed to kernel |                                          bool is_maskable) | ||||||
|  * @len: length of buffer |  | ||||||
|  * @flic: pointer to flic device state |  | ||||||
|  * |  | ||||||
|  * Returns: -ENOMEM if buffer is too small, |  | ||||||
|  * -EINVAL if attr.group is invalid, |  | ||||||
|  * -EFAULT if copying to userspace failed, |  | ||||||
|  * on success return number of stored interrupts |  | ||||||
|  */ |  | ||||||
| static int flic_get_all_irqs(KVMS390FLICState *flic, |  | ||||||
|                              void *buf, int len) |  | ||||||
| { | { | ||||||
|     struct kvm_device_attr attr = { |     /* nothing to do */ | ||||||
|         .group = KVM_DEV_FLIC_GET_ALL_IRQS, |     return 0; | ||||||
|         .addr = (uint64_t) buf, |  | ||||||
|         .attr = len, |  | ||||||
|     }; |  | ||||||
|     int rc; |  | ||||||
|  |  | ||||||
|     rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr); |  | ||||||
|  |  | ||||||
|     return rc == -1 ? -errno : rc; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void flic_enable_pfault(KVMS390FLICState *flic) | static int qemu_s390_io_adapter_map(S390FLICState *fs, uint32_t id, | ||||||
|  |                                     uint64_t map_addr, bool do_map) | ||||||
| { | { | ||||||
|     struct kvm_device_attr attr = { |     /* nothing to do */ | ||||||
|         .group = KVM_DEV_FLIC_APF_ENABLE, |     return 0; | ||||||
|     }; |  | ||||||
|     int rc; |  | ||||||
|  |  | ||||||
|     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); |  | ||||||
|  |  | ||||||
|     if (rc) { |  | ||||||
|         fprintf(stderr, "flic: couldn't enable pfault\n"); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void flic_disable_wait_pfault(KVMS390FLICState *flic) | static int qemu_s390_add_adapter_routes(S390FLICState *fs, | ||||||
|  |                                         AdapterRoutes *routes) | ||||||
| { | { | ||||||
|     struct kvm_device_attr attr = { |     return -ENOSYS; | ||||||
|         .group = KVM_DEV_FLIC_APF_DISABLE_WAIT, |  | ||||||
|     }; |  | ||||||
|     int rc; |  | ||||||
|  |  | ||||||
|     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); |  | ||||||
|  |  | ||||||
|     if (rc) { |  | ||||||
|         fprintf(stderr, "flic: couldn't disable pfault\n"); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /** flic_enqueue_irqs - returns 0 on success | static void qemu_s390_release_adapter_routes(S390FLICState *fs, | ||||||
|  * @buf: pointer to buffer which is passed to kernel |                                              AdapterRoutes *routes) | ||||||
|  * @len: length of buffer |  | ||||||
|  * @flic: pointer to flic device state |  | ||||||
|  * |  | ||||||
|  * Returns: -EINVAL if attr.group is unknown |  | ||||||
|  */ |  | ||||||
| static int flic_enqueue_irqs(void *buf, uint64_t len, |  | ||||||
|                             KVMS390FLICState *flic) |  | ||||||
| { | { | ||||||
|     int rc; |  | ||||||
|     struct kvm_device_attr attr = { |  | ||||||
|         .group = KVM_DEV_FLIC_ENQUEUE, |  | ||||||
|         .addr = (uint64_t) buf, |  | ||||||
|         .attr = len, |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); |  | ||||||
|  |  | ||||||
|     return rc ? -errno : 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) | ||||||
|  * __get_all_irqs - store all pending irqs in buffer |  | ||||||
|  * @flic: pointer to flic device state |  | ||||||
|  * @buf: pointer to pointer to a buffer |  | ||||||
|  * @len: length of buffer |  | ||||||
|  * |  | ||||||
|  * Returns: return value of flic_get_all_irqs |  | ||||||
|  * Note: Retry and increase buffer size until flic_get_all_irqs |  | ||||||
|  * either returns a value >= 0 or a negative error code. |  | ||||||
|  * -ENOMEM is an exception, which means the buffer is too small |  | ||||||
|  * and we should try again. Other negative error codes can be |  | ||||||
|  * -EFAULT and -EINVAL which we ignore at this point |  | ||||||
|  */ |  | ||||||
| static int __get_all_irqs(KVMS390FLICState *flic, |  | ||||||
|                           void **buf, int len) |  | ||||||
| { | { | ||||||
|     int r; |     S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); | ||||||
|  |  | ||||||
|     do { |     fsc->register_io_adapter = qemu_s390_register_io_adapter; | ||||||
|         /* returns -ENOMEM if buffer is too small and number |     fsc->io_adapter_map = qemu_s390_io_adapter_map; | ||||||
|          * of queued interrupts on success */ |     fsc->add_adapter_routes = qemu_s390_add_adapter_routes; | ||||||
|         r = flic_get_all_irqs(flic, *buf, len); |     fsc->release_adapter_routes = qemu_s390_release_adapter_routes; | ||||||
|         if (r >= 0) { |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         len *= 2; |  | ||||||
|         *buf = g_try_realloc(*buf, len); |  | ||||||
|         if (!buf) { |  | ||||||
|             return -ENOMEM; |  | ||||||
|         } |  | ||||||
|     } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER); |  | ||||||
|  |  | ||||||
|     return r; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | static const TypeInfo qemu_s390_flic_info = { | ||||||
|  * kvm_flic_save - Save pending floating interrupts |     .name          = TYPE_QEMU_S390_FLIC, | ||||||
|  * @f: QEMUFile containing migration state |     .parent        = TYPE_S390_FLIC_COMMON, | ||||||
|  * @opaque: pointer to flic device state |     .instance_size = sizeof(QEMUS390FLICState), | ||||||
|  * |     .class_init    = qemu_s390_flic_class_init, | ||||||
|  * Note: Pass buf and len to kernel. Start with one page and |  | ||||||
|  * increase until buffer is sufficient or maxium size is |  | ||||||
|  * reached |  | ||||||
|  */ |  | ||||||
| static void kvm_flic_save(QEMUFile *f, void *opaque) |  | ||||||
| { |  | ||||||
|     KVMS390FLICState *flic = opaque; |  | ||||||
|     int len = FLIC_SAVE_INITIAL_SIZE; |  | ||||||
|     void *buf; |  | ||||||
|     int count; |  | ||||||
|  |  | ||||||
|     flic_disable_wait_pfault((struct KVMS390FLICState *) opaque); |  | ||||||
|  |  | ||||||
|     buf = g_try_malloc0(len); |  | ||||||
|     if (!buf) { |  | ||||||
|         /* Storing FLIC_FAILED into the count field here will cause the |  | ||||||
|          * target system to fail when attempting to load irqs from the |  | ||||||
|          * migration state */ |  | ||||||
|         error_report("flic: couldn't allocate memory"); |  | ||||||
|         qemu_put_be64(f, FLIC_FAILED); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     count = __get_all_irqs(flic, &buf, len); |  | ||||||
|     if (count < 0) { |  | ||||||
|         error_report("flic: couldn't retrieve irqs from kernel, rc %d", |  | ||||||
|                      count); |  | ||||||
|         /* Storing FLIC_FAILED into the count field here will cause the |  | ||||||
|          * target system to fail when attempting to load irqs from the |  | ||||||
|          * migration state */ |  | ||||||
|         qemu_put_be64(f, FLIC_FAILED); |  | ||||||
|     } else { |  | ||||||
|         qemu_put_be64(f, count); |  | ||||||
|         qemu_put_buffer(f, (uint8_t *) buf, |  | ||||||
|                         count * sizeof(struct kvm_s390_irq)); |  | ||||||
|     } |  | ||||||
|     g_free(buf); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * kvm_flic_load - Load pending floating interrupts |  | ||||||
|  * @f: QEMUFile containing migration state |  | ||||||
|  * @opaque: pointer to flic device state |  | ||||||
|  * @version_id: version id for migration |  | ||||||
|  * |  | ||||||
|  * Returns: value of flic_enqueue_irqs, -EINVAL on error |  | ||||||
|  * Note: Do nothing when no interrupts where stored |  | ||||||
|  * in QEMUFile |  | ||||||
|  */ |  | ||||||
| static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id) |  | ||||||
| { |  | ||||||
|     uint64_t len = 0; |  | ||||||
|     uint64_t count = 0; |  | ||||||
|     void *buf = NULL; |  | ||||||
|     int r = 0; |  | ||||||
|  |  | ||||||
|     if (version_id != FLIC_SAVEVM_VERSION) { |  | ||||||
|         r = -EINVAL; |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     flic_enable_pfault((struct KVMS390FLICState *) opaque); |  | ||||||
|  |  | ||||||
|     count = qemu_get_be64(f); |  | ||||||
|     len = count * sizeof(struct kvm_s390_irq); |  | ||||||
|     if (count == FLIC_FAILED) { |  | ||||||
|         r = -EINVAL; |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|     if (count == 0) { |  | ||||||
|         r = 0; |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|     buf = g_try_malloc0(len); |  | ||||||
|     if (!buf) { |  | ||||||
|         r = -ENOMEM; |  | ||||||
|         goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) { |  | ||||||
|         r = -EINVAL; |  | ||||||
|         goto out_free; |  | ||||||
|     } |  | ||||||
|     r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque); |  | ||||||
|  |  | ||||||
| out_free: |  | ||||||
|     g_free(buf); |  | ||||||
| out: |  | ||||||
|     return r; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) |  | ||||||
| { |  | ||||||
|     KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); |  | ||||||
|     struct kvm_create_device cd = {0}; |  | ||||||
|     int ret; |  | ||||||
|  |  | ||||||
|     flic_state->fd = -1; |  | ||||||
|     if (!kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) { |  | ||||||
|         trace_flic_no_device_api(errno); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     cd.type = KVM_DEV_TYPE_FLIC; |  | ||||||
|     ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd); |  | ||||||
|     if (ret < 0) { |  | ||||||
|         trace_flic_create_device(errno); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     flic_state->fd = cd.fd; |  | ||||||
|  |  | ||||||
|     /* Register savevm handler for floating interrupts */ |  | ||||||
|     register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save, |  | ||||||
|                     kvm_flic_load, (void *) flic_state); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void kvm_s390_flic_unrealize(DeviceState *dev, Error **errp) |  | ||||||
| { |  | ||||||
|     KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); |  | ||||||
|  |  | ||||||
|     unregister_savevm(DEVICE(flic_state), "s390-flic", flic_state); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void kvm_s390_flic_reset(DeviceState *dev) |  | ||||||
| { |  | ||||||
|     KVMS390FLICState *flic = KVM_S390_FLIC(dev); |  | ||||||
|     struct kvm_device_attr attr = { |  | ||||||
|         .group = KVM_DEV_FLIC_CLEAR_IRQS, |  | ||||||
|     }; |  | ||||||
|     int rc = 0; |  | ||||||
|  |  | ||||||
|     if (flic->fd == -1) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     flic_disable_wait_pfault(flic); |  | ||||||
|  |  | ||||||
|     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); |  | ||||||
|     if (rc) { |  | ||||||
|         trace_flic_reset_failed(errno); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     flic_enable_pfault(flic); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) |  | ||||||
| { |  | ||||||
|     DeviceClass *dc = DEVICE_CLASS(oc); |  | ||||||
|  |  | ||||||
|     dc->realize = kvm_s390_flic_realize; |  | ||||||
|     dc->unrealize = kvm_s390_flic_unrealize; |  | ||||||
|     dc->reset = kvm_s390_flic_reset; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static const TypeInfo kvm_s390_flic_info = { |  | ||||||
|     .name          = TYPE_KVM_S390_FLIC, |  | ||||||
|     .parent        = TYPE_SYS_BUS_DEVICE, |  | ||||||
|     .instance_size = sizeof(KVMS390FLICState), |  | ||||||
|     .class_init    = kvm_s390_flic_class_init, |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void kvm_s390_flic_register_types(void) | static const TypeInfo s390_flic_common_info = { | ||||||
|  |     .name          = TYPE_S390_FLIC_COMMON, | ||||||
|  |     .parent        = TYPE_SYS_BUS_DEVICE, | ||||||
|  |     .instance_size = sizeof(S390FLICState), | ||||||
|  |     .class_size    = sizeof(S390FLICStateClass), | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static void qemu_s390_flic_register_types(void) | ||||||
| { | { | ||||||
|     type_register_static(&kvm_s390_flic_info); |     type_register_static(&s390_flic_common_info); | ||||||
|  |     type_register_static(&qemu_s390_flic_info); | ||||||
| } | } | ||||||
|  |  | ||||||
| type_init(kvm_s390_flic_register_types) | type_init(qemu_s390_flic_register_types) | ||||||
|   | |||||||
							
								
								
									
										420
									
								
								hw/intc/s390_flic_kvm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								hw/intc/s390_flic_kvm.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,420 @@ | |||||||
|  | /* | ||||||
|  |  * QEMU S390x KVM floating interrupt controller (flic) | ||||||
|  |  * | ||||||
|  |  * Copyright 2014 IBM Corp. | ||||||
|  |  * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com> | ||||||
|  |  *            Cornelia Huck <cornelia.huck@de.ibm.com> | ||||||
|  |  * | ||||||
|  |  * This work is licensed under the terms of the GNU GPL, version 2 or (at | ||||||
|  |  * your option) any later version. See the COPYING file in the top-level | ||||||
|  |  * directory. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <sys/ioctl.h> | ||||||
|  | #include "qemu/error-report.h" | ||||||
|  | #include "hw/sysbus.h" | ||||||
|  | #include "sysemu/kvm.h" | ||||||
|  | #include "migration/qemu-file.h" | ||||||
|  | #include "hw/s390x/s390_flic.h" | ||||||
|  | #include "hw/s390x/adapter.h" | ||||||
|  | #include "trace.h" | ||||||
|  |  | ||||||
|  | #define FLIC_SAVE_INITIAL_SIZE getpagesize() | ||||||
|  | #define FLIC_FAILED (-1UL) | ||||||
|  | #define FLIC_SAVEVM_VERSION 1 | ||||||
|  |  | ||||||
|  | typedef struct KVMS390FLICState { | ||||||
|  |     S390FLICState parent_obj; | ||||||
|  |  | ||||||
|  |     uint32_t fd; | ||||||
|  | } KVMS390FLICState; | ||||||
|  |  | ||||||
|  | DeviceState *s390_flic_kvm_create(void) | ||||||
|  | { | ||||||
|  |     DeviceState *dev = NULL; | ||||||
|  |  | ||||||
|  |     if (kvm_enabled()) { | ||||||
|  |         dev = qdev_create(NULL, TYPE_KVM_S390_FLIC); | ||||||
|  |         object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC, | ||||||
|  |                                   OBJECT(dev), NULL); | ||||||
|  |     } | ||||||
|  |     return dev; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * flic_get_all_irqs - store all pending irqs in buffer | ||||||
|  |  * @buf: pointer to buffer which is passed to kernel | ||||||
|  |  * @len: length of buffer | ||||||
|  |  * @flic: pointer to flic device state | ||||||
|  |  * | ||||||
|  |  * Returns: -ENOMEM if buffer is too small, | ||||||
|  |  * -EINVAL if attr.group is invalid, | ||||||
|  |  * -EFAULT if copying to userspace failed, | ||||||
|  |  * on success return number of stored interrupts | ||||||
|  |  */ | ||||||
|  | static int flic_get_all_irqs(KVMS390FLICState *flic, | ||||||
|  |                              void *buf, int len) | ||||||
|  | { | ||||||
|  |     struct kvm_device_attr attr = { | ||||||
|  |         .group = KVM_DEV_FLIC_GET_ALL_IRQS, | ||||||
|  |         .addr = (uint64_t) buf, | ||||||
|  |         .attr = len, | ||||||
|  |     }; | ||||||
|  |     int rc; | ||||||
|  |  | ||||||
|  |     rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr); | ||||||
|  |  | ||||||
|  |     return rc == -1 ? -errno : rc; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void flic_enable_pfault(KVMS390FLICState *flic) | ||||||
|  | { | ||||||
|  |     struct kvm_device_attr attr = { | ||||||
|  |         .group = KVM_DEV_FLIC_APF_ENABLE, | ||||||
|  |     }; | ||||||
|  |     int rc; | ||||||
|  |  | ||||||
|  |     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); | ||||||
|  |  | ||||||
|  |     if (rc) { | ||||||
|  |         fprintf(stderr, "flic: couldn't enable pfault\n"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void flic_disable_wait_pfault(KVMS390FLICState *flic) | ||||||
|  | { | ||||||
|  |     struct kvm_device_attr attr = { | ||||||
|  |         .group = KVM_DEV_FLIC_APF_DISABLE_WAIT, | ||||||
|  |     }; | ||||||
|  |     int rc; | ||||||
|  |  | ||||||
|  |     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); | ||||||
|  |  | ||||||
|  |     if (rc) { | ||||||
|  |         fprintf(stderr, "flic: couldn't disable pfault\n"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** flic_enqueue_irqs - returns 0 on success | ||||||
|  |  * @buf: pointer to buffer which is passed to kernel | ||||||
|  |  * @len: length of buffer | ||||||
|  |  * @flic: pointer to flic device state | ||||||
|  |  * | ||||||
|  |  * Returns: -EINVAL if attr.group is unknown | ||||||
|  |  */ | ||||||
|  | static int flic_enqueue_irqs(void *buf, uint64_t len, | ||||||
|  |                             KVMS390FLICState *flic) | ||||||
|  | { | ||||||
|  |     int rc; | ||||||
|  |     struct kvm_device_attr attr = { | ||||||
|  |         .group = KVM_DEV_FLIC_ENQUEUE, | ||||||
|  |         .addr = (uint64_t) buf, | ||||||
|  |         .attr = len, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); | ||||||
|  |  | ||||||
|  |     return rc ? -errno : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * __get_all_irqs - store all pending irqs in buffer | ||||||
|  |  * @flic: pointer to flic device state | ||||||
|  |  * @buf: pointer to pointer to a buffer | ||||||
|  |  * @len: length of buffer | ||||||
|  |  * | ||||||
|  |  * Returns: return value of flic_get_all_irqs | ||||||
|  |  * Note: Retry and increase buffer size until flic_get_all_irqs | ||||||
|  |  * either returns a value >= 0 or a negative error code. | ||||||
|  |  * -ENOMEM is an exception, which means the buffer is too small | ||||||
|  |  * and we should try again. Other negative error codes can be | ||||||
|  |  * -EFAULT and -EINVAL which we ignore at this point | ||||||
|  |  */ | ||||||
|  | static int __get_all_irqs(KVMS390FLICState *flic, | ||||||
|  |                           void **buf, int len) | ||||||
|  | { | ||||||
|  |     int r; | ||||||
|  |  | ||||||
|  |     do { | ||||||
|  |         /* returns -ENOMEM if buffer is too small and number | ||||||
|  |          * of queued interrupts on success */ | ||||||
|  |         r = flic_get_all_irqs(flic, *buf, len); | ||||||
|  |         if (r >= 0) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         len *= 2; | ||||||
|  |         *buf = g_try_realloc(*buf, len); | ||||||
|  |         if (!buf) { | ||||||
|  |             return -ENOMEM; | ||||||
|  |         } | ||||||
|  |     } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER); | ||||||
|  |  | ||||||
|  |     return r; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id, | ||||||
|  |                                         uint8_t isc, bool swap, | ||||||
|  |                                         bool is_maskable) | ||||||
|  | { | ||||||
|  |     struct kvm_s390_io_adapter adapter = { | ||||||
|  |         .id = id, | ||||||
|  |         .isc = isc, | ||||||
|  |         .maskable = is_maskable, | ||||||
|  |         .swap = swap, | ||||||
|  |     }; | ||||||
|  |     KVMS390FLICState *flic = KVM_S390_FLIC(fs); | ||||||
|  |     int r, ret; | ||||||
|  |     struct kvm_device_attr attr = { | ||||||
|  |         .group = KVM_DEV_FLIC_ADAPTER_REGISTER, | ||||||
|  |         .addr = (uint64_t)&adapter, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) { | ||||||
|  |         return -ENOSYS; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); | ||||||
|  |  | ||||||
|  |     ret = r ? -errno : 0; | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id, | ||||||
|  |                                    uint64_t map_addr, bool do_map) | ||||||
|  | { | ||||||
|  |     struct kvm_s390_io_adapter_req req = { | ||||||
|  |         .id = id, | ||||||
|  |         .type = do_map ? KVM_S390_IO_ADAPTER_MAP : KVM_S390_IO_ADAPTER_UNMAP, | ||||||
|  |         .addr = map_addr, | ||||||
|  |     }; | ||||||
|  |     struct kvm_device_attr attr = { | ||||||
|  |         .group = KVM_DEV_FLIC_ADAPTER_MODIFY, | ||||||
|  |         .addr = (uint64_t)&req, | ||||||
|  |     }; | ||||||
|  |     KVMS390FLICState *flic = KVM_S390_FLIC(fs); | ||||||
|  |     int r; | ||||||
|  |  | ||||||
|  |     if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) { | ||||||
|  |         return -ENOSYS; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); | ||||||
|  |     return r ? -errno : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int kvm_s390_add_adapter_routes(S390FLICState *fs, | ||||||
|  |                                        AdapterRoutes *routes) | ||||||
|  | { | ||||||
|  |     int ret, i; | ||||||
|  |     uint64_t ind_offset = routes->adapter.ind_offset; | ||||||
|  |  | ||||||
|  |     for (i = 0; i < routes->num_routes; i++) { | ||||||
|  |         ret = kvm_irqchip_add_adapter_route(kvm_state, &routes->adapter); | ||||||
|  |         if (ret < 0) { | ||||||
|  |             goto out_undo; | ||||||
|  |         } | ||||||
|  |         routes->gsi[i] = ret; | ||||||
|  |         routes->adapter.ind_offset++; | ||||||
|  |     } | ||||||
|  |     /* Restore passed-in structure to original state. */ | ||||||
|  |     routes->adapter.ind_offset = ind_offset; | ||||||
|  |     return 0; | ||||||
|  | out_undo: | ||||||
|  |     while (--i >= 0) { | ||||||
|  |         kvm_irqchip_release_virq(kvm_state, routes->gsi[i]); | ||||||
|  |         routes->gsi[i] = -1; | ||||||
|  |     } | ||||||
|  |     routes->adapter.ind_offset = ind_offset; | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void kvm_s390_release_adapter_routes(S390FLICState *fs, | ||||||
|  |                                             AdapterRoutes *routes) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |  | ||||||
|  |     for (i = 0; i < routes->num_routes; i++) { | ||||||
|  |         if (routes->gsi[i] >= 0) { | ||||||
|  |             kvm_irqchip_release_virq(kvm_state, routes->gsi[i]); | ||||||
|  |             routes->gsi[i] = -1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * kvm_flic_save - Save pending floating interrupts | ||||||
|  |  * @f: QEMUFile containing migration state | ||||||
|  |  * @opaque: pointer to flic device state | ||||||
|  |  * | ||||||
|  |  * Note: Pass buf and len to kernel. Start with one page and | ||||||
|  |  * increase until buffer is sufficient or maxium size is | ||||||
|  |  * reached | ||||||
|  |  */ | ||||||
|  | static void kvm_flic_save(QEMUFile *f, void *opaque) | ||||||
|  | { | ||||||
|  |     KVMS390FLICState *flic = opaque; | ||||||
|  |     int len = FLIC_SAVE_INITIAL_SIZE; | ||||||
|  |     void *buf; | ||||||
|  |     int count; | ||||||
|  |  | ||||||
|  |     flic_disable_wait_pfault((struct KVMS390FLICState *) opaque); | ||||||
|  |  | ||||||
|  |     buf = g_try_malloc0(len); | ||||||
|  |     if (!buf) { | ||||||
|  |         /* Storing FLIC_FAILED into the count field here will cause the | ||||||
|  |          * target system to fail when attempting to load irqs from the | ||||||
|  |          * migration state */ | ||||||
|  |         error_report("flic: couldn't allocate memory"); | ||||||
|  |         qemu_put_be64(f, FLIC_FAILED); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     count = __get_all_irqs(flic, &buf, len); | ||||||
|  |     if (count < 0) { | ||||||
|  |         error_report("flic: couldn't retrieve irqs from kernel, rc %d", | ||||||
|  |                      count); | ||||||
|  |         /* Storing FLIC_FAILED into the count field here will cause the | ||||||
|  |          * target system to fail when attempting to load irqs from the | ||||||
|  |          * migration state */ | ||||||
|  |         qemu_put_be64(f, FLIC_FAILED); | ||||||
|  |     } else { | ||||||
|  |         qemu_put_be64(f, count); | ||||||
|  |         qemu_put_buffer(f, (uint8_t *) buf, | ||||||
|  |                         count * sizeof(struct kvm_s390_irq)); | ||||||
|  |     } | ||||||
|  |     g_free(buf); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * kvm_flic_load - Load pending floating interrupts | ||||||
|  |  * @f: QEMUFile containing migration state | ||||||
|  |  * @opaque: pointer to flic device state | ||||||
|  |  * @version_id: version id for migration | ||||||
|  |  * | ||||||
|  |  * Returns: value of flic_enqueue_irqs, -EINVAL on error | ||||||
|  |  * Note: Do nothing when no interrupts where stored | ||||||
|  |  * in QEMUFile | ||||||
|  |  */ | ||||||
|  | static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id) | ||||||
|  | { | ||||||
|  |     uint64_t len = 0; | ||||||
|  |     uint64_t count = 0; | ||||||
|  |     void *buf = NULL; | ||||||
|  |     int r = 0; | ||||||
|  |  | ||||||
|  |     if (version_id != FLIC_SAVEVM_VERSION) { | ||||||
|  |         r = -EINVAL; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     flic_enable_pfault((struct KVMS390FLICState *) opaque); | ||||||
|  |  | ||||||
|  |     count = qemu_get_be64(f); | ||||||
|  |     len = count * sizeof(struct kvm_s390_irq); | ||||||
|  |     if (count == FLIC_FAILED) { | ||||||
|  |         r = -EINVAL; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |     if (count == 0) { | ||||||
|  |         r = 0; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |     buf = g_try_malloc0(len); | ||||||
|  |     if (!buf) { | ||||||
|  |         r = -ENOMEM; | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) { | ||||||
|  |         r = -EINVAL; | ||||||
|  |         goto out_free; | ||||||
|  |     } | ||||||
|  |     r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque); | ||||||
|  |  | ||||||
|  | out_free: | ||||||
|  |     g_free(buf); | ||||||
|  | out: | ||||||
|  |     return r; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) | ||||||
|  | { | ||||||
|  |     KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); | ||||||
|  |     struct kvm_create_device cd = {0}; | ||||||
|  |     int ret; | ||||||
|  |  | ||||||
|  |     flic_state->fd = -1; | ||||||
|  |     if (!kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) { | ||||||
|  |         trace_flic_no_device_api(errno); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     cd.type = KVM_DEV_TYPE_FLIC; | ||||||
|  |     ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd); | ||||||
|  |     if (ret < 0) { | ||||||
|  |         trace_flic_create_device(errno); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     flic_state->fd = cd.fd; | ||||||
|  |  | ||||||
|  |     /* Register savevm handler for floating interrupts */ | ||||||
|  |     register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save, | ||||||
|  |                     kvm_flic_load, (void *) flic_state); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void kvm_s390_flic_unrealize(DeviceState *dev, Error **errp) | ||||||
|  | { | ||||||
|  |     KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); | ||||||
|  |  | ||||||
|  |     unregister_savevm(DEVICE(flic_state), "s390-flic", flic_state); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void kvm_s390_flic_reset(DeviceState *dev) | ||||||
|  | { | ||||||
|  |     KVMS390FLICState *flic = KVM_S390_FLIC(dev); | ||||||
|  |     struct kvm_device_attr attr = { | ||||||
|  |         .group = KVM_DEV_FLIC_CLEAR_IRQS, | ||||||
|  |     }; | ||||||
|  |     int rc = 0; | ||||||
|  |  | ||||||
|  |     if (flic->fd == -1) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     flic_disable_wait_pfault(flic); | ||||||
|  |  | ||||||
|  |     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); | ||||||
|  |     if (rc) { | ||||||
|  |         trace_flic_reset_failed(errno); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     flic_enable_pfault(flic); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) | ||||||
|  | { | ||||||
|  |     DeviceClass *dc = DEVICE_CLASS(oc); | ||||||
|  |     S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); | ||||||
|  |  | ||||||
|  |     dc->realize = kvm_s390_flic_realize; | ||||||
|  |     dc->unrealize = kvm_s390_flic_unrealize; | ||||||
|  |     dc->reset = kvm_s390_flic_reset; | ||||||
|  |     fsc->register_io_adapter = kvm_s390_register_io_adapter; | ||||||
|  |     fsc->io_adapter_map = kvm_s390_io_adapter_map; | ||||||
|  |     fsc->add_adapter_routes = kvm_s390_add_adapter_routes; | ||||||
|  |     fsc->release_adapter_routes = kvm_s390_release_adapter_routes; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const TypeInfo kvm_s390_flic_info = { | ||||||
|  |     .name          = TYPE_KVM_S390_FLIC, | ||||||
|  |     .parent        = TYPE_S390_FLIC_COMMON, | ||||||
|  |     .instance_size = sizeof(KVMS390FLICState), | ||||||
|  |     .class_init    = kvm_s390_flic_class_init, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static void kvm_s390_flic_register_types(void) | ||||||
|  | { | ||||||
|  |     type_register_static(&kvm_s390_flic_info); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type_init(kvm_s390_flic_register_types) | ||||||
| @@ -69,10 +69,10 @@ static void main_cpu_reset(void *opaque) | |||||||
|     env->deba = reset_info->flash_base; |     env->deba = reset_info->flash_base; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void lm32_evr_init(QEMUMachineInitArgs *args) | static void lm32_evr_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     LM32CPU *cpu; |     LM32CPU *cpu; | ||||||
|     CPULM32State *env; |     CPULM32State *env; | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
| @@ -162,12 +162,12 @@ static void lm32_evr_init(QEMUMachineInitArgs *args) | |||||||
|     qemu_register_reset(main_cpu_reset, reset_info); |     qemu_register_reset(main_cpu_reset, reset_info); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void lm32_uclinux_init(QEMUMachineInitArgs *args) | static void lm32_uclinux_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     LM32CPU *cpu; |     LM32CPU *cpu; | ||||||
|     CPULM32State *env; |     CPULM32State *env; | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
|   | |||||||
| @@ -74,12 +74,12 @@ static void main_cpu_reset(void *opaque) | |||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| milkymist_init(QEMUMachineInitArgs *args) | milkymist_init(MachineState *machine) | ||||||
| { | { | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     LM32CPU *cpu; |     LM32CPU *cpu; | ||||||
|     CPULM32State *env; |     CPULM32State *env; | ||||||
|     int kernel_size; |     int kernel_size; | ||||||
|   | |||||||
| @@ -20,11 +20,11 @@ | |||||||
|  |  | ||||||
| /* Board init.  */ | /* Board init.  */ | ||||||
|  |  | ||||||
| static void an5206_init(QEMUMachineInitArgs *args) | static void an5206_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     M68kCPU *cpu; |     M68kCPU *cpu; | ||||||
|     CPUM68KState *env; |     CPUM68KState *env; | ||||||
|     int kernel_size; |     int kernel_size; | ||||||
|   | |||||||
| @@ -16,11 +16,11 @@ | |||||||
|  |  | ||||||
| /* Board init.  */ | /* Board init.  */ | ||||||
|  |  | ||||||
| static void dummy_m68k_init(QEMUMachineInitArgs *args) | static void dummy_m68k_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     CPUM68KState *env; |     CPUM68KState *env; | ||||||
|     MemoryRegion *address_space_mem =  get_system_memory(); |     MemoryRegion *address_space_mem =  get_system_memory(); | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|   | |||||||
| @@ -188,11 +188,11 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void mcf5208evb_init(QEMUMachineInitArgs *args) | static void mcf5208evb_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     M68kCPU *cpu; |     M68kCPU *cpu; | ||||||
|     CPUM68KState *env; |     CPUM68KState *env; | ||||||
|     int kernel_size; |     int kernel_size; | ||||||
|   | |||||||
| @@ -79,9 +79,9 @@ static void machine_cpu_reset(MicroBlazeCPU *cpu) | |||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| petalogix_ml605_init(QEMUMachineInitArgs *args) | petalogix_ml605_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     DeviceState *dev, *dma, *eth0; |     DeviceState *dev, *dma, *eth0; | ||||||
|     Object *ds, *cs; |     Object *ds, *cs; | ||||||
| @@ -196,13 +196,13 @@ petalogix_ml605_init(QEMUMachineInitArgs *args) | |||||||
|             qemu_irq cs_line; |             qemu_irq cs_line; | ||||||
|  |  | ||||||
|             dev = ssi_create_slave(spi, "n25q128"); |             dev = ssi_create_slave(spi, "n25q128"); | ||||||
|             cs_line = qdev_get_gpio_in(dev, 0); |             cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0); | ||||||
|             sysbus_connect_irq(busdev, i+1, cs_line); |             sysbus_connect_irq(busdev, i+1, cs_line); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     microblaze_load_kernel(cpu, ddr_base, ram_size, |     microblaze_load_kernel(cpu, ddr_base, ram_size, | ||||||
|                            args->initrd_filename, |                            machine->initrd_filename, | ||||||
|                            BINARY_DEVICE_TREE_FILE, |                            BINARY_DEVICE_TREE_FILE, | ||||||
|                            machine_cpu_reset); |                            machine_cpu_reset); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -59,10 +59,10 @@ static void machine_cpu_reset(MicroBlazeCPU *cpu) | |||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| petalogix_s3adsp1800_init(QEMUMachineInitArgs *args) | petalogix_s3adsp1800_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     DeviceState *dev; |     DeviceState *dev; | ||||||
|     MicroBlazeCPU *cpu; |     MicroBlazeCPU *cpu; | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
| @@ -128,7 +128,7 @@ petalogix_s3adsp1800_init(QEMUMachineInitArgs *args) | |||||||
|     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[ETHLITE_IRQ]); |     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[ETHLITE_IRQ]); | ||||||
|  |  | ||||||
|     microblaze_load_kernel(cpu, ddr_base, ram_size, |     microblaze_load_kernel(cpu, ddr_base, ram_size, | ||||||
|                            args->initrd_filename, |                            machine->initrd_filename, | ||||||
|                            BINARY_DEVICE_TREE_FILE, |                            BINARY_DEVICE_TREE_FILE, | ||||||
|                            machine_cpu_reset); |                            machine_cpu_reset); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -259,13 +259,13 @@ static void cpu_request_exit(void *opaque, int irq, int level) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void mips_fulong2e_init(QEMUMachineInitArgs *args) | static void mips_fulong2e_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     char *filename; |     char *filename; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|   | |||||||
| @@ -329,19 +329,19 @@ static void mips_jazz_init(MemoryRegion *address_space, | |||||||
| } | } | ||||||
|  |  | ||||||
| static | static | ||||||
| void mips_magnum_init(QEMUMachineInitArgs *args) | void mips_magnum_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|         mips_jazz_init(get_system_memory(), get_system_io(), |         mips_jazz_init(get_system_memory(), get_system_io(), | ||||||
|                        ram_size, cpu_model, JAZZ_MAGNUM); |                        ram_size, cpu_model, JAZZ_MAGNUM); | ||||||
| } | } | ||||||
|  |  | ||||||
| static | static | ||||||
| void mips_pica61_init(QEMUMachineInitArgs *args) | void mips_pica61_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     mips_jazz_init(get_system_memory(), get_system_io(), |     mips_jazz_init(get_system_memory(), get_system_io(), | ||||||
|                    ram_size, cpu_model, JAZZ_PICA61); |                    ram_size, cpu_model, JAZZ_PICA61); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -875,13 +875,13 @@ static void cpu_request_exit(void *opaque, int irq, int level) | |||||||
| } | } | ||||||
|  |  | ||||||
| static | static | ||||||
| void mips_malta_init(QEMUMachineInitArgs *args) | void mips_malta_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     char *filename; |     char *filename; | ||||||
|     pflash_t *fl; |     pflash_t *fl; | ||||||
|     MemoryRegion *system_memory = get_system_memory(); |     MemoryRegion *system_memory = get_system_memory(); | ||||||
|   | |||||||
| @@ -133,13 +133,13 @@ static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd) | |||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| mips_mipssim_init(QEMUMachineInitArgs *args) | mips_mipssim_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     char *filename; |     char *filename; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *isa = g_new(MemoryRegion, 1); |     MemoryRegion *isa = g_new(MemoryRegion, 1); | ||||||
|   | |||||||
| @@ -153,13 +153,13 @@ static void main_cpu_reset(void *opaque) | |||||||
|  |  | ||||||
| static const int sector_len = 32 * 1024; | static const int sector_len = 32 * 1024; | ||||||
| static | static | ||||||
| void mips_r4k_init(QEMUMachineInitArgs *args) | void mips_r4k_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     char *filename; |     char *filename; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|   | |||||||
| @@ -29,7 +29,6 @@ obj-$(CONFIG_NSERIES) += cbus.o | |||||||
| obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o | obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o | ||||||
| obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o | obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o | ||||||
| obj-$(CONFIG_IMX) += imx_ccm.o | obj-$(CONFIG_IMX) += imx_ccm.o | ||||||
| obj-$(CONFIG_LM32) += lm32_sys.o |  | ||||||
| obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o | obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o | ||||||
| obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o | obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o | ||||||
| obj-$(CONFIG_MAINSTONE) += mst_fpga.o | obj-$(CONFIG_MAINSTONE) += mst_fpga.o | ||||||
|   | |||||||
| @@ -1,179 +0,0 @@ | |||||||
| /* |  | ||||||
|  *  QEMU model of the LatticeMico32 system control block. |  | ||||||
|  * |  | ||||||
|  *  Copyright (c) 2010 Michael Walle <michael@walle.cc> |  | ||||||
|  * |  | ||||||
|  * This library is free software; you can redistribute it and/or |  | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  | ||||||
|  * License as published by the Free Software Foundation; either |  | ||||||
|  * version 2 of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This library is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU |  | ||||||
|  * Lesser General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU Lesser General Public |  | ||||||
|  * License along with this library; if not, see <http://www.gnu.org/licenses/>. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * This model is mainly intended for testing purposes and doesn't fit to any |  | ||||||
|  * real hardware. On the one hand it provides a control register (R_CTRL) on |  | ||||||
|  * the other hand it supports the lm32 tests. |  | ||||||
|  * |  | ||||||
|  * A write to the control register causes a system shutdown. |  | ||||||
|  * Tests first write the pointer to a test name to the test name register |  | ||||||
|  * (R_TESTNAME) and then write a zero to the pass/fail register (R_PASSFAIL) if |  | ||||||
|  * the test is passed or any non-zero value to it if the test is failed. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "hw/hw.h" |  | ||||||
| #include "hw/sysbus.h" |  | ||||||
| #include "trace.h" |  | ||||||
| #include "qemu/log.h" |  | ||||||
| #include "qemu/error-report.h" |  | ||||||
| #include "sysemu/sysemu.h" |  | ||||||
|  |  | ||||||
| enum { |  | ||||||
|     R_CTRL = 0, |  | ||||||
|     R_PASSFAIL, |  | ||||||
|     R_TESTNAME, |  | ||||||
|     R_MAX |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| #define MAX_TESTNAME_LEN 32 |  | ||||||
|  |  | ||||||
| #define TYPE_LM32_SYS "lm32-sys" |  | ||||||
| #define LM32_SYS(obj) OBJECT_CHECK(LM32SysState, (obj), TYPE_LM32_SYS) |  | ||||||
|  |  | ||||||
| struct LM32SysState { |  | ||||||
|     SysBusDevice parent_obj; |  | ||||||
|  |  | ||||||
|     MemoryRegion iomem; |  | ||||||
|     uint32_t base; |  | ||||||
|     uint32_t regs[R_MAX]; |  | ||||||
|     uint8_t testname[MAX_TESTNAME_LEN]; |  | ||||||
| }; |  | ||||||
| typedef struct LM32SysState LM32SysState; |  | ||||||
|  |  | ||||||
| static void copy_testname(LM32SysState *s) |  | ||||||
| { |  | ||||||
|     cpu_physical_memory_read(s->regs[R_TESTNAME], s->testname, |  | ||||||
|             MAX_TESTNAME_LEN); |  | ||||||
|     s->testname[MAX_TESTNAME_LEN - 1] = '\0'; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void sys_write(void *opaque, hwaddr addr, |  | ||||||
|                       uint64_t value, unsigned size) |  | ||||||
| { |  | ||||||
|     LM32SysState *s = opaque; |  | ||||||
|     char *testname; |  | ||||||
|  |  | ||||||
|     trace_lm32_sys_memory_write(addr, value); |  | ||||||
|  |  | ||||||
|     addr >>= 2; |  | ||||||
|     switch (addr) { |  | ||||||
|     case R_CTRL: |  | ||||||
|         qemu_system_shutdown_request(); |  | ||||||
|         break; |  | ||||||
|     case R_PASSFAIL: |  | ||||||
|         s->regs[addr] = value; |  | ||||||
|         testname = (char *)s->testname; |  | ||||||
|         fprintf(stderr, "TC  %-*s %s\n", MAX_TESTNAME_LEN, |  | ||||||
|                 testname, (value) ? "FAILED" : "OK"); |  | ||||||
|         if (value) { |  | ||||||
|             cpu_dump_state(qemu_get_cpu(0), stderr, fprintf, 0); |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case R_TESTNAME: |  | ||||||
|         s->regs[addr] = value; |  | ||||||
|         copy_testname(s); |  | ||||||
|         break; |  | ||||||
|  |  | ||||||
|     default: |  | ||||||
|         error_report("lm32_sys: write access to unknown register 0x" |  | ||||||
|                 TARGET_FMT_plx, addr << 2); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static bool sys_ops_accepts(void *opaque, hwaddr addr, |  | ||||||
|                             unsigned size, bool is_write) |  | ||||||
| { |  | ||||||
|     return is_write && size == 4; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static const MemoryRegionOps sys_ops = { |  | ||||||
|     .write = sys_write, |  | ||||||
|     .valid.accepts = sys_ops_accepts, |  | ||||||
|     .endianness = DEVICE_NATIVE_ENDIAN, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static void sys_reset(DeviceState *d) |  | ||||||
| { |  | ||||||
|     LM32SysState *s = LM32_SYS(d); |  | ||||||
|     int i; |  | ||||||
|  |  | ||||||
|     for (i = 0; i < R_MAX; i++) { |  | ||||||
|         s->regs[i] = 0; |  | ||||||
|     } |  | ||||||
|     memset(s->testname, 0, MAX_TESTNAME_LEN); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int lm32_sys_init(SysBusDevice *dev) |  | ||||||
| { |  | ||||||
|     LM32SysState *s = LM32_SYS(dev); |  | ||||||
|  |  | ||||||
|     memory_region_init_io(&s->iomem, OBJECT(dev), &sys_ops , s, |  | ||||||
|                           "sys", R_MAX * 4); |  | ||||||
|     sysbus_init_mmio(dev, &s->iomem); |  | ||||||
|  |  | ||||||
|     /* Note: This device is not created in the board initialization, |  | ||||||
|      * instead it has to be added with the -device parameter. Therefore, |  | ||||||
|      * the device maps itself. */ |  | ||||||
|     sysbus_mmio_map(dev, 0, s->base); |  | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static const VMStateDescription vmstate_lm32_sys = { |  | ||||||
|     .name = "lm32-sys", |  | ||||||
|     .version_id = 1, |  | ||||||
|     .minimum_version_id = 1, |  | ||||||
|     .fields = (VMStateField[]) { |  | ||||||
|         VMSTATE_UINT32_ARRAY(regs, LM32SysState, R_MAX), |  | ||||||
|         VMSTATE_BUFFER(testname, LM32SysState), |  | ||||||
|         VMSTATE_END_OF_LIST() |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static Property lm32_sys_properties[] = { |  | ||||||
|     DEFINE_PROP_UINT32("base", LM32SysState, base, 0xffff0000), |  | ||||||
|     DEFINE_PROP_END_OF_LIST(), |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static void lm32_sys_class_init(ObjectClass *klass, void *data) |  | ||||||
| { |  | ||||||
|     DeviceClass *dc = DEVICE_CLASS(klass); |  | ||||||
|     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); |  | ||||||
|  |  | ||||||
|     k->init = lm32_sys_init; |  | ||||||
|     dc->reset = sys_reset; |  | ||||||
|     dc->vmsd = &vmstate_lm32_sys; |  | ||||||
|     dc->props = lm32_sys_properties; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static const TypeInfo lm32_sys_info = { |  | ||||||
|     .name          = TYPE_LM32_SYS, |  | ||||||
|     .parent        = TYPE_SYS_BUS_DEVICE, |  | ||||||
|     .instance_size = sizeof(LM32SysState), |  | ||||||
|     .class_init    = lm32_sys_class_init, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static void lm32_sys_register_types(void) |  | ||||||
| { |  | ||||||
|     type_register_static(&lm32_sys_info); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type_init(lm32_sys_register_types) |  | ||||||
| @@ -107,14 +107,14 @@ moxie_intc_create(hwaddr base, qemu_irq irq, int kind_of_intr) | |||||||
|     return dev; |     return dev; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void moxiesim_init(QEMUMachineInitArgs *args) | static void moxiesim_init(MachineState *machine) | ||||||
| { | { | ||||||
|     MoxieCPU *cpu = NULL; |     MoxieCPU *cpu = NULL; | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     CPUMoxieState *env; |     CPUMoxieState *env; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * QEMU Xilinx GEM emulation |  * QEMU Cadence GEM emulation | ||||||
|  * |  * | ||||||
|  * Copyright (c) 2011 Xilinx, Inc. |  * Copyright (c) 2011 Xilinx, Inc. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -90,11 +90,11 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size, | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void openrisc_sim_init(QEMUMachineInitArgs *args) | static void openrisc_sim_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     OpenRISCCPU *cpu = NULL; |     OpenRISCCPU *cpu = NULL; | ||||||
|     MemoryRegion *ram; |     MemoryRegion *ram; | ||||||
|     int n; |     int n; | ||||||
|   | |||||||
| @@ -605,13 +605,13 @@ PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr) | |||||||
|     int dom, bus; |     int dom, bus; | ||||||
|     unsigned slot; |     unsigned slot; | ||||||
|  |  | ||||||
|     assert(!root->parent_dev); |  | ||||||
|  |  | ||||||
|     if (!root) { |     if (!root) { | ||||||
|         fprintf(stderr, "No primary PCI bus\n"); |         fprintf(stderr, "No primary PCI bus\n"); | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     assert(!root->parent_dev); | ||||||
|  |  | ||||||
|     if (!devaddr) { |     if (!devaddr) { | ||||||
|         *devfnp = -1; |         *devfnp = -1; | ||||||
|         return pci_find_bus_nr(root, 0); |         return pci_find_bus_nr(root, 0); | ||||||
|   | |||||||
| @@ -123,7 +123,7 @@ static void dt_serial_create(void *fdt, unsigned long long offset, | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static int ppce500_load_device_tree(QEMUMachineInitArgs *args, | static int ppce500_load_device_tree(MachineState *machine, | ||||||
|                                     PPCE500Params *params, |                                     PPCE500Params *params, | ||||||
|                                     hwaddr addr, |                                     hwaddr addr, | ||||||
|                                     hwaddr initrd_base, |                                     hwaddr initrd_base, | ||||||
| @@ -132,7 +132,7 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args, | |||||||
| { | { | ||||||
|     CPUPPCState *env = first_cpu->env_ptr; |     CPUPPCState *env = first_cpu->env_ptr; | ||||||
|     int ret = -1; |     int ret = -1; | ||||||
|     uint64_t mem_reg_property[] = { 0, cpu_to_be64(args->ram_size) }; |     uint64_t mem_reg_property[] = { 0, cpu_to_be64(machine->ram_size) }; | ||||||
|     int fdt_size; |     int fdt_size; | ||||||
|     void *fdt; |     void *fdt; | ||||||
|     uint8_t hypercall[16]; |     uint8_t hypercall[16]; | ||||||
| @@ -207,7 +207,7 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", |     ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", | ||||||
|                                       args->kernel_cmdline); |                                       machine->kernel_cmdline); | ||||||
|     if (ret < 0) |     if (ret < 0) | ||||||
|         fprintf(stderr, "couldn't set /chosen/bootargs\n"); |         fprintf(stderr, "couldn't set /chosen/bootargs\n"); | ||||||
|  |  | ||||||
| @@ -387,7 +387,7 @@ out: | |||||||
| } | } | ||||||
|  |  | ||||||
| typedef struct DeviceTreeParams { | typedef struct DeviceTreeParams { | ||||||
|     QEMUMachineInitArgs args; |     MachineState *machine; | ||||||
|     PPCE500Params params; |     PPCE500Params params; | ||||||
|     hwaddr addr; |     hwaddr addr; | ||||||
|     hwaddr initrd_base; |     hwaddr initrd_base; | ||||||
| @@ -397,18 +397,18 @@ typedef struct DeviceTreeParams { | |||||||
| static void ppce500_reset_device_tree(void *opaque) | static void ppce500_reset_device_tree(void *opaque) | ||||||
| { | { | ||||||
|     DeviceTreeParams *p = opaque; |     DeviceTreeParams *p = opaque; | ||||||
|     ppce500_load_device_tree(&p->args, &p->params, p->addr, p->initrd_base, |     ppce500_load_device_tree(p->machine, &p->params, p->addr, p->initrd_base, | ||||||
|                              p->initrd_size, false); |                              p->initrd_size, false); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int ppce500_prep_device_tree(QEMUMachineInitArgs *args, | static int ppce500_prep_device_tree(MachineState *machine, | ||||||
|                                     PPCE500Params *params, |                                     PPCE500Params *params, | ||||||
|                                     hwaddr addr, |                                     hwaddr addr, | ||||||
|                                     hwaddr initrd_base, |                                     hwaddr initrd_base, | ||||||
|                                     hwaddr initrd_size) |                                     hwaddr initrd_size) | ||||||
| { | { | ||||||
|     DeviceTreeParams *p = g_new(DeviceTreeParams, 1); |     DeviceTreeParams *p = g_new(DeviceTreeParams, 1); | ||||||
|     p->args = *args; |     p->machine = machine; | ||||||
|     p->params = *params; |     p->params = *params; | ||||||
|     p->addr = addr; |     p->addr = addr; | ||||||
|     p->initrd_base = initrd_base; |     p->initrd_base = initrd_base; | ||||||
| @@ -417,7 +417,7 @@ static int ppce500_prep_device_tree(QEMUMachineInitArgs *args, | |||||||
|     qemu_register_reset(ppce500_reset_device_tree, p); |     qemu_register_reset(ppce500_reset_device_tree, p); | ||||||
|  |  | ||||||
|     /* Issue the device tree loader once, so that we get the size of the blob */ |     /* Issue the device tree loader once, so that we get the size of the blob */ | ||||||
|     return ppce500_load_device_tree(args, params, addr, initrd_base, |     return ppce500_load_device_tree(machine, params, addr, initrd_base, | ||||||
|                                     initrd_size, true); |                                     initrd_size, true); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -597,7 +597,7 @@ static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, | |||||||
|     return mpic; |     return mpic; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) | void ppce500_init(MachineState *machine, PPCE500Params *params) | ||||||
| { | { | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
| @@ -622,8 +622,8 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) | |||||||
|     PPCE500CCSRState *ccsr; |     PPCE500CCSRState *ccsr; | ||||||
|  |  | ||||||
|     /* Setup CPUs */ |     /* Setup CPUs */ | ||||||
|     if (args->cpu_model == NULL) { |     if (machine->cpu_model == NULL) { | ||||||
|         args->cpu_model = "e500v2_v30"; |         machine->cpu_model = "e500v2_v30"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); |     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); | ||||||
| @@ -633,7 +633,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) | |||||||
|         CPUState *cs; |         CPUState *cs; | ||||||
|         qemu_irq *input; |         qemu_irq *input; | ||||||
|  |  | ||||||
|         cpu = cpu_ppc_init(args->cpu_model); |         cpu = cpu_ppc_init(machine->cpu_model); | ||||||
|         if (cpu == NULL) { |         if (cpu == NULL) { | ||||||
|             fprintf(stderr, "Unable to initialize CPU!\n"); |             fprintf(stderr, "Unable to initialize CPU!\n"); | ||||||
|             exit(1); |             exit(1); | ||||||
| @@ -672,7 +672,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) | |||||||
|  |  | ||||||
|     /* Fixup Memory size on a alignment boundary */ |     /* Fixup Memory size on a alignment boundary */ | ||||||
|     ram_size &= ~(RAM_SIZES_ALIGN - 1); |     ram_size &= ~(RAM_SIZES_ALIGN - 1); | ||||||
|     args->ram_size = ram_size; |     machine->ram_size = ram_size; | ||||||
|  |  | ||||||
|     /* Register Memory */ |     /* Register Memory */ | ||||||
|     memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size); |     memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size); | ||||||
| @@ -739,11 +739,11 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) | |||||||
|     sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); |     sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); | ||||||
|  |  | ||||||
|     /* Load kernel. */ |     /* Load kernel. */ | ||||||
|     if (args->kernel_filename) { |     if (machine->kernel_filename) { | ||||||
|         kernel_size = load_uimage(args->kernel_filename, &entry, |         kernel_size = load_uimage(machine->kernel_filename, &entry, | ||||||
|                                   &loadaddr, NULL); |                                   &loadaddr, NULL); | ||||||
|         if (kernel_size < 0) { |         if (kernel_size < 0) { | ||||||
|             kernel_size = load_elf(args->kernel_filename, NULL, NULL, |             kernel_size = load_elf(machine->kernel_filename, NULL, NULL, | ||||||
|                                    &elf_entry, &elf_lowaddr, NULL, 1, |                                    &elf_entry, &elf_lowaddr, NULL, 1, | ||||||
|                                    ELF_MACHINE, 0); |                                    ELF_MACHINE, 0); | ||||||
|             entry = elf_entry; |             entry = elf_entry; | ||||||
| @@ -752,7 +752,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) | |||||||
|         /* XXX try again as binary */ |         /* XXX try again as binary */ | ||||||
|         if (kernel_size < 0) { |         if (kernel_size < 0) { | ||||||
|             fprintf(stderr, "qemu: could not load kernel '%s'\n", |             fprintf(stderr, "qemu: could not load kernel '%s'\n", | ||||||
|                     args->kernel_filename); |                     machine->kernel_filename); | ||||||
|             exit(1); |             exit(1); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -764,14 +764,14 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Load initrd. */ |     /* Load initrd. */ | ||||||
|     if (args->initrd_filename) { |     if (machine->initrd_filename) { | ||||||
|         initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; |         initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; | ||||||
|         initrd_size = load_image_targphys(args->initrd_filename, initrd_base, |         initrd_size = load_image_targphys(machine->initrd_filename, initrd_base, | ||||||
|                                           ram_size - initrd_base); |                                           ram_size - initrd_base); | ||||||
|  |  | ||||||
|         if (initrd_size < 0) { |         if (initrd_size < 0) { | ||||||
|             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", |             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", | ||||||
|                     args->initrd_filename); |                     machine->initrd_filename); | ||||||
|             exit(1); |             exit(1); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -779,11 +779,11 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* If we're loading a kernel directly, we must load the device tree too. */ |     /* If we're loading a kernel directly, we must load the device tree too. */ | ||||||
|     if (args->kernel_filename) { |     if (machine->kernel_filename) { | ||||||
|         struct boot_info *boot_info; |         struct boot_info *boot_info; | ||||||
|         int dt_size; |         int dt_size; | ||||||
|  |  | ||||||
|         dt_size = ppce500_prep_device_tree(args, params, dt_base, |         dt_size = ppce500_prep_device_tree(machine, params, dt_base, | ||||||
|                                            initrd_base, initrd_size); |                                            initrd_base, initrd_size); | ||||||
|         if (dt_size < 0) { |         if (dt_size < 0) { | ||||||
|             fprintf(stderr, "couldn't load device tree\n"); |             fprintf(stderr, "couldn't load device tree\n"); | ||||||
|   | |||||||
| @@ -13,6 +13,6 @@ typedef struct PPCE500Params { | |||||||
|     int mpic_version; |     int mpic_version; | ||||||
| } PPCE500Params; | } PPCE500Params; | ||||||
|  |  | ||||||
| void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params); | void ppce500_init(MachineState *machine, PPCE500Params *params); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) | |||||||
|                      sizeof(compatible)); |                      sizeof(compatible)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void e500plat_init(QEMUMachineInitArgs *args) | static void e500plat_init(MachineState *machine) | ||||||
| { | { | ||||||
|     PPCE500Params params = { |     PPCE500Params params = { | ||||||
|         .pci_first_slot = 0x1, |         .pci_first_slot = 0x1, | ||||||
| @@ -43,7 +43,7 @@ static void e500plat_init(QEMUMachineInitArgs *args) | |||||||
|         params.mpic_version = OPENPIC_MODEL_FSL_MPIC_20; |         params.mpic_version = OPENPIC_MODEL_FSL_MPIC_20; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ppce500_init(args, ¶ms); |     ppce500_init(machine, ¶ms); | ||||||
| } | } | ||||||
|  |  | ||||||
| static QEMUMachine e500plat_machine = { | static QEMUMachine e500plat_machine = { | ||||||
|   | |||||||
| @@ -140,14 +140,14 @@ static void ppc_core99_reset(void *opaque) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* PowerPC Mac99 hardware initialisation */ | /* PowerPC Mac99 hardware initialisation */ | ||||||
| static void ppc_core99_init(QEMUMachineInitArgs *args) | static void ppc_core99_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     const char *boot_device = args->boot_order; |     const char *boot_device = machine->boot_order; | ||||||
|     PowerPCCPU *cpu = NULL; |     PowerPCCPU *cpu = NULL; | ||||||
|     CPUPPCState *env = NULL; |     CPUPPCState *env = NULL; | ||||||
|     char *filename; |     char *filename; | ||||||
|   | |||||||
| @@ -71,14 +71,14 @@ static void ppc_heathrow_reset(void *opaque) | |||||||
|     cpu_reset(CPU(cpu)); |     cpu_reset(CPU(cpu)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ppc_heathrow_init(QEMUMachineInitArgs *args) | static void ppc_heathrow_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     const char *boot_device = args->boot_order; |     const char *boot_device = machine->boot_order; | ||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
|     PowerPCCPU *cpu = NULL; |     PowerPCCPU *cpu = NULL; | ||||||
|     CPUPPCState *env = NULL; |     CPUPPCState *env = NULL; | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt) | |||||||
|                      sizeof(compatible)); |                      sizeof(compatible)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void mpc8544ds_init(QEMUMachineInitArgs *args) | static void mpc8544ds_init(MachineState *machine) | ||||||
| { | { | ||||||
|     PPCE500Params params = { |     PPCE500Params params = { | ||||||
|         .pci_first_slot = 0x11, |         .pci_first_slot = 0x11, | ||||||
| @@ -35,7 +35,7 @@ static void mpc8544ds_init(QEMUMachineInitArgs *args) | |||||||
|         .mpic_version = OPENPIC_MODEL_FSL_MPIC_20, |         .mpic_version = OPENPIC_MODEL_FSL_MPIC_20, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     ppce500_init(args, ¶ms); |     ppce500_init(machine, ¶ms); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -172,12 +172,12 @@ static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) | |||||||
|     qemu_register_reset(&ref405ep_fpga_reset, fpga); |     qemu_register_reset(&ref405ep_fpga_reset, fpga); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ref405ep_init(QEMUMachineInitArgs *args) | static void ref405ep_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     char *filename; |     char *filename; | ||||||
|     ppc4xx_bd_info_t bd; |     ppc4xx_bd_info_t bd; | ||||||
|     CPUPPCState *env; |     CPUPPCState *env; | ||||||
| @@ -499,11 +499,11 @@ static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) | |||||||
|     qemu_register_reset(&taihu_cpld_reset, cpld); |     qemu_register_reset(&taihu_cpld_reset, cpld); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void taihu_405ep_init(QEMUMachineInitArgs *args) | static void taihu_405ep_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     char *filename; |     char *filename; | ||||||
|     qemu_irq *pic; |     qemu_irq *pic; | ||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
|   | |||||||
| @@ -156,13 +156,13 @@ static void main_cpu_reset(void *opaque) | |||||||
|     mmubooke_create_initial_mapping(env, 0, 0); |     mmubooke_create_initial_mapping(env, 0, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void bamboo_init(QEMUMachineInitArgs *args) | static void bamboo_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 }; |     unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 }; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
|     MemoryRegion *isa = g_new(MemoryRegion, 1); |     MemoryRegion *isa = g_new(MemoryRegion, 1); | ||||||
|   | |||||||
| @@ -364,14 +364,14 @@ static const MemoryRegionPortio prep_portio_list[] = { | |||||||
| static PortioList prep_port_list; | static PortioList prep_port_list; | ||||||
|  |  | ||||||
| /* PowerPC PREP hardware initialisation */ | /* PowerPC PREP hardware initialisation */ | ||||||
| static void ppc_prep_init(QEMUMachineInitArgs *args) | static void ppc_prep_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     const char *boot_device = args->boot_order; |     const char *boot_device = machine->boot_order; | ||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
|     PowerPCCPU *cpu = NULL; |     PowerPCCPU *cpu = NULL; | ||||||
|     CPUPPCState *env = NULL; |     CPUPPCState *env = NULL; | ||||||
|   | |||||||
| @@ -1140,14 +1140,14 @@ static SaveVMHandlers savevm_htab_handlers = { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| /* pSeries LPAR / sPAPR hardware init */ | /* pSeries LPAR / sPAPR hardware init */ | ||||||
| static void ppc_spapr_init(QEMUMachineInitArgs *args) | static void ppc_spapr_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     const char *initrd_filename = args->initrd_filename; |     const char *initrd_filename = machine->initrd_filename; | ||||||
|     const char *boot_device = args->boot_order; |     const char *boot_device = machine->boot_order; | ||||||
|     PowerPCCPU *cpu; |     PowerPCCPU *cpu; | ||||||
|     CPUPPCState *env; |     CPUPPCState *env; | ||||||
|     PCIHostState *phb; |     PCIHostState *phb; | ||||||
|   | |||||||
| @@ -194,12 +194,12 @@ static int xilinx_load_device_tree(hwaddr addr, | |||||||
|     return fdt_size; |     return fdt_size; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void virtex_init(QEMUMachineInitArgs *args) | static void virtex_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t ram_size = args->ram_size; |     ram_addr_t ram_size = machine->ram_size; | ||||||
|     const char *cpu_model = args->cpu_model; |     const char *cpu_model = machine->cpu_model; | ||||||
|     const char *kernel_filename = args->kernel_filename; |     const char *kernel_filename = machine->kernel_filename; | ||||||
|     const char *kernel_cmdline = args->kernel_cmdline; |     const char *kernel_cmdline = machine->kernel_cmdline; | ||||||
|     hwaddr initrd_base = 0; |     hwaddr initrd_base = 0; | ||||||
|     int initrd_size = 0; |     int initrd_size = 0; | ||||||
|     MemoryRegion *address_space_mem = get_system_memory(); |     MemoryRegion *address_space_mem = get_system_memory(); | ||||||
| @@ -275,14 +275,14 @@ static void virtex_init(QEMUMachineInitArgs *args) | |||||||
|         boot_info.ima_size = kernel_size; |         boot_info.ima_size = kernel_size; | ||||||
|  |  | ||||||
|         /* Load initrd. */ |         /* Load initrd. */ | ||||||
|         if (args->initrd_filename) { |         if (machine->initrd_filename) { | ||||||
|             initrd_base = high = ROUND_UP(high, 4); |             initrd_base = high = ROUND_UP(high, 4); | ||||||
|             initrd_size = load_image_targphys(args->initrd_filename, |             initrd_size = load_image_targphys(machine->initrd_filename, | ||||||
|                                               high, ram_size - high); |                                               high, ram_size - high); | ||||||
|  |  | ||||||
|             if (initrd_size < 0) { |             if (initrd_size < 0) { | ||||||
|                 error_report("couldn't load ram disk '%s'", |                 error_report("couldn't load ram disk '%s'", | ||||||
|                              args->initrd_filename); |                              machine->initrd_filename); | ||||||
|                 exit(1); |                 exit(1); | ||||||
|             } |             } | ||||||
|             high = ROUND_UP(high + initrd_size, 4); |             high = ROUND_UP(high + initrd_size, 4); | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ | |||||||
| #include "ioinst.h" | #include "ioinst.h" | ||||||
| #include "css.h" | #include "css.h" | ||||||
| #include "trace.h" | #include "trace.h" | ||||||
|  | #include "hw/s390x/s390_flic.h" | ||||||
|  |  | ||||||
| typedef struct CrwContainer { | typedef struct CrwContainer { | ||||||
|     CRW crw; |     CRW crw; | ||||||
| @@ -39,6 +40,13 @@ typedef struct CssImage { | |||||||
|     ChpInfo chpids[MAX_CHPID + 1]; |     ChpInfo chpids[MAX_CHPID + 1]; | ||||||
| } CssImage; | } CssImage; | ||||||
|  |  | ||||||
|  | typedef struct IoAdapter { | ||||||
|  |     uint32_t id; | ||||||
|  |     uint8_t type; | ||||||
|  |     uint8_t isc; | ||||||
|  |     QTAILQ_ENTRY(IoAdapter) sibling; | ||||||
|  | } IoAdapter; | ||||||
|  |  | ||||||
| typedef struct ChannelSubSys { | typedef struct ChannelSubSys { | ||||||
|     QTAILQ_HEAD(, CrwContainer) pending_crws; |     QTAILQ_HEAD(, CrwContainer) pending_crws; | ||||||
|     bool do_crw_mchk; |     bool do_crw_mchk; | ||||||
| @@ -49,6 +57,7 @@ typedef struct ChannelSubSys { | |||||||
|     uint64_t chnmon_area; |     uint64_t chnmon_area; | ||||||
|     CssImage *css[MAX_CSSID + 1]; |     CssImage *css[MAX_CSSID + 1]; | ||||||
|     uint8_t default_cssid; |     uint8_t default_cssid; | ||||||
|  |     QTAILQ_HEAD(, IoAdapter) io_adapters; | ||||||
| } ChannelSubSys; | } ChannelSubSys; | ||||||
|  |  | ||||||
| static ChannelSubSys *channel_subsys; | static ChannelSubSys *channel_subsys; | ||||||
| @@ -69,6 +78,46 @@ int css_create_css_image(uint8_t cssid, bool default_image) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap, | ||||||
|  |                             bool maskable, uint32_t *id) | ||||||
|  | { | ||||||
|  |     IoAdapter *adapter; | ||||||
|  |     bool found = false; | ||||||
|  |     int ret; | ||||||
|  |     S390FLICState *fs = s390_get_flic(); | ||||||
|  |     S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); | ||||||
|  |  | ||||||
|  |     *id = 0; | ||||||
|  |     QTAILQ_FOREACH(adapter, &channel_subsys->io_adapters, sibling) { | ||||||
|  |         if ((adapter->type == type) && (adapter->isc == isc)) { | ||||||
|  |             *id = adapter->id; | ||||||
|  |             found = true; | ||||||
|  |             ret = 0; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if (adapter->id >= *id) { | ||||||
|  |             *id = adapter->id + 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (found) { | ||||||
|  |         goto out; | ||||||
|  |     } | ||||||
|  |     adapter = g_new0(IoAdapter, 1); | ||||||
|  |     ret = fsc->register_io_adapter(fs, *id, isc, swap, maskable); | ||||||
|  |     if (ret == 0) { | ||||||
|  |         adapter->id = *id; | ||||||
|  |         adapter->isc = isc; | ||||||
|  |         adapter->type = type; | ||||||
|  |         QTAILQ_INSERT_TAIL(&channel_subsys->io_adapters, adapter, sibling); | ||||||
|  |     } else { | ||||||
|  |         g_free(adapter); | ||||||
|  |         fprintf(stderr, "Unexpected error %d when registering adapter %d\n", | ||||||
|  |                 ret, *id); | ||||||
|  |     } | ||||||
|  | out: | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
| uint16_t css_build_subchannel_id(SubchDev *sch) | uint16_t css_build_subchannel_id(SubchDev *sch) | ||||||
| { | { | ||||||
|     if (channel_subsys->max_cssid > 0) { |     if (channel_subsys->max_cssid > 0) { | ||||||
| @@ -1235,6 +1284,7 @@ static void css_init(void) | |||||||
|     channel_subsys->do_crw_mchk = true; |     channel_subsys->do_crw_mchk = true; | ||||||
|     channel_subsys->crws_lost = false; |     channel_subsys->crws_lost = false; | ||||||
|     channel_subsys->chnmon_active = false; |     channel_subsys->chnmon_active = false; | ||||||
|  |     QTAILQ_INIT(&channel_subsys->io_adapters); | ||||||
| } | } | ||||||
| machine_init(css_init); | machine_init(css_init); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -98,4 +98,8 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, | |||||||
|                            int hotplugged, int add); |                            int hotplugged, int add); | ||||||
| void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); | void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); | ||||||
| void css_adapter_interrupt(uint8_t isc); | void css_adapter_interrupt(uint8_t isc); | ||||||
|  |  | ||||||
|  | #define CSS_IO_ADAPTER_VIRTIO 1 | ||||||
|  | int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap, | ||||||
|  |                             bool maskable, uint32_t *id); | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -79,9 +79,9 @@ static void virtio_ccw_register_hcalls(void) | |||||||
|                                    virtio_ccw_hcall_early_printk); |                                    virtio_ccw_hcall_early_printk); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ccw_init(QEMUMachineInitArgs *args) | static void ccw_init(MachineState *machine) | ||||||
| { | { | ||||||
|     ram_addr_t my_ram_size = args->ram_size; |     ram_addr_t my_ram_size = machine->ram_size; | ||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|     int shift = 0; |     int shift = 0; | ||||||
| @@ -102,8 +102,8 @@ static void ccw_init(QEMUMachineInitArgs *args) | |||||||
|     /* get a BUS */ |     /* get a BUS */ | ||||||
|     css_bus = virtual_css_bus_init(); |     css_bus = virtual_css_bus_init(); | ||||||
|     s390_sclp_init(); |     s390_sclp_init(); | ||||||
|     s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline, |     s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, | ||||||
|                       args->initrd_filename, "s390-ccw.img"); |                       machine->initrd_filename, "s390-ccw.img"); | ||||||
|     s390_flic_init(); |     s390_flic_init(); | ||||||
|  |  | ||||||
|     /* register hypercalls */ |     /* register hypercalls */ | ||||||
| @@ -118,7 +118,7 @@ static void ccw_init(QEMUMachineInitArgs *args) | |||||||
|     storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE); |     storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE); | ||||||
|  |  | ||||||
|     /* init CPUs */ |     /* init CPUs */ | ||||||
|     s390_init_cpus(args->cpu_model, storage_keys); |     s390_init_cpus(machine->cpu_model, storage_keys); | ||||||
|  |  | ||||||
|     if (kvm_enabled()) { |     if (kvm_enabled()) { | ||||||
|         kvm_s390_enable_css_support(s390_cpu_addr2state(0)); |         kvm_s390_enable_css_support(s390_cpu_addr2state(0)); | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user