Compare commits
	
		
			218 Commits
		
	
	
		
			pull-chard
			...
			pull-gtk-3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 2bda66028b | ||
|  | 298526fe92 | ||
|  | 881249c792 | ||
|  | f4b11eee2f | ||
|  | 6fffa26244 | ||
|  | e638308097 | ||
|  | 9c749e4dbe | ||
|  | 379e21c258 | ||
|  | a00f66ab9b | ||
|  | 69df1c3c9d | ||
|  | 6d4adef48d | ||
|  | 3b163b0165 | ||
|  | f214530f56 | ||
|  | 9d5614d582 | ||
|  | 39d16d29c8 | ||
|  | cc13eead53 | ||
|  | 86c3b20a5f | ||
|  | 6d585ca559 | ||
|  | dfb3804d47 | ||
|  | 4191d0eb41 | ||
|  | 03d51428e2 | ||
|  | 582ab779c5 | ||
|  | 8678b71ce6 | ||
|  | 1fcc9ddfb3 | ||
|  | c6e929e784 | ||
|  | b3c56df769 | ||
|  | ed7a0aa8bc | ||
|  | 04ce397b33 | ||
|  | 14b155ddc4 | ||
|  | e029f29385 | ||
|  | 90f1cd9138 | ||
|  | 7d11fc7c2b | ||
|  | 096c46c0ff | ||
|  | df9351e372 | ||
|  | 50573c66eb | ||
|  | 46dea4160d | ||
|  | dc668ded10 | ||
|  | 1e8ece0db3 | ||
|  | 4a41a2d68a | ||
|  | 62e466e845 | ||
|  | c3adb58fe0 | ||
|  | aa7a6a399f | ||
|  | 2e323f03bf | ||
|  | 22956a3755 | ||
|  | 5d92c74f8a | ||
|  | b19fc63cad | ||
|  | 90c5d39cb8 | ||
|  | 01c22f2cdd | ||
|  | cb201b4872 | ||
|  | f33f991185 | ||
|  | be21c33616 | ||
|  | 8bf0975902 | ||
|  | 7effdaa321 | ||
|  | d44229c54f | ||
|  | d0b2542574 | ||
|  | 4c1410d59c | ||
|  | bbbd67f0cc | ||
|  | 2ef1f68d4f | ||
|  | 0c591eb0a9 | ||
|  | 00c8cb0a36 | ||
|  | 31b030d4ab | ||
|  | 0063ebd6ac | ||
|  | 0dd106c5f0 | ||
|  | a47dddd734 | ||
|  | d7f0a59ff0 | ||
|  | bb0e627a84 | ||
|  | baea4fae7b | ||
|  | 0ea8cb8895 | ||
|  | b3310ab338 | ||
|  | 75a34036d4 | ||
|  | d0e39c5d70 | ||
|  | 611d4f996f | ||
|  | 648f034c6c | ||
|  | 90b40a696a | ||
|  | 239c51a54f | ||
|  | 74f10515d1 | ||
|  | 3f38f309b2 | ||
|  | 5638d180d6 | ||
|  | d5a11fefef | ||
|  | f0c3c505a8 | ||
|  | ff4700b05c | ||
|  | 0429a97195 | ||
|  | 27103424c4 | ||
|  | 6f03bef0ff | ||
|  | 8cd70437f3 | ||
|  | 28ecfd7a62 | ||
|  | efee734004 | ||
|  | 99df7dce8a | ||
|  | 93afeade09 | ||
|  | 7510454e3e | ||
|  | 7372c2b926 | ||
|  | 9262685b81 | ||
|  | 1590bbcb02 | ||
|  | 247bf011f6 | ||
|  | 433ac7a968 | ||
|  | db5d39f786 | ||
|  | 94a444b295 | ||
|  | d940ee9b78 | ||
|  | 500050d1e0 | ||
|  | ef02ef5f45 | ||
|  | 8fb4f821e9 | ||
|  | 5fcca9ff3b | ||
|  | 74f54bc4ba | ||
|  | 9576de7573 | ||
|  | 285f025d2c | ||
|  | c080e30ec8 | ||
|  | 8c2e1b0093 | ||
|  | 1cf5ccbca8 | ||
|  | 62864712b3 | ||
|  | 2fad1112db | ||
|  | 2efc6be2ea | ||
|  | 33276f1b9c | ||
|  | 19d6ca16d9 | ||
|  | 70d74660e7 | ||
|  | d2810ffd34 | ||
|  | 9d111183d5 | ||
|  | 4a9a1f49c5 | ||
|  | 57fac92c2d | ||
|  | 41975b269c | ||
|  | 57ed25b1b0 | ||
|  | cc28c6aa46 | ||
|  | 18fa1c42a3 | ||
|  | d3f4984583 | ||
|  | 7af803d4f8 | ||
|  | f988388025 | ||
|  | 9562f69cfd | ||
|  | 27eb6c097c | ||
|  | d475e5acd2 | ||
|  | dc3dd0d2be | ||
|  | 88eb7c29e4 | ||
|  | 48ff269272 | ||
|  | 6e4a876b43 | ||
|  | 7d1de46448 | ||
|  | be8d853766 | ||
|  | 98563fc3ec | ||
|  | 2da61b671e | ||
|  | 11f590b1a2 | ||
|  | b5042a3622 | ||
|  | 98d39e34fe | ||
|  | 938789ea92 | ||
|  | dba2855572 | ||
|  | 3456a8d185 | ||
|  | 26d49c4675 | ||
|  | be86c53c05 | ||
|  | c8d146aecc | ||
|  | 0100f42550 | ||
|  | 295d51aa6a | ||
|  | c6ba42f6bc | ||
|  | fb0e843a11 | ||
|  | 8f3babb74d | ||
|  | 7a1a4dac94 | ||
|  | 602a3921ff | ||
|  | f8762027a3 | ||
|  | d2f69df746 | ||
|  | 5c21ce77d7 | ||
|  | 02e7f85dac | ||
|  | 04e9a20b49 | ||
|  | 2ef66625f3 | ||
|  | 0399a3819b | ||
|  | 6e8114a065 | ||
|  | aa97405e32 | ||
|  | 26c9a015ef | ||
|  | b6f46f02f4 | ||
|  | 02063aaa65 | ||
|  | c7a59bed62 | ||
|  | 83bb0b2ffd | ||
|  | dc06cbd286 | ||
|  | 0056ae24bc | ||
|  | 261747f176 | ||
|  | 36d20cb2b3 | ||
|  | 49649f23db | ||
|  | a3d7cbc139 | ||
|  | 1b8601b0ea | ||
|  | cdccf7d7e7 | ||
|  | 1f760d5f2b | ||
|  | 7c77b654c5 | ||
|  | 5ef4a1c304 | ||
|  | d43269dddc | ||
|  | 1a7d9ee6dd | ||
|  | a01aedc8d3 | ||
|  | 7b0309490c | ||
|  | 267a3264cd | ||
|  | 2b81b35f8f | ||
|  | 750036a848 | ||
|  | 2f23e9ae2c | ||
|  | 21143b615a | ||
|  | fd3ece2533 | ||
|  | a822837d12 | ||
|  | 01ac27ce7f | ||
|  | 84f3fe1b07 | ||
|  | 2c3445bb85 | ||
|  | 7602e3e4a3 | ||
|  | 613c12ec28 | ||
|  | d58b912271 | ||
|  | 7f5e07d9b3 | ||
|  | dc9528fdf9 | ||
|  | 68e5ec6400 | ||
|  | 5c1e1890bf | ||
|  | c2804ee6c0 | ||
|  | 16c358e96e | ||
|  | be813ef02d | ||
|  | 2a7a1a56d1 | ||
|  | 5d371f41b4 | ||
|  | 5223070c47 | ||
|  | 59ca664ef8 | ||
|  | bceae7697f | ||
|  | b0b58195e4 | ||
|  | 6299659f54 | ||
|  | b86b05ed60 | ||
|  | 515b943a91 | ||
|  | 4b35991a3b | ||
|  | dad1fcab91 | ||
|  | 13f65b2e10 | ||
|  | b4e5a4bffd | ||
|  | 263cf4367f | ||
|  | dc65540465 | ||
|  | ac41881b48 | ||
|  | 98bc3ab0f2 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -21,6 +21,7 @@ | |||||||
| libdis* | libdis* | ||||||
| libuser | libuser | ||||||
| /linux-headers/asm | /linux-headers/asm | ||||||
|  | /qga/qapi-generated | ||||||
| /qapi-generated | /qapi-generated | ||||||
| /qapi-types.[ch] | /qapi-types.[ch] | ||||||
| /qapi-visit.[ch] | /qapi-visit.[ch] | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -13,6 +13,9 @@ | |||||||
| [submodule "roms/openbios"] | [submodule "roms/openbios"] | ||||||
| 	path = roms/openbios | 	path = roms/openbios | ||||||
| 	url = git://git.qemu-project.org/openbios.git | 	url = git://git.qemu-project.org/openbios.git | ||||||
|  | [submodule "roms/openhackware"] | ||||||
|  | 	path = roms/openhackware | ||||||
|  | 	url = git://git.qemu-project.org/openhackware.git | ||||||
| [submodule "roms/qemu-palcode"] | [submodule "roms/qemu-palcode"] | ||||||
| 	path = roms/qemu-palcode | 	path = roms/qemu-palcode | ||||||
| 	url = git://github.com/rth7680/qemu-palcode.git | 	url = git://github.com/rth7680/qemu-palcode.git | ||||||
|   | |||||||
							
								
								
									
										53
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -4,6 +4,12 @@ python: | |||||||
| compiler: | compiler: | ||||||
|   - gcc |   - gcc | ||||||
|   - clang |   - clang | ||||||
|  | notifications: | ||||||
|  |   irc: | ||||||
|  |     channels: | ||||||
|  |       - "irc.oftc.net#qemu" | ||||||
|  |     on_success: change | ||||||
|  |     on_failure: always | ||||||
| env: | env: | ||||||
|   global: |   global: | ||||||
|     - TEST_CMD="make check" |     - TEST_CMD="make check" | ||||||
| @@ -14,23 +20,23 @@ env: | |||||||
|     - GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev" |     - GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev" | ||||||
|     - EXTRA_PKGS="" |     - EXTRA_PKGS="" | ||||||
|   matrix: |   matrix: | ||||||
|   - TARGETS=alpha-softmmu,alpha-linux-user |     - TARGETS=alpha-softmmu,alpha-linux-user | ||||||
|   - TARGETS=arm-softmmu,arm-linux-user |     - TARGETS=arm-softmmu,arm-linux-user | ||||||
|   - TARGETS=aarch64-softmmu,aarch64-linux-user |     - TARGETS=aarch64-softmmu,aarch64-linux-user | ||||||
|   - TARGETS=cris-softmmu |     - TARGETS=cris-softmmu | ||||||
|   - TARGETS=i386-softmmu,x86_64-softmmu |     - TARGETS=i386-softmmu,x86_64-softmmu | ||||||
|   - TARGETS=lm32-softmmu |     - TARGETS=lm32-softmmu | ||||||
|   - TARGETS=m68k-softmmu |     - TARGETS=m68k-softmmu | ||||||
|   - TARGETS=microblaze-softmmu,microblazeel-softmmu |     - TARGETS=microblaze-softmmu,microblazeel-softmmu | ||||||
|   - TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu |     - TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu | ||||||
|   - TARGETS=moxie-softmmu |     - TARGETS=moxie-softmmu | ||||||
|   - TARGETS=or32-softmmu, |     - TARGETS=or32-softmmu, | ||||||
|   - TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu |     - TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu | ||||||
|   - TARGETS=s390x-softmmu |     - TARGETS=s390x-softmmu | ||||||
|   - TARGETS=sh4-softmmu,sh4eb-softmmu |     - TARGETS=sh4-softmmu,sh4eb-softmmu | ||||||
|   - TARGETS=sparc-softmmu,sparc64-softmmu |     - TARGETS=sparc-softmmu,sparc64-softmmu | ||||||
|   - TARGETS=unicore32-softmmu |     - TARGETS=unicore32-softmmu | ||||||
|   - TARGETS=xtensa-softmmu,xtensaeb-softmmu |     - TARGETS=xtensa-softmmu,xtensaeb-softmmu | ||||||
| before_install: | before_install: | ||||||
|   - git submodule update --init --recursive |   - git submodule update --init --recursive | ||||||
|   - sudo apt-get update -qq |   - sudo apt-get update -qq | ||||||
| @@ -46,6 +52,10 @@ matrix: | |||||||
|     - env: TARGETS=i386-softmmu,x86_64-softmmu |     - env: TARGETS=i386-softmmu,x86_64-softmmu | ||||||
|            EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter" |            EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter" | ||||||
|       compiler: gcc |       compiler: gcc | ||||||
|  |     # All the extra -dev packages | ||||||
|  |     - env: TARGETS=i386-softmmu,x86_64-softmmu | ||||||
|  |            EXTRA_PKGS="libaio-dev libcap-ng-dev libattr1-dev libbrlapi-dev uuid-dev libusb-1.0.0-dev" | ||||||
|  |       compiler: gcc | ||||||
|     # Currently configure doesn't force --disable-pie |     # Currently configure doesn't force --disable-pie | ||||||
|     - env: TARGETS=i386-softmmu,x86_64-softmmu |     - env: TARGETS=i386-softmmu,x86_64-softmmu | ||||||
|            EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie" |            EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie" | ||||||
| @@ -65,8 +75,7 @@ matrix: | |||||||
|            EXTRA_CONFIG="--enable-trace-backend=ftrace" |            EXTRA_CONFIG="--enable-trace-backend=ftrace" | ||||||
|            TEST_CMD="" |            TEST_CMD="" | ||||||
|       compiler: gcc |       compiler: gcc | ||||||
|     # This disabled make check for the ftrace backend which needs more setting up |     - env: TARGETS=i386-softmmu,x86_64-softmmu | ||||||
|     # Currently broken on 12.04 due to mis-packaged liburcu and changed API, will be pulled. |           EXTRA_PKGS="liblttng-ust-dev liburcu-dev" | ||||||
|     #- env: TARGETS=i386-softmmu,x86_64-softmmu |           EXTRA_CONFIG="--enable-trace-backend=ust" | ||||||
|     #       EXTRA_PKGS="liblttng-ust-dev liburcu-dev" |       compiler: gcc | ||||||
|     #       EXTRA_CONFIG="--enable-trace-backend=ust" |  | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
								
							| @@ -265,10 +265,7 @@ clean: | |||||||
| # avoid old build problems by removing potentially incorrect old files | # avoid old build problems by removing potentially incorrect old files | ||||||
| 	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h | 	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h | ||||||
| 	rm -f qemu-options.def | 	rm -f qemu-options.def | ||||||
| 	find . -name '*.[oda]' -type f -exec rm -f {} + | 	find . \( -name '*.l[oa]' -o -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} + | ||||||
| 	find . -name '*.l[oa]' -type f -exec rm -f {} + |  | ||||||
| 	find . -name '*$(DSOSUF)' -type f -exec rm -f {} + |  | ||||||
| 	find . -name '*.mo' -type f -exec rm -f {} + |  | ||||||
| 	rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ | 	rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ | ||||||
| 	rm -f fsdev/*.pod | 	rm -f fsdev/*.pod | ||||||
| 	rm -rf .libs */.libs | 	rm -rf .libs */.libs | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ libcacard-y += libcacard/vcardt.o | |||||||
|  |  | ||||||
| ifeq ($(CONFIG_SOFTMMU),y) | ifeq ($(CONFIG_SOFTMMU),y) | ||||||
| common-obj-y = blockdev.o blockdev-nbd.o block/ | common-obj-y = blockdev.o blockdev-nbd.o block/ | ||||||
|  | common-obj-y += iothread.o | ||||||
| common-obj-y += net/ | common-obj-y += net/ | ||||||
| common-obj-y += qdev-monitor.o device-hotplug.o | common-obj-y += qdev-monitor.o device-hotplug.o | ||||||
| common-obj-$(CONFIG_WIN32) += os-win32.o | common-obj-$(CONFIG_WIN32) += os-win32.o | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								async.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								async.c
									
									
									
									
									
								
							| @@ -214,6 +214,7 @@ aio_ctx_finalize(GSource     *source) | |||||||
|     thread_pool_free(ctx->thread_pool); |     thread_pool_free(ctx->thread_pool); | ||||||
|     aio_set_event_notifier(ctx, &ctx->notifier, NULL); |     aio_set_event_notifier(ctx, &ctx->notifier, NULL); | ||||||
|     event_notifier_cleanup(&ctx->notifier); |     event_notifier_cleanup(&ctx->notifier); | ||||||
|  |     rfifolock_destroy(&ctx->lock); | ||||||
|     qemu_mutex_destroy(&ctx->bh_lock); |     qemu_mutex_destroy(&ctx->bh_lock); | ||||||
|     g_array_free(ctx->pollfds, TRUE); |     g_array_free(ctx->pollfds, TRUE); | ||||||
|     timerlistgroup_deinit(&ctx->tlg); |     timerlistgroup_deinit(&ctx->tlg); | ||||||
| @@ -250,6 +251,12 @@ static void aio_timerlist_notify(void *opaque) | |||||||
|     aio_notify(opaque); |     aio_notify(opaque); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void aio_rfifolock_cb(void *opaque) | ||||||
|  | { | ||||||
|  |     /* Kick owner thread in case they are blocked in aio_poll() */ | ||||||
|  |     aio_notify(opaque); | ||||||
|  | } | ||||||
|  |  | ||||||
| AioContext *aio_context_new(void) | AioContext *aio_context_new(void) | ||||||
| { | { | ||||||
|     AioContext *ctx; |     AioContext *ctx; | ||||||
| @@ -257,6 +264,7 @@ AioContext *aio_context_new(void) | |||||||
|     ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD)); |     ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD)); | ||||||
|     ctx->thread_pool = NULL; |     ctx->thread_pool = NULL; | ||||||
|     qemu_mutex_init(&ctx->bh_lock); |     qemu_mutex_init(&ctx->bh_lock); | ||||||
|  |     rfifolock_init(&ctx->lock, aio_rfifolock_cb, ctx); | ||||||
|     event_notifier_init(&ctx->notifier, false); |     event_notifier_init(&ctx->notifier, false); | ||||||
|     aio_set_event_notifier(ctx, &ctx->notifier,  |     aio_set_event_notifier(ctx, &ctx->notifier,  | ||||||
|                            (EventNotifierHandler *) |                            (EventNotifierHandler *) | ||||||
| @@ -275,3 +283,13 @@ void aio_context_unref(AioContext *ctx) | |||||||
| { | { | ||||||
|     g_source_unref(&ctx->source); |     g_source_unref(&ctx->source); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void aio_context_acquire(AioContext *ctx) | ||||||
|  | { | ||||||
|  |     rfifolock_lock(&ctx->lock); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void aio_context_release(AioContext *ctx) | ||||||
|  | { | ||||||
|  |     rfifolock_unlock(&ctx->lock); | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										80
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								block.c
									
									
									
									
									
								
							| @@ -1321,7 +1321,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, | |||||||
|                           bdrv_open_flags(bs, flags | BDRV_O_UNMAP) | |                           bdrv_open_flags(bs, flags | BDRV_O_UNMAP) | | ||||||
|                           BDRV_O_PROTOCOL, true, &local_err); |                           BDRV_O_PROTOCOL, true, &local_err); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         goto fail; |         goto unlink_and_fail; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Find the right image format driver */ |     /* Find the right image format driver */ | ||||||
| @@ -1388,12 +1388,19 @@ done: | |||||||
|         ret = -EINVAL; |         ret = -EINVAL; | ||||||
|         goto close_and_fail; |         goto close_and_fail; | ||||||
|     } |     } | ||||||
|     QDECREF(options); |  | ||||||
|  |  | ||||||
|     if (!bdrv_key_required(bs)) { |     if (!bdrv_key_required(bs)) { | ||||||
|         bdrv_dev_change_media_cb(bs, true); |         bdrv_dev_change_media_cb(bs, true); | ||||||
|  |     } else if (!runstate_check(RUN_STATE_PRELAUNCH) | ||||||
|  |                && !runstate_check(RUN_STATE_INMIGRATE) | ||||||
|  |                && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */ | ||||||
|  |         error_setg(errp, | ||||||
|  |                    "Guest must be stopped for opening of encrypted image"); | ||||||
|  |         ret = -EBUSY; | ||||||
|  |         goto close_and_fail; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     QDECREF(options); | ||||||
|     *pbs = bs; |     *pbs = bs; | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
| @@ -4055,7 +4062,7 @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag) | |||||||
|  |  | ||||||
| int bdrv_debug_resume(BlockDriverState *bs, const char *tag) | int bdrv_debug_resume(BlockDriverState *bs, const char *tag) | ||||||
| { | { | ||||||
|     while (bs && bs->drv && !bs->drv->bdrv_debug_resume) { |     while (bs && (!bs->drv || !bs->drv->bdrv_debug_resume)) { | ||||||
|         bs = bs->file; |         bs = bs->file; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -4776,9 +4783,17 @@ flush_parent: | |||||||
|  |  | ||||||
| void bdrv_invalidate_cache(BlockDriverState *bs) | void bdrv_invalidate_cache(BlockDriverState *bs) | ||||||
| { | { | ||||||
|     if (bs->drv && bs->drv->bdrv_invalidate_cache) { |     if (!bs->drv)  { | ||||||
|         bs->drv->bdrv_invalidate_cache(bs); |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (bs->drv->bdrv_invalidate_cache) { | ||||||
|  |         bs->drv->bdrv_invalidate_cache(bs); | ||||||
|  |     } else if (bs->file) { | ||||||
|  |         bdrv_invalidate_cache(bs->file); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     refresh_total_sectors(bs, bs->total_sectors); | ||||||
| } | } | ||||||
|  |  | ||||||
| void bdrv_invalidate_cache_all(void) | void bdrv_invalidate_cache_all(void) | ||||||
| @@ -5390,43 +5405,37 @@ int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options) | |||||||
|     return bs->drv->bdrv_amend_options(bs, options); |     return bs->drv->bdrv_amend_options(bs, options); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Used to recurse on single child block filters. | /* This function will be called by the bdrv_recurse_is_first_non_filter method | ||||||
|  * Single child block filter will store their child in bs->file. |  * of block filter and by bdrv_is_first_non_filter. | ||||||
|  |  * It is used to test if the given bs is the candidate or recurse more in the | ||||||
|  |  * node graph. | ||||||
|  */ |  */ | ||||||
| bool bdrv_generic_is_first_non_filter(BlockDriverState *bs, |  | ||||||
|                                       BlockDriverState *candidate) |  | ||||||
| { |  | ||||||
|     if (!bs->drv) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!bs->drv->authorizations[BS_IS_A_FILTER]) { |  | ||||||
|         if (bs == candidate) { |  | ||||||
|             return true; |  | ||||||
|         } else { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!bs->drv->authorizations[BS_FILTER_PASS_DOWN]) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!bs->file) { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return bdrv_recurse_is_first_non_filter(bs->file, candidate); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs, | bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs, | ||||||
|                                       BlockDriverState *candidate) |                                       BlockDriverState *candidate) | ||||||
| { | { | ||||||
|     if (bs->drv && bs->drv->bdrv_recurse_is_first_non_filter) { |     /* return false if basic checks fails */ | ||||||
|  |     if (!bs || !bs->drv) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* the code reached a non block filter driver -> check if the bs is | ||||||
|  |      * the same as the candidate. It's the recursion termination condition. | ||||||
|  |      */ | ||||||
|  |     if (!bs->drv->is_filter) { | ||||||
|  |         return bs == candidate; | ||||||
|  |     } | ||||||
|  |     /* Down this path the driver is a block filter driver */ | ||||||
|  |  | ||||||
|  |     /* If the block filter recursion method is defined use it to recurse down | ||||||
|  |      * the node graph. | ||||||
|  |      */ | ||||||
|  |     if (bs->drv->bdrv_recurse_is_first_non_filter) { | ||||||
|         return bs->drv->bdrv_recurse_is_first_non_filter(bs, candidate); |         return bs->drv->bdrv_recurse_is_first_non_filter(bs, candidate); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return bdrv_generic_is_first_non_filter(bs, candidate); |     /* the driver is a block filter but don't allow to recurse -> return false | ||||||
|  |      */ | ||||||
|  |     return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* This function checks if the candidate is the first non filter bs down it's | /* This function checks if the candidate is the first non filter bs down it's | ||||||
| @@ -5441,6 +5450,7 @@ bool bdrv_is_first_non_filter(BlockDriverState *candidate) | |||||||
|     QTAILQ_FOREACH(bs, &bdrv_states, device_list) { |     QTAILQ_FOREACH(bs, &bdrv_states, device_list) { | ||||||
|         bool perm; |         bool perm; | ||||||
|  |  | ||||||
|  |         /* try to recurse in this top level bs */ | ||||||
|         perm = bdrv_recurse_is_first_non_filter(bs, candidate); |         perm = bdrv_recurse_is_first_non_filter(bs, candidate); | ||||||
|  |  | ||||||
|         /* candidate is the first non filter */ |         /* candidate is the first non filter */ | ||||||
|   | |||||||
| @@ -288,6 +288,20 @@ static BlockDriverAIOCB *blkverify_aio_flush(BlockDriverState *bs, | |||||||
|     return bdrv_aio_flush(s->test_file, cb, opaque); |     return bdrv_aio_flush(s->test_file, cb, opaque); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs, | ||||||
|  |                                                   BlockDriverState *candidate) | ||||||
|  | { | ||||||
|  |     BDRVBlkverifyState *s = bs->opaque; | ||||||
|  |  | ||||||
|  |     bool perm = bdrv_recurse_is_first_non_filter(bs->file, candidate); | ||||||
|  |  | ||||||
|  |     if (perm) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return bdrv_recurse_is_first_non_filter(s->test_file, candidate); | ||||||
|  | } | ||||||
|  |  | ||||||
| static BlockDriver bdrv_blkverify = { | static BlockDriver bdrv_blkverify = { | ||||||
|     .format_name            = "blkverify", |     .format_name            = "blkverify", | ||||||
|     .protocol_name          = "blkverify", |     .protocol_name          = "blkverify", | ||||||
| @@ -302,7 +316,8 @@ static BlockDriver bdrv_blkverify = { | |||||||
|     .bdrv_aio_writev        = blkverify_aio_writev, |     .bdrv_aio_writev        = blkverify_aio_writev, | ||||||
|     .bdrv_aio_flush         = blkverify_aio_flush, |     .bdrv_aio_flush         = blkverify_aio_flush, | ||||||
|  |  | ||||||
|     .authorizations         = { true, false }, |     .is_filter              = true, | ||||||
|  |     .bdrv_recurse_is_first_non_filter = blkverify_recurse_is_first_non_filter, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void bdrv_blkverify_init(void) | static void bdrv_blkverify_init(void) | ||||||
|   | |||||||
| @@ -43,6 +43,17 @@ static void nbd_recv_coroutines_enter_all(NbdClientSession *s) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void nbd_teardown_connection(NbdClientSession *client) | ||||||
|  | { | ||||||
|  |     /* finish any pending coroutines */ | ||||||
|  |     shutdown(client->sock, 2); | ||||||
|  |     nbd_recv_coroutines_enter_all(client); | ||||||
|  |  | ||||||
|  |     qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL); | ||||||
|  |     closesocket(client->sock); | ||||||
|  |     client->sock = -1; | ||||||
|  | } | ||||||
|  |  | ||||||
| static void nbd_reply_ready(void *opaque) | static void nbd_reply_ready(void *opaque) | ||||||
| { | { | ||||||
|     NbdClientSession *s = opaque; |     NbdClientSession *s = opaque; | ||||||
| @@ -78,7 +89,7 @@ static void nbd_reply_ready(void *opaque) | |||||||
|     } |     } | ||||||
|  |  | ||||||
| fail: | fail: | ||||||
|     nbd_recv_coroutines_enter_all(s); |     nbd_teardown_connection(s); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void nbd_restart_write(void *opaque) | static void nbd_restart_write(void *opaque) | ||||||
| @@ -324,7 +335,7 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num, | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void nbd_teardown_connection(NbdClientSession *client) | void nbd_client_session_close(NbdClientSession *client) | ||||||
| { | { | ||||||
|     struct nbd_request request = { |     struct nbd_request request = { | ||||||
|         .type = NBD_CMD_DISC, |         .type = NBD_CMD_DISC, | ||||||
| @@ -332,22 +343,14 @@ static void nbd_teardown_connection(NbdClientSession *client) | |||||||
|         .len = 0 |         .len = 0 | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     nbd_send_request(client->sock, &request); |  | ||||||
|  |  | ||||||
|     /* finish any pending coroutines */ |  | ||||||
|     shutdown(client->sock, 2); |  | ||||||
|     nbd_recv_coroutines_enter_all(client); |  | ||||||
|  |  | ||||||
|     qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL); |  | ||||||
|     closesocket(client->sock); |  | ||||||
|     client->sock = -1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void nbd_client_session_close(NbdClientSession *client) |  | ||||||
| { |  | ||||||
|     if (!client->bs) { |     if (!client->bs) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |     if (client->sock == -1) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     nbd_send_request(client->sock, &request); | ||||||
|  |  | ||||||
|     nbd_teardown_connection(client); |     nbd_teardown_connection(client); | ||||||
|     client->bs = NULL; |     client->bs = NULL; | ||||||
|   | |||||||
| @@ -380,6 +380,10 @@ 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) { | ||||||
|  |         return -ENOMEDIUM; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* Call .bdrv_co_readv() directly instead of using the public block-layer |     /* Call .bdrv_co_readv() directly instead of using the public block-layer | ||||||
|      * interface.  This avoids double I/O throttling and request tracking, |      * interface.  This avoids double I/O throttling and request tracking, | ||||||
|      * which can lead to deadlock when block layer copy-on-read is enabled. |      * which can lead to deadlock when block layer copy-on-read is enabled. | ||||||
|   | |||||||
| @@ -96,7 +96,8 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index) | |||||||
|     refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); |     refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); | ||||||
|     if (refcount_table_index >= s->refcount_table_size) |     if (refcount_table_index >= s->refcount_table_size) | ||||||
|         return 0; |         return 0; | ||||||
|     refcount_block_offset = s->refcount_table[refcount_table_index]; |     refcount_block_offset = | ||||||
|  |         s->refcount_table[refcount_table_index] & REFT_OFFSET_MASK; | ||||||
|     if (!refcount_block_offset) |     if (!refcount_block_offset) | ||||||
|         return 0; |         return 0; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -644,7 +644,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Clear unknown autoclear feature bits */ |     /* Clear unknown autoclear feature bits */ | ||||||
|     if (!bs->read_only && s->autoclear_features != 0) { |     if (!bs->read_only && !(flags & BDRV_O_INCOMING) && s->autoclear_features) { | ||||||
|         s->autoclear_features = 0; |         s->autoclear_features = 0; | ||||||
|         ret = qcow2_update_header(bs); |         ret = qcow2_update_header(bs); | ||||||
|         if (ret < 0) { |         if (ret < 0) { | ||||||
| @@ -657,7 +657,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, | |||||||
|     qemu_co_mutex_init(&s->lock); |     qemu_co_mutex_init(&s->lock); | ||||||
|  |  | ||||||
|     /* Repair image if dirty */ |     /* Repair image if dirty */ | ||||||
|     if (!(flags & BDRV_O_CHECK) && !bs->read_only && |     if (!(flags & (BDRV_O_CHECK | BDRV_O_INCOMING)) && !bs->read_only && | ||||||
|         (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) { |         (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) { | ||||||
|         BdrvCheckResult result = {0}; |         BdrvCheckResult result = {0}; | ||||||
|  |  | ||||||
| @@ -1137,10 +1137,12 @@ static void qcow2_close(BlockDriverState *bs) | |||||||
|     /* else pre-write overlap checks in cache_destroy may crash */ |     /* else pre-write overlap checks in cache_destroy may crash */ | ||||||
|     s->l1_table = NULL; |     s->l1_table = NULL; | ||||||
|  |  | ||||||
|     qcow2_cache_flush(bs, s->l2_table_cache); |     if (!(bs->open_flags & BDRV_O_INCOMING)) { | ||||||
|     qcow2_cache_flush(bs, s->refcount_block_cache); |         qcow2_cache_flush(bs, s->l2_table_cache); | ||||||
|  |         qcow2_cache_flush(bs, s->refcount_block_cache); | ||||||
|  |  | ||||||
|     qcow2_mark_clean(bs); |         qcow2_mark_clean(bs); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     qcow2_cache_destroy(bs, s->l2_table_cache); |     qcow2_cache_destroy(bs, s->l2_table_cache); | ||||||
|     qcow2_cache_destroy(bs, s->refcount_block_cache); |     qcow2_cache_destroy(bs, s->refcount_block_cache); | ||||||
| @@ -1176,11 +1178,10 @@ static void qcow2_invalidate_cache(BlockDriverState *bs) | |||||||
|  |  | ||||||
|     qcow2_close(bs); |     qcow2_close(bs); | ||||||
|  |  | ||||||
|     options = qdict_new(); |     bdrv_invalidate_cache(bs->file); | ||||||
|     qdict_put(options, QCOW2_OPT_LAZY_REFCOUNTS, |  | ||||||
|               qbool_from_int(s->use_lazy_refcounts)); |  | ||||||
|  |  | ||||||
|     memset(s, 0, sizeof(BDRVQcowState)); |     memset(s, 0, sizeof(BDRVQcowState)); | ||||||
|  |     options = qdict_clone_shallow(bs->options); | ||||||
|     qcow2_open(bs, options, flags, NULL); |     qcow2_open(bs, options, flags, NULL); | ||||||
|  |  | ||||||
|     QDECREF(options); |     QDECREF(options); | ||||||
|   | |||||||
| @@ -1563,6 +1563,9 @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs) | |||||||
|     BDRVQEDState *s = bs->opaque; |     BDRVQEDState *s = bs->opaque; | ||||||
|  |  | ||||||
|     bdrv_qed_close(bs); |     bdrv_qed_close(bs); | ||||||
|  |  | ||||||
|  |     bdrv_invalidate_cache(bs->file); | ||||||
|  |  | ||||||
|     memset(s, 0, sizeof(BDRVQEDState)); |     memset(s, 0, sizeof(BDRVQEDState)); | ||||||
|     bdrv_qed_open(bs, NULL, bs->open_flags, NULL); |     bdrv_qed_open(bs, NULL, bs->open_flags, NULL); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -852,8 +852,6 @@ static BlockDriver bdrv_quorum = { | |||||||
|     .bdrv_file_open     = quorum_open, |     .bdrv_file_open     = quorum_open, | ||||||
|     .bdrv_close         = quorum_close, |     .bdrv_close         = quorum_close, | ||||||
|  |  | ||||||
|     .authorizations     = { true, true }, |  | ||||||
|  |  | ||||||
|     .bdrv_co_flush_to_disk = quorum_co_flush, |     .bdrv_co_flush_to_disk = quorum_co_flush, | ||||||
|  |  | ||||||
|     .bdrv_getlength     = quorum_getlength, |     .bdrv_getlength     = quorum_getlength, | ||||||
| @@ -862,6 +860,7 @@ static BlockDriver bdrv_quorum = { | |||||||
|     .bdrv_aio_writev    = quorum_aio_writev, |     .bdrv_aio_writev    = quorum_aio_writev, | ||||||
|     .bdrv_invalidate_cache = quorum_invalidate_cache, |     .bdrv_invalidate_cache = quorum_invalidate_cache, | ||||||
|  |  | ||||||
|  |     .is_filter           = true, | ||||||
|     .bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter, |     .bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1561,6 +1561,15 @@ static int check_hdev_writable(BDRVRawState *s) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void hdev_parse_filename(const char *filename, QDict *options, | ||||||
|  |                                 Error **errp) | ||||||
|  | { | ||||||
|  |     /* The prefix is optional, just as for "file". */ | ||||||
|  |     strstart(filename, "host_device:", &filename); | ||||||
|  |  | ||||||
|  |     qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename))); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int hdev_open(BlockDriverState *bs, QDict *options, int flags, | static int hdev_open(BlockDriverState *bs, QDict *options, int flags, | ||||||
|                      Error **errp) |                      Error **errp) | ||||||
| { | { | ||||||
| @@ -1767,6 +1776,18 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options, | |||||||
|     int ret = 0; |     int ret = 0; | ||||||
|     struct stat stat_buf; |     struct stat stat_buf; | ||||||
|     int64_t total_size = 0; |     int64_t total_size = 0; | ||||||
|  |     bool has_prefix; | ||||||
|  |  | ||||||
|  |     /* This function is used by all three protocol block drivers and therefore | ||||||
|  |      * any of these three prefixes may be given. | ||||||
|  |      * The return value has to be stored somewhere, otherwise this is an error | ||||||
|  |      * due to -Werror=unused-value. */ | ||||||
|  |     has_prefix = | ||||||
|  |         strstart(filename, "host_device:", &filename) || | ||||||
|  |         strstart(filename, "host_cdrom:" , &filename) || | ||||||
|  |         strstart(filename, "host_floppy:", &filename); | ||||||
|  |  | ||||||
|  |     (void)has_prefix; | ||||||
|  |  | ||||||
|     /* Read out options */ |     /* Read out options */ | ||||||
|     while (options && options->name) { |     while (options && options->name) { | ||||||
| @@ -1805,6 +1826,7 @@ static BlockDriver bdrv_host_device = { | |||||||
|     .instance_size      = sizeof(BDRVRawState), |     .instance_size      = sizeof(BDRVRawState), | ||||||
|     .bdrv_needs_filename = true, |     .bdrv_needs_filename = true, | ||||||
|     .bdrv_probe_device  = hdev_probe_device, |     .bdrv_probe_device  = hdev_probe_device, | ||||||
|  |     .bdrv_parse_filename = hdev_parse_filename, | ||||||
|     .bdrv_file_open     = hdev_open, |     .bdrv_file_open     = hdev_open, | ||||||
|     .bdrv_close         = raw_close, |     .bdrv_close         = raw_close, | ||||||
|     .bdrv_reopen_prepare = raw_reopen_prepare, |     .bdrv_reopen_prepare = raw_reopen_prepare, | ||||||
| @@ -1834,6 +1856,15 @@ static BlockDriver bdrv_host_device = { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| #ifdef __linux__ | #ifdef __linux__ | ||||||
|  | static void floppy_parse_filename(const char *filename, QDict *options, | ||||||
|  |                                   Error **errp) | ||||||
|  | { | ||||||
|  |     /* The prefix is optional, just as for "file". */ | ||||||
|  |     strstart(filename, "host_floppy:", &filename); | ||||||
|  |  | ||||||
|  |     qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename))); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int floppy_open(BlockDriverState *bs, QDict *options, int flags, | static int floppy_open(BlockDriverState *bs, QDict *options, int flags, | ||||||
|                        Error **errp) |                        Error **errp) | ||||||
| { | { | ||||||
| @@ -1939,6 +1970,7 @@ static BlockDriver bdrv_host_floppy = { | |||||||
|     .instance_size      = sizeof(BDRVRawState), |     .instance_size      = sizeof(BDRVRawState), | ||||||
|     .bdrv_needs_filename = true, |     .bdrv_needs_filename = true, | ||||||
|     .bdrv_probe_device	= floppy_probe_device, |     .bdrv_probe_device	= floppy_probe_device, | ||||||
|  |     .bdrv_parse_filename = floppy_parse_filename, | ||||||
|     .bdrv_file_open     = floppy_open, |     .bdrv_file_open     = floppy_open, | ||||||
|     .bdrv_close         = raw_close, |     .bdrv_close         = raw_close, | ||||||
|     .bdrv_reopen_prepare = raw_reopen_prepare, |     .bdrv_reopen_prepare = raw_reopen_prepare, | ||||||
| @@ -1963,7 +1995,20 @@ static BlockDriver bdrv_host_floppy = { | |||||||
|     .bdrv_media_changed = floppy_media_changed, |     .bdrv_media_changed = floppy_media_changed, | ||||||
|     .bdrv_eject         = floppy_eject, |     .bdrv_eject         = floppy_eject, | ||||||
| }; | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | ||||||
|  | static void cdrom_parse_filename(const char *filename, QDict *options, | ||||||
|  |                                  Error **errp) | ||||||
|  | { | ||||||
|  |     /* The prefix is optional, just as for "file". */ | ||||||
|  |     strstart(filename, "host_cdrom:", &filename); | ||||||
|  |  | ||||||
|  |     qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename))); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef __linux__ | ||||||
| static int cdrom_open(BlockDriverState *bs, QDict *options, int flags, | static int cdrom_open(BlockDriverState *bs, QDict *options, int flags, | ||||||
|                       Error **errp) |                       Error **errp) | ||||||
| { | { | ||||||
| @@ -2050,6 +2095,7 @@ static BlockDriver bdrv_host_cdrom = { | |||||||
|     .instance_size      = sizeof(BDRVRawState), |     .instance_size      = sizeof(BDRVRawState), | ||||||
|     .bdrv_needs_filename = true, |     .bdrv_needs_filename = true, | ||||||
|     .bdrv_probe_device	= cdrom_probe_device, |     .bdrv_probe_device	= cdrom_probe_device, | ||||||
|  |     .bdrv_parse_filename = cdrom_parse_filename, | ||||||
|     .bdrv_file_open     = cdrom_open, |     .bdrv_file_open     = cdrom_open, | ||||||
|     .bdrv_close         = raw_close, |     .bdrv_close         = raw_close, | ||||||
|     .bdrv_reopen_prepare = raw_reopen_prepare, |     .bdrv_reopen_prepare = raw_reopen_prepare, | ||||||
| @@ -2180,6 +2226,7 @@ static BlockDriver bdrv_host_cdrom = { | |||||||
|     .instance_size      = sizeof(BDRVRawState), |     .instance_size      = sizeof(BDRVRawState), | ||||||
|     .bdrv_needs_filename = true, |     .bdrv_needs_filename = true, | ||||||
|     .bdrv_probe_device	= cdrom_probe_device, |     .bdrv_probe_device	= cdrom_probe_device, | ||||||
|  |     .bdrv_parse_filename = cdrom_parse_filename, | ||||||
|     .bdrv_file_open     = cdrom_open, |     .bdrv_file_open     = cdrom_open, | ||||||
|     .bdrv_close         = raw_close, |     .bdrv_close         = raw_close, | ||||||
|     .bdrv_reopen_prepare = raw_reopen_prepare, |     .bdrv_reopen_prepare = raw_reopen_prepare, | ||||||
|   | |||||||
| @@ -593,6 +593,15 @@ static int hdev_probe_device(const char *filename) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void hdev_parse_filename(const char *filename, QDict *options, | ||||||
|  |                                 Error **errp) | ||||||
|  | { | ||||||
|  |     /* The prefix is optional, just as for "file". */ | ||||||
|  |     strstart(filename, "host_device:", &filename); | ||||||
|  |  | ||||||
|  |     qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename))); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int hdev_open(BlockDriverState *bs, QDict *options, int flags, | static int hdev_open(BlockDriverState *bs, QDict *options, int flags, | ||||||
|                      Error **errp) |                      Error **errp) | ||||||
| { | { | ||||||
| @@ -663,6 +672,7 @@ static BlockDriver bdrv_host_device = { | |||||||
|     .protocol_name	= "host_device", |     .protocol_name	= "host_device", | ||||||
|     .instance_size	= sizeof(BDRVRawState), |     .instance_size	= sizeof(BDRVRawState), | ||||||
|     .bdrv_needs_filename = true, |     .bdrv_needs_filename = true, | ||||||
|  |     .bdrv_parse_filename = hdev_parse_filename, | ||||||
|     .bdrv_probe_device	= hdev_probe_device, |     .bdrv_probe_device	= hdev_probe_device, | ||||||
|     .bdrv_file_open	= hdev_open, |     .bdrv_file_open	= hdev_open, | ||||||
|     .bdrv_close		= raw_close, |     .bdrv_close		= raw_close, | ||||||
|   | |||||||
| @@ -61,7 +61,7 @@ | |||||||
| /* These structures are ones that are defined in the VHDX specification | /* These structures are ones that are defined in the VHDX specification | ||||||
|  * document */ |  * document */ | ||||||
|  |  | ||||||
| #define VHDX_FILE_SIGNATURE 0x656C696678646876  /* "vhdxfile" in ASCII */ | #define VHDX_FILE_SIGNATURE 0x656C696678646876ULL  /* "vhdxfile" in ASCII */ | ||||||
| typedef struct VHDXFileIdentifier { | typedef struct VHDXFileIdentifier { | ||||||
|     uint64_t    signature;              /* "vhdxfile" in ASCII */ |     uint64_t    signature;              /* "vhdxfile" in ASCII */ | ||||||
|     uint16_t    creator[256];           /* optional; utf-16 string to identify |     uint16_t    creator[256];           /* optional; utf-16 string to identify | ||||||
| @@ -238,7 +238,7 @@ typedef struct QEMU_PACKED VHDXLogDataSector { | |||||||
| /* upper 44 bits are the file offset in 1MB units lower 3 bits are the state | /* upper 44 bits are the file offset in 1MB units lower 3 bits are the state | ||||||
|    other bits are reserved */ |    other bits are reserved */ | ||||||
| #define VHDX_BAT_STATE_BIT_MASK 0x07 | #define VHDX_BAT_STATE_BIT_MASK 0x07 | ||||||
| #define VHDX_BAT_FILE_OFF_MASK  0xFFFFFFFFFFF00000 /* upper 44 bits */ | #define VHDX_BAT_FILE_OFF_MASK  0xFFFFFFFFFFF00000ULL /* upper 44 bits */ | ||||||
| typedef uint64_t VHDXBatEntry; | typedef uint64_t VHDXBatEntry; | ||||||
|  |  | ||||||
| /* ---- METADATA REGION STRUCTURES ---- */ | /* ---- METADATA REGION STRUCTURES ---- */ | ||||||
| @@ -247,7 +247,7 @@ typedef uint64_t VHDXBatEntry; | |||||||
| #define VHDX_METADATA_MAX_ENTRIES 2047  /* not including the header */ | #define VHDX_METADATA_MAX_ENTRIES 2047  /* not including the header */ | ||||||
| #define VHDX_METADATA_TABLE_MAX_SIZE \ | #define VHDX_METADATA_TABLE_MAX_SIZE \ | ||||||
|     (VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1)) |     (VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1)) | ||||||
| #define VHDX_METADATA_SIGNATURE 0x617461646174656D  /* "metadata" in ASCII */ | #define VHDX_METADATA_SIGNATURE 0x617461646174656DULL  /* "metadata" in ASCII */ | ||||||
| typedef struct QEMU_PACKED VHDXMetadataTableHeader { | typedef struct QEMU_PACKED VHDXMetadataTableHeader { | ||||||
|     uint64_t    signature;              /* "metadata" in ASCII */ |     uint64_t    signature;              /* "metadata" in ASCII */ | ||||||
|     uint16_t    reserved; |     uint16_t    reserved; | ||||||
|   | |||||||
| @@ -1000,7 +1000,7 @@ int main(int argc, char **argv) | |||||||
|     memset(ts, 0, sizeof(TaskState)); |     memset(ts, 0, sizeof(TaskState)); | ||||||
|     init_task_state(ts); |     init_task_state(ts); | ||||||
|     ts->info = info; |     ts->info = info; | ||||||
|     env->opaque = ts; |     cpu->opaque = ts; | ||||||
|  |  | ||||||
| #if defined(TARGET_I386) | #if defined(TARGET_I386) | ||||||
|     cpu_x86_set_cpl(env, 3); |     cpu_x86_set_cpl(env, 3); | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -31,19 +31,6 @@ printf " '%s'" "$0" "$@" >> config.log | |||||||
| echo >> config.log | echo >> config.log | ||||||
| echo "#" >> config.log | echo "#" >> config.log | ||||||
|  |  | ||||||
| # Save the configure command line for later reuse. |  | ||||||
| cat <<EOD >config.status |  | ||||||
| #!/bin/sh |  | ||||||
| # Generated by configure. |  | ||||||
| # Run this file to recreate the current configuration. |  | ||||||
| # Compiler output produced by configure, useful for debugging |  | ||||||
| # configure, is in config.log if it exists. |  | ||||||
| EOD |  | ||||||
| printf "exec" >>config.status |  | ||||||
| printf " '%s'" "$0" "$@" >>config.status |  | ||||||
| echo >>config.status |  | ||||||
| chmod +x config.status |  | ||||||
|  |  | ||||||
| error_exit() { | error_exit() { | ||||||
|     echo |     echo | ||||||
|     echo "ERROR: $1" |     echo "ERROR: $1" | ||||||
| @@ -3835,6 +3822,11 @@ fi | |||||||
|  |  | ||||||
| int128=no | int128=no | ||||||
| cat > $TMPC << EOF | cat > $TMPC << EOF | ||||||
|  | #if defined(__clang_major__) && defined(__clang_minor__) | ||||||
|  | # if ((__clang_major__ < 3) || (__clang_major__ == 3) && (__clang_minor__ < 2)) | ||||||
|  | #  error __int128_t does not work in CLANG before 3.2 | ||||||
|  | # endif | ||||||
|  | #endif | ||||||
| __int128_t a; | __int128_t a; | ||||||
| __uint128_t b; | __uint128_t b; | ||||||
| int main (void) { | int main (void) { | ||||||
| @@ -5146,3 +5138,17 @@ done | |||||||
| if test "$docs" = "yes" ; then | if test "$docs" = "yes" ; then | ||||||
|   mkdir -p QMP |   mkdir -p QMP | ||||||
| fi | fi | ||||||
|  |  | ||||||
|  | # Save the configure command line for later reuse. | ||||||
|  | cat <<EOD >config.status | ||||||
|  | #!/bin/sh | ||||||
|  | # Generated by configure. | ||||||
|  | # Run this file to recreate the current configuration. | ||||||
|  | # Compiler output produced by configure, useful for debugging | ||||||
|  | # configure, is in config.log if it exists. | ||||||
|  | EOD | ||||||
|  | printf "exec" >>config.status | ||||||
|  | printf " '%s'" "$0" "$@" >>config.status | ||||||
|  | echo >>config.status | ||||||
|  | chmod +x config.status | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										106
									
								
								cpu-exec.c
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								cpu-exec.c
									
									
									
									
									
								
							| @@ -23,29 +23,22 @@ | |||||||
| #include "qemu/atomic.h" | #include "qemu/atomic.h" | ||||||
| #include "sysemu/qtest.h" | #include "sysemu/qtest.h" | ||||||
|  |  | ||||||
| bool qemu_cpu_has_work(CPUState *cpu) | void cpu_loop_exit(CPUState *cpu) | ||||||
| { | { | ||||||
|     return cpu_has_work(cpu); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void cpu_loop_exit(CPUArchState *env) |  | ||||||
| { |  | ||||||
|     CPUState *cpu = ENV_GET_CPU(env); |  | ||||||
|  |  | ||||||
|     cpu->current_tb = NULL; |     cpu->current_tb = NULL; | ||||||
|     siglongjmp(env->jmp_env, 1); |     siglongjmp(cpu->jmp_env, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* exit the current TB from a signal handler. The host registers are | /* exit the current TB from a signal handler. The host registers are | ||||||
|    restored in a state compatible with the CPU emulator |    restored in a state compatible with the CPU emulator | ||||||
|  */ |  */ | ||||||
| #if defined(CONFIG_SOFTMMU) | #if defined(CONFIG_SOFTMMU) | ||||||
| void cpu_resume_from_signal(CPUArchState *env, void *puc) | void cpu_resume_from_signal(CPUState *cpu, void *puc) | ||||||
| { | { | ||||||
|     /* XXX: restore cpu registers saved in host registers */ |     /* XXX: restore cpu registers saved in host registers */ | ||||||
|  |  | ||||||
|     env->exception_index = -1; |     cpu->exception_index = -1; | ||||||
|     siglongjmp(env->jmp_env, 1); |     siglongjmp(cpu->jmp_env, 1); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -108,7 +101,7 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles, | |||||||
|     if (max_cycles > CF_COUNT_MASK) |     if (max_cycles > CF_COUNT_MASK) | ||||||
|         max_cycles = CF_COUNT_MASK; |         max_cycles = CF_COUNT_MASK; | ||||||
|  |  | ||||||
|     tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, |     tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, | ||||||
|                      max_cycles); |                      max_cycles); | ||||||
|     cpu->current_tb = tb; |     cpu->current_tb = tb; | ||||||
|     /* execute the generated code */ |     /* execute the generated code */ | ||||||
| @@ -123,6 +116,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, | |||||||
|                                       target_ulong cs_base, |                                       target_ulong cs_base, | ||||||
|                                       uint64_t flags) |                                       uint64_t flags) | ||||||
| { | { | ||||||
|  |     CPUState *cpu = ENV_GET_CPU(env); | ||||||
|     TranslationBlock *tb, **ptb1; |     TranslationBlock *tb, **ptb1; | ||||||
|     unsigned int h; |     unsigned int h; | ||||||
|     tb_page_addr_t phys_pc, phys_page1; |     tb_page_addr_t phys_pc, phys_page1; | ||||||
| @@ -160,7 +154,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, | |||||||
|     } |     } | ||||||
|  not_found: |  not_found: | ||||||
|    /* if no translated code available, then translate it now */ |    /* if no translated code available, then translate it now */ | ||||||
|     tb = tb_gen_code(env, pc, cs_base, flags, 0); |     tb = tb_gen_code(cpu, pc, cs_base, flags, 0); | ||||||
|  |  | ||||||
|  found: |  found: | ||||||
|     /* Move the last found TB to the head of the list */ |     /* Move the last found TB to the head of the list */ | ||||||
| @@ -170,12 +164,13 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, | |||||||
|         tcg_ctx.tb_ctx.tb_phys_hash[h] = tb; |         tcg_ctx.tb_ctx.tb_phys_hash[h] = tb; | ||||||
|     } |     } | ||||||
|     /* we add the TB in the virtual pc hash table */ |     /* we add the TB in the virtual pc hash table */ | ||||||
|     env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; |     cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; | ||||||
|     return tb; |     return tb; | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline TranslationBlock *tb_find_fast(CPUArchState *env) | static inline TranslationBlock *tb_find_fast(CPUArchState *env) | ||||||
| { | { | ||||||
|  |     CPUState *cpu = ENV_GET_CPU(env); | ||||||
|     TranslationBlock *tb; |     TranslationBlock *tb; | ||||||
|     target_ulong cs_base, pc; |     target_ulong cs_base, pc; | ||||||
|     int flags; |     int flags; | ||||||
| @@ -184,7 +179,7 @@ static inline TranslationBlock *tb_find_fast(CPUArchState *env) | |||||||
|        always be the same before a given translated block |        always be the same before a given translated block | ||||||
|        is executed. */ |        is executed. */ | ||||||
|     cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); |     cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); | ||||||
|     tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; |     tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; | ||||||
|     if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || |     if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || | ||||||
|                  tb->flags != flags)) { |                  tb->flags != flags)) { | ||||||
|         tb = tb_find_slow(env, pc, cs_base, flags); |         tb = tb_find_slow(env, pc, cs_base, flags); | ||||||
| @@ -201,10 +196,11 @@ void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler) | |||||||
|  |  | ||||||
| static void cpu_handle_debug_exception(CPUArchState *env) | static void cpu_handle_debug_exception(CPUArchState *env) | ||||||
| { | { | ||||||
|  |     CPUState *cpu = ENV_GET_CPU(env); | ||||||
|     CPUWatchpoint *wp; |     CPUWatchpoint *wp; | ||||||
|  |  | ||||||
|     if (!env->watchpoint_hit) { |     if (!cpu->watchpoint_hit) { | ||||||
|         QTAILQ_FOREACH(wp, &env->watchpoints, entry) { |         QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { | ||||||
|             wp->flags &= ~BP_WATCHPOINT_HIT; |             wp->flags &= ~BP_WATCHPOINT_HIT; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -283,16 +279,16 @@ int cpu_exec(CPUArchState *env) | |||||||
| #else | #else | ||||||
| #error unsupported target CPU | #error unsupported target CPU | ||||||
| #endif | #endif | ||||||
|     env->exception_index = -1; |     cpu->exception_index = -1; | ||||||
|  |  | ||||||
|     /* prepare setjmp context for exception handling */ |     /* prepare setjmp context for exception handling */ | ||||||
|     for(;;) { |     for(;;) { | ||||||
|         if (sigsetjmp(env->jmp_env, 0) == 0) { |         if (sigsetjmp(cpu->jmp_env, 0) == 0) { | ||||||
|             /* if an exception is pending, we execute it here */ |             /* if an exception is pending, we execute it here */ | ||||||
|             if (env->exception_index >= 0) { |             if (cpu->exception_index >= 0) { | ||||||
|                 if (env->exception_index >= EXCP_INTERRUPT) { |                 if (cpu->exception_index >= EXCP_INTERRUPT) { | ||||||
|                     /* exit request from the cpu execution loop */ |                     /* exit request from the cpu execution loop */ | ||||||
|                     ret = env->exception_index; |                     ret = cpu->exception_index; | ||||||
|                     if (ret == EXCP_DEBUG) { |                     if (ret == EXCP_DEBUG) { | ||||||
|                         cpu_handle_debug_exception(env); |                         cpu_handle_debug_exception(env); | ||||||
|                     } |                     } | ||||||
| @@ -305,11 +301,11 @@ int cpu_exec(CPUArchState *env) | |||||||
| #if defined(TARGET_I386) | #if defined(TARGET_I386) | ||||||
|                     cc->do_interrupt(cpu); |                     cc->do_interrupt(cpu); | ||||||
| #endif | #endif | ||||||
|                     ret = env->exception_index; |                     ret = cpu->exception_index; | ||||||
|                     break; |                     break; | ||||||
| #else | #else | ||||||
|                     cc->do_interrupt(cpu); |                     cc->do_interrupt(cpu); | ||||||
|                     env->exception_index = -1; |                     cpu->exception_index = -1; | ||||||
| #endif | #endif | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -324,8 +320,8 @@ int cpu_exec(CPUArchState *env) | |||||||
|                     } |                     } | ||||||
|                     if (interrupt_request & CPU_INTERRUPT_DEBUG) { |                     if (interrupt_request & CPU_INTERRUPT_DEBUG) { | ||||||
|                         cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG; |                         cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG; | ||||||
|                         env->exception_index = EXCP_DEBUG; |                         cpu->exception_index = EXCP_DEBUG; | ||||||
|                         cpu_loop_exit(env); |                         cpu_loop_exit(cpu); | ||||||
|                     } |                     } | ||||||
| #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ | #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ | ||||||
|     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \ |     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \ | ||||||
| @@ -333,8 +329,8 @@ int cpu_exec(CPUArchState *env) | |||||||
|                     if (interrupt_request & CPU_INTERRUPT_HALT) { |                     if (interrupt_request & CPU_INTERRUPT_HALT) { | ||||||
|                         cpu->interrupt_request &= ~CPU_INTERRUPT_HALT; |                         cpu->interrupt_request &= ~CPU_INTERRUPT_HALT; | ||||||
|                         cpu->halted = 1; |                         cpu->halted = 1; | ||||||
|                         env->exception_index = EXCP_HLT; |                         cpu->exception_index = EXCP_HLT; | ||||||
|                         cpu_loop_exit(env); |                         cpu_loop_exit(cpu); | ||||||
|                     } |                     } | ||||||
| #endif | #endif | ||||||
| #if defined(TARGET_I386) | #if defined(TARGET_I386) | ||||||
| @@ -348,8 +344,8 @@ int cpu_exec(CPUArchState *env) | |||||||
|                             cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, |                             cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, | ||||||
|                                                           0); |                                                           0); | ||||||
|                             do_cpu_init(x86_cpu); |                             do_cpu_init(x86_cpu); | ||||||
|                             env->exception_index = EXCP_HALTED; |                             cpu->exception_index = EXCP_HALTED; | ||||||
|                             cpu_loop_exit(env); |                             cpu_loop_exit(cpu); | ||||||
|                     } else if (interrupt_request & CPU_INTERRUPT_SIPI) { |                     } else if (interrupt_request & CPU_INTERRUPT_SIPI) { | ||||||
|                             do_cpu_sipi(x86_cpu); |                             do_cpu_sipi(x86_cpu); | ||||||
|                     } else if (env->hflags2 & HF2_GIF_MASK) { |                     } else if (env->hflags2 & HF2_GIF_MASK) { | ||||||
| @@ -420,7 +416,7 @@ int cpu_exec(CPUArchState *env) | |||||||
| #elif defined(TARGET_LM32) | #elif defined(TARGET_LM32) | ||||||
|                     if ((interrupt_request & CPU_INTERRUPT_HARD) |                     if ((interrupt_request & CPU_INTERRUPT_HARD) | ||||||
|                         && (env->ie & IE_IE)) { |                         && (env->ie & IE_IE)) { | ||||||
|                         env->exception_index = EXCP_IRQ; |                         cpu->exception_index = EXCP_IRQ; | ||||||
|                         cc->do_interrupt(cpu); |                         cc->do_interrupt(cpu); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
|                     } |                     } | ||||||
| @@ -429,7 +425,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                         && (env->sregs[SR_MSR] & MSR_IE) |                         && (env->sregs[SR_MSR] & MSR_IE) | ||||||
|                         && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)) |                         && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)) | ||||||
|                         && !(env->iflags & (D_FLAG | IMM_FLAG))) { |                         && !(env->iflags & (D_FLAG | IMM_FLAG))) { | ||||||
|                         env->exception_index = EXCP_IRQ; |                         cpu->exception_index = EXCP_IRQ; | ||||||
|                         cc->do_interrupt(cpu); |                         cc->do_interrupt(cpu); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
|                     } |                     } | ||||||
| @@ -437,7 +433,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                     if ((interrupt_request & CPU_INTERRUPT_HARD) && |                     if ((interrupt_request & CPU_INTERRUPT_HARD) && | ||||||
|                         cpu_mips_hw_interrupts_pending(env)) { |                         cpu_mips_hw_interrupts_pending(env)) { | ||||||
|                         /* Raise it */ |                         /* Raise it */ | ||||||
|                         env->exception_index = EXCP_EXT_INTERRUPT; |                         cpu->exception_index = EXCP_EXT_INTERRUPT; | ||||||
|                         env->error_code = 0; |                         env->error_code = 0; | ||||||
|                         cc->do_interrupt(cpu); |                         cc->do_interrupt(cpu); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
| @@ -454,7 +450,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                             idx = EXCP_TICK; |                             idx = EXCP_TICK; | ||||||
|                         } |                         } | ||||||
|                         if (idx >= 0) { |                         if (idx >= 0) { | ||||||
|                             env->exception_index = idx; |                             cpu->exception_index = idx; | ||||||
|                             cc->do_interrupt(cpu); |                             cc->do_interrupt(cpu); | ||||||
|                             next_tb = 0; |                             next_tb = 0; | ||||||
|                         } |                         } | ||||||
| @@ -469,7 +465,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                             if (((type == TT_EXTINT) && |                             if (((type == TT_EXTINT) && | ||||||
|                                   cpu_pil_allowed(env, pil)) || |                                   cpu_pil_allowed(env, pil)) || | ||||||
|                                   type != TT_EXTINT) { |                                   type != TT_EXTINT) { | ||||||
|                                 env->exception_index = env->interrupt_index; |                                 cpu->exception_index = env->interrupt_index; | ||||||
|                                 cc->do_interrupt(cpu); |                                 cc->do_interrupt(cpu); | ||||||
|                                 next_tb = 0; |                                 next_tb = 0; | ||||||
|                             } |                             } | ||||||
| @@ -478,7 +474,7 @@ int cpu_exec(CPUArchState *env) | |||||||
| #elif defined(TARGET_ARM) | #elif defined(TARGET_ARM) | ||||||
|                     if (interrupt_request & CPU_INTERRUPT_FIQ |                     if (interrupt_request & CPU_INTERRUPT_FIQ | ||||||
|                         && !(env->daif & PSTATE_F)) { |                         && !(env->daif & PSTATE_F)) { | ||||||
|                         env->exception_index = EXCP_FIQ; |                         cpu->exception_index = EXCP_FIQ; | ||||||
|                         cc->do_interrupt(cpu); |                         cc->do_interrupt(cpu); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
|                     } |                     } | ||||||
| @@ -494,14 +490,14 @@ int cpu_exec(CPUArchState *env) | |||||||
|                     if (interrupt_request & CPU_INTERRUPT_HARD |                     if (interrupt_request & CPU_INTERRUPT_HARD | ||||||
|                         && ((IS_M(env) && env->regs[15] < 0xfffffff0) |                         && ((IS_M(env) && env->regs[15] < 0xfffffff0) | ||||||
|                             || !(env->daif & PSTATE_I))) { |                             || !(env->daif & PSTATE_I))) { | ||||||
|                         env->exception_index = EXCP_IRQ; |                         cpu->exception_index = EXCP_IRQ; | ||||||
|                         cc->do_interrupt(cpu); |                         cc->do_interrupt(cpu); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
|                     } |                     } | ||||||
| #elif defined(TARGET_UNICORE32) | #elif defined(TARGET_UNICORE32) | ||||||
|                     if (interrupt_request & CPU_INTERRUPT_HARD |                     if (interrupt_request & CPU_INTERRUPT_HARD | ||||||
|                         && !(env->uncached_asr & ASR_I)) { |                         && !(env->uncached_asr & ASR_I)) { | ||||||
|                         env->exception_index = UC32_EXCP_INTR; |                         cpu->exception_index = UC32_EXCP_INTR; | ||||||
|                         cc->do_interrupt(cpu); |                         cc->do_interrupt(cpu); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
|                     } |                     } | ||||||
| @@ -536,7 +532,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                         if (idx >= 0) { |                         if (idx >= 0) { | ||||||
|                             env->exception_index = idx; |                             cpu->exception_index = idx; | ||||||
|                             env->error_code = 0; |                             env->error_code = 0; | ||||||
|                             cc->do_interrupt(cpu); |                             cc->do_interrupt(cpu); | ||||||
|                             next_tb = 0; |                             next_tb = 0; | ||||||
| @@ -546,7 +542,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                     if (interrupt_request & CPU_INTERRUPT_HARD |                     if (interrupt_request & CPU_INTERRUPT_HARD | ||||||
|                         && (env->pregs[PR_CCS] & I_FLAG) |                         && (env->pregs[PR_CCS] & I_FLAG) | ||||||
|                         && !env->locked_irq) { |                         && !env->locked_irq) { | ||||||
|                         env->exception_index = EXCP_IRQ; |                         cpu->exception_index = EXCP_IRQ; | ||||||
|                         cc->do_interrupt(cpu); |                         cc->do_interrupt(cpu); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
|                     } |                     } | ||||||
| @@ -558,7 +554,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                             m_flag_archval = M_FLAG_V32; |                             m_flag_archval = M_FLAG_V32; | ||||||
|                         } |                         } | ||||||
|                         if ((env->pregs[PR_CCS] & m_flag_archval)) { |                         if ((env->pregs[PR_CCS] & m_flag_archval)) { | ||||||
|                             env->exception_index = EXCP_NMI; |                             cpu->exception_index = EXCP_NMI; | ||||||
|                             cc->do_interrupt(cpu); |                             cc->do_interrupt(cpu); | ||||||
|                             next_tb = 0; |                             next_tb = 0; | ||||||
|                         } |                         } | ||||||
| @@ -572,7 +568,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                            hardware doesn't rely on this, so we |                            hardware doesn't rely on this, so we | ||||||
|                            provide/save the vector when the interrupt is |                            provide/save the vector when the interrupt is | ||||||
|                            first signalled.  */ |                            first signalled.  */ | ||||||
|                         env->exception_index = env->pending_vector; |                         cpu->exception_index = env->pending_vector; | ||||||
|                         do_interrupt_m68k_hardirq(env); |                         do_interrupt_m68k_hardirq(env); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
|                     } |                     } | ||||||
| @@ -584,7 +580,7 @@ int cpu_exec(CPUArchState *env) | |||||||
|                     } |                     } | ||||||
| #elif defined(TARGET_XTENSA) | #elif defined(TARGET_XTENSA) | ||||||
|                     if (interrupt_request & CPU_INTERRUPT_HARD) { |                     if (interrupt_request & CPU_INTERRUPT_HARD) { | ||||||
|                         env->exception_index = EXC_IRQ; |                         cpu->exception_index = EXC_IRQ; | ||||||
|                         cc->do_interrupt(cpu); |                         cc->do_interrupt(cpu); | ||||||
|                         next_tb = 0; |                         next_tb = 0; | ||||||
|                     } |                     } | ||||||
| @@ -600,8 +596,8 @@ int cpu_exec(CPUArchState *env) | |||||||
|                 } |                 } | ||||||
|                 if (unlikely(cpu->exit_request)) { |                 if (unlikely(cpu->exit_request)) { | ||||||
|                     cpu->exit_request = 0; |                     cpu->exit_request = 0; | ||||||
|                     env->exception_index = EXCP_INTERRUPT; |                     cpu->exception_index = EXCP_INTERRUPT; | ||||||
|                     cpu_loop_exit(env); |                     cpu_loop_exit(cpu); | ||||||
|                 } |                 } | ||||||
|                 spin_lock(&tcg_ctx.tb_ctx.tb_lock); |                 spin_lock(&tcg_ctx.tb_ctx.tb_lock); | ||||||
|                 tb = tb_find_fast(env); |                 tb = tb_find_fast(env); | ||||||
| @@ -654,25 +650,25 @@ int cpu_exec(CPUArchState *env) | |||||||
|                         /* Instruction counter expired.  */ |                         /* Instruction counter expired.  */ | ||||||
|                         int insns_left; |                         int insns_left; | ||||||
|                         tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK); |                         tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK); | ||||||
|                         insns_left = env->icount_decr.u32; |                         insns_left = cpu->icount_decr.u32; | ||||||
|                         if (env->icount_extra && insns_left >= 0) { |                         if (cpu->icount_extra && insns_left >= 0) { | ||||||
|                             /* Refill decrementer and continue execution.  */ |                             /* Refill decrementer and continue execution.  */ | ||||||
|                             env->icount_extra += insns_left; |                             cpu->icount_extra += insns_left; | ||||||
|                             if (env->icount_extra > 0xffff) { |                             if (cpu->icount_extra > 0xffff) { | ||||||
|                                 insns_left = 0xffff; |                                 insns_left = 0xffff; | ||||||
|                             } else { |                             } else { | ||||||
|                                 insns_left = env->icount_extra; |                                 insns_left = cpu->icount_extra; | ||||||
|                             } |                             } | ||||||
|                             env->icount_extra -= insns_left; |                             cpu->icount_extra -= insns_left; | ||||||
|                             env->icount_decr.u16.low = insns_left; |                             cpu->icount_decr.u16.low = insns_left; | ||||||
|                         } else { |                         } else { | ||||||
|                             if (insns_left > 0) { |                             if (insns_left > 0) { | ||||||
|                                 /* Execute remaining instructions.  */ |                                 /* Execute remaining instructions.  */ | ||||||
|                                 cpu_exec_nocache(env, insns_left, tb); |                                 cpu_exec_nocache(env, insns_left, tb); | ||||||
|                             } |                             } | ||||||
|                             env->exception_index = EXCP_INTERRUPT; |                             cpu->exception_index = EXCP_INTERRUPT; | ||||||
|                             next_tb = 0; |                             next_tb = 0; | ||||||
|                             cpu_loop_exit(env); |                             cpu_loop_exit(cpu); | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								cpus.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								cpus.c
									
									
									
									
									
								
							| @@ -76,7 +76,7 @@ static bool cpu_thread_is_idle(CPUState *cpu) | |||||||
|     if (cpu_is_stopped(cpu)) { |     if (cpu_is_stopped(cpu)) { | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|     if (!cpu->halted || qemu_cpu_has_work(cpu) || |     if (!cpu->halted || cpu_has_work(cpu) || | ||||||
|         kvm_halt_in_kernel()) { |         kvm_halt_in_kernel()) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| @@ -139,11 +139,10 @@ static int64_t cpu_get_icount_locked(void) | |||||||
|  |  | ||||||
|     icount = qemu_icount; |     icount = qemu_icount; | ||||||
|     if (cpu) { |     if (cpu) { | ||||||
|         CPUArchState *env = cpu->env_ptr; |         if (!cpu_can_do_io(cpu)) { | ||||||
|         if (!can_do_io(env)) { |  | ||||||
|             fprintf(stderr, "Bad clock read\n"); |             fprintf(stderr, "Bad clock read\n"); | ||||||
|         } |         } | ||||||
|         icount -= (env->icount_decr.u16.low + env->icount_extra); |         icount -= (cpu->icount_decr.u16.low + cpu->icount_extra); | ||||||
|     } |     } | ||||||
|     return qemu_icount_bias + (icount << icount_time_shift); |     return qemu_icount_bias + (icount << icount_time_shift); | ||||||
| } | } | ||||||
| @@ -1236,6 +1235,7 @@ int vm_stop_force_state(RunState state) | |||||||
|  |  | ||||||
| static int tcg_cpu_exec(CPUArchState *env) | static int tcg_cpu_exec(CPUArchState *env) | ||||||
| { | { | ||||||
|  |     CPUState *cpu = ENV_GET_CPU(env); | ||||||
|     int ret; |     int ret; | ||||||
| #ifdef CONFIG_PROFILER | #ifdef CONFIG_PROFILER | ||||||
|     int64_t ti; |     int64_t ti; | ||||||
| @@ -1248,9 +1248,9 @@ static int tcg_cpu_exec(CPUArchState *env) | |||||||
|         int64_t count; |         int64_t count; | ||||||
|         int64_t deadline; |         int64_t deadline; | ||||||
|         int decr; |         int decr; | ||||||
|         qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); |         qemu_icount -= (cpu->icount_decr.u16.low + cpu->icount_extra); | ||||||
|         env->icount_decr.u16.low = 0; |         cpu->icount_decr.u16.low = 0; | ||||||
|         env->icount_extra = 0; |         cpu->icount_extra = 0; | ||||||
|         deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); |         deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); | ||||||
|  |  | ||||||
|         /* Maintain prior (possibly buggy) behaviour where if no deadline |         /* Maintain prior (possibly buggy) behaviour where if no deadline | ||||||
| @@ -1266,8 +1266,8 @@ static int tcg_cpu_exec(CPUArchState *env) | |||||||
|         qemu_icount += count; |         qemu_icount += count; | ||||||
|         decr = (count > 0xffff) ? 0xffff : count; |         decr = (count > 0xffff) ? 0xffff : count; | ||||||
|         count -= decr; |         count -= decr; | ||||||
|         env->icount_decr.u16.low = decr; |         cpu->icount_decr.u16.low = decr; | ||||||
|         env->icount_extra = count; |         cpu->icount_extra = count; | ||||||
|     } |     } | ||||||
|     ret = cpu_exec(env); |     ret = cpu_exec(env); | ||||||
| #ifdef CONFIG_PROFILER | #ifdef CONFIG_PROFILER | ||||||
| @@ -1276,10 +1276,9 @@ static int tcg_cpu_exec(CPUArchState *env) | |||||||
|     if (use_icount) { |     if (use_icount) { | ||||||
|         /* Fold pending instructions back into the |         /* Fold pending instructions back into the | ||||||
|            instruction counter, and clear the interrupt flag.  */ |            instruction counter, and clear the interrupt flag.  */ | ||||||
|         qemu_icount -= (env->icount_decr.u16.low |         qemu_icount -= (cpu->icount_decr.u16.low + cpu->icount_extra); | ||||||
|                         + env->icount_extra); |         cpu->icount_decr.u32 = 0; | ||||||
|         env->icount_decr.u32 = 0; |         cpu->icount_extra = 0; | ||||||
|         env->icount_extra = 0; |  | ||||||
|     } |     } | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								cputlb.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								cputlb.c
									
									
									
									
									
								
							| @@ -46,9 +46,9 @@ int tlb_flush_count; | |||||||
|  * entries from the TLB at any time, so flushing more entries than |  * entries from the TLB at any time, so flushing more entries than | ||||||
|  * required is only an efficiency issue, not a correctness issue. |  * required is only an efficiency issue, not a correctness issue. | ||||||
|  */ |  */ | ||||||
| void tlb_flush(CPUArchState *env, int flush_global) | void tlb_flush(CPUState *cpu, int flush_global) | ||||||
| { | { | ||||||
|     CPUState *cpu = ENV_GET_CPU(env); |     CPUArchState *env = cpu->env_ptr; | ||||||
|  |  | ||||||
| #if defined(DEBUG_TLB) | #if defined(DEBUG_TLB) | ||||||
|     printf("tlb_flush:\n"); |     printf("tlb_flush:\n"); | ||||||
| @@ -58,7 +58,7 @@ void tlb_flush(CPUArchState *env, int flush_global) | |||||||
|     cpu->current_tb = NULL; |     cpu->current_tb = NULL; | ||||||
|  |  | ||||||
|     memset(env->tlb_table, -1, sizeof(env->tlb_table)); |     memset(env->tlb_table, -1, sizeof(env->tlb_table)); | ||||||
|     memset(env->tb_jmp_cache, 0, sizeof(env->tb_jmp_cache)); |     memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache)); | ||||||
|  |  | ||||||
|     env->tlb_flush_addr = -1; |     env->tlb_flush_addr = -1; | ||||||
|     env->tlb_flush_mask = 0; |     env->tlb_flush_mask = 0; | ||||||
| @@ -77,9 +77,9 @@ static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void tlb_flush_page(CPUArchState *env, target_ulong addr) | void tlb_flush_page(CPUState *cpu, target_ulong addr) | ||||||
| { | { | ||||||
|     CPUState *cpu = ENV_GET_CPU(env); |     CPUArchState *env = cpu->env_ptr; | ||||||
|     int i; |     int i; | ||||||
|     int mmu_idx; |     int mmu_idx; | ||||||
|  |  | ||||||
| @@ -93,7 +93,7 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr) | |||||||
|                TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", |                TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", | ||||||
|                env->tlb_flush_addr, env->tlb_flush_mask); |                env->tlb_flush_addr, env->tlb_flush_mask); | ||||||
| #endif | #endif | ||||||
|         tlb_flush(env, 1); |         tlb_flush(cpu, 1); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     /* must reset current TB so that interrupts cannot modify the |     /* must reset current TB so that interrupts cannot modify the | ||||||
| @@ -106,7 +106,7 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr) | |||||||
|         tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr); |         tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     tb_flush_jmp_cache(env, addr); |     tb_flush_jmp_cache(cpu, addr); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* update the TLBs so that writes to code in the virtual page 'addr' | /* update the TLBs so that writes to code in the virtual page 'addr' | ||||||
| @@ -119,7 +119,7 @@ void tlb_protect_code(ram_addr_t ram_addr) | |||||||
|  |  | ||||||
| /* update the TLB so that writes in physical page 'phys_addr' are no longer | /* update the TLB so that writes in physical page 'phys_addr' are no longer | ||||||
|    tested for self modifying code */ |    tested for self modifying code */ | ||||||
| void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr, | void tlb_unprotect_code_phys(CPUState *cpu, ram_addr_t ram_addr, | ||||||
|                              target_ulong vaddr) |                              target_ulong vaddr) | ||||||
| { | { | ||||||
|     cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE); |     cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE); | ||||||
| @@ -221,10 +221,11 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr, | |||||||
| /* Add a new TLB entry. At most one entry for a given virtual address | /* Add a new TLB entry. At most one entry for a given virtual address | ||||||
|    is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the |    is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the | ||||||
|    supplied size is only used by tlb_flush_page.  */ |    supplied size is only used by tlb_flush_page.  */ | ||||||
| void tlb_set_page(CPUArchState *env, target_ulong vaddr, | void tlb_set_page(CPUState *cpu, target_ulong vaddr, | ||||||
|                   hwaddr paddr, int prot, |                   hwaddr paddr, int prot, | ||||||
|                   int mmu_idx, target_ulong size) |                   int mmu_idx, target_ulong size) | ||||||
| { | { | ||||||
|  |     CPUArchState *env = cpu->env_ptr; | ||||||
|     MemoryRegionSection *section; |     MemoryRegionSection *section; | ||||||
|     unsigned int index; |     unsigned int index; | ||||||
|     target_ulong address; |     target_ulong address; | ||||||
| @@ -232,7 +233,6 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, | |||||||
|     uintptr_t addend; |     uintptr_t addend; | ||||||
|     CPUTLBEntry *te; |     CPUTLBEntry *te; | ||||||
|     hwaddr iotlb, xlat, sz; |     hwaddr iotlb, xlat, sz; | ||||||
|     CPUState *cpu = ENV_GET_CPU(env); |  | ||||||
|  |  | ||||||
|     assert(size >= TARGET_PAGE_SIZE); |     assert(size >= TARGET_PAGE_SIZE); | ||||||
|     if (size != TARGET_PAGE_SIZE) { |     if (size != TARGET_PAGE_SIZE) { | ||||||
| @@ -261,7 +261,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     code_address = address; |     code_address = address; | ||||||
|     iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, xlat, |     iotlb = memory_region_section_get_iotlb(cpu, section, vaddr, paddr, xlat, | ||||||
|                                             prot, &address); |                                             prot, &address); | ||||||
|  |  | ||||||
|     index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |     index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | ||||||
| @@ -322,7 +322,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) | |||||||
|         if (cc->do_unassigned_access) { |         if (cc->do_unassigned_access) { | ||||||
|             cc->do_unassigned_access(cpu, addr, false, true, 0, 4); |             cc->do_unassigned_access(cpu, addr, false, true, 0, 4); | ||||||
|         } else { |         } else { | ||||||
|             cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" |             cpu_abort(cpu, "Trying to execute code outside RAM or ROM at 0x" | ||||||
|                       TARGET_FMT_lx "\n", addr); |                       TARGET_FMT_lx "\n", addr); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -33,12 +33,14 @@ DriveInfo *add_init_drive(const char *optstr) | |||||||
| { | { | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
|     QemuOpts *opts; |     QemuOpts *opts; | ||||||
|  |     MachineClass *mc; | ||||||
|  |  | ||||||
|     opts = drive_def(optstr); |     opts = drive_def(optstr); | ||||||
|     if (!opts) |     if (!opts) | ||||||
|         return NULL; |         return NULL; | ||||||
|  |  | ||||||
|     dinfo = drive_init(opts, current_machine->block_default_type); |     mc = MACHINE_GET_CLASS(current_machine); | ||||||
|  |     dinfo = drive_init(opts, mc->qemu_machine->block_default_type); | ||||||
|     if (!dinfo) { |     if (!dinfo) { | ||||||
|         qemu_opts_del(opts); |         qemu_opts_del(opts); | ||||||
|         return NULL; |         return NULL; | ||||||
|   | |||||||
| @@ -123,11 +123,12 @@ And it looks like this on the wire: | |||||||
|  |  | ||||||
| Flat union types avoid the nesting on the wire. They are used whenever a | Flat union types avoid the nesting on the wire. They are used whenever a | ||||||
| specific field of the base type is declared as the discriminator ('type' is | specific field of the base type is declared as the discriminator ('type' is | ||||||
| then no longer generated). The discriminator must always be a string field. | then no longer generated). The discriminator must be of enumeration type. | ||||||
| The above example can then be modified as follows: | The above example can then be modified as follows: | ||||||
|  |  | ||||||
|  |  { 'enum': 'BlockdevDriver', 'data': [ 'raw', 'qcow2' ] } | ||||||
|  { 'type': 'BlockdevCommonOptions', |  { 'type': 'BlockdevCommonOptions', | ||||||
|    'data': { 'driver': 'str', 'readonly': 'bool' } } |    'data': { 'driver': 'BlockdevDriver', 'readonly': 'bool' } } | ||||||
|  { 'union': 'BlockdevOptions', |  { 'union': 'BlockdevOptions', | ||||||
|    'base': 'BlockdevCommonOptions', |    'base': 'BlockdevCommonOptions', | ||||||
|    'discriminator': 'driver', |    'discriminator': 'driver', | ||||||
|   | |||||||
| @@ -11,99 +11,92 @@ | |||||||
| ; (Com+Lpt)" from the list.  Click "Have a disk".  Select this file. | ; (Com+Lpt)" from the list.  Click "Have a disk".  Select this file. | ||||||
| ; Procedure may vary a bit depending on the windows version. | ; Procedure may vary a bit depending on the windows version. | ||||||
|  |  | ||||||
| ; FIXME: This file covers the single port version only. | ; This file covers all options: pci-serial, pci-serial-2x, pci-serial-4x | ||||||
|  | ; for both 32 and 64 bit platforms. | ||||||
|  |  | ||||||
| [Version] | [Version] | ||||||
| Signature="$CHICAGO$" | Signature="$Windows NT$" | ||||||
| Class=Ports | Class=MultiFunction | ||||||
| ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} | ClassGUID={4d36e971-e325-11ce-bfc1-08002be10318} | ||||||
| Provider=%QEMU% | Provider=%QEMU% | ||||||
| DriverVer=09/24/2012,1.3.0 | DriverVer=12/29/2013,1.3.0 | ||||||
|  | [ControlFlags] | ||||||
| [SourceDisksNames] | ExcludeFromSelect=* | ||||||
| 3426=windows cd |  | ||||||
|  |  | ||||||
| [SourceDisksFiles] |  | ||||||
| serial.sys 		= 3426 |  | ||||||
| serenum.sys 		= 3426 |  | ||||||
|  |  | ||||||
| [DestinationDirs] |  | ||||||
| DefaultDestDir  = 11        ;LDID_SYS |  | ||||||
| ComPort.NT.Copy = 12        ;DIRID_DRIVERS |  | ||||||
| SerialEnumerator.NT.Copy=12 ;DIRID_DRIVERS |  | ||||||
|  |  | ||||||
| ; Drivers |  | ||||||
| ;---------------------------------------------------------- |  | ||||||
| [Manufacturer] | [Manufacturer] | ||||||
| %QEMU%=QEMU,NTx86 | %QEMU%=QEMU,NTx86,NTAMD64 | ||||||
|  |  | ||||||
| [QEMU.NTx86] | [QEMU.NTx86] | ||||||
| %QEMU-PCI_SERIAL.DeviceDesc% = ComPort, "PCI\VEN_1b36&DEV_0002&CC_0700" | %QEMU-PCI_SERIAL_1_PORT%=ComPort_inst1, PCI\VEN_1B36&DEV_0002 | ||||||
|  | %QEMU-PCI_SERIAL_2_PORT%=ComPort_inst2, PCI\VEN_1B36&DEV_0003 | ||||||
|  | %QEMU-PCI_SERIAL_4_PORT%=ComPort_inst4, PCI\VEN_1B36&DEV_0004 | ||||||
|  |  | ||||||
| ; COM sections | [QEMU.NTAMD64] | ||||||
| ;---------------------------------------------------------- | %QEMU-PCI_SERIAL_1_PORT%=ComPort_inst1, PCI\VEN_1B36&DEV_0002 | ||||||
| [ComPort.AddReg] | %QEMU-PCI_SERIAL_2_PORT%=ComPort_inst2, PCI\VEN_1B36&DEV_0003 | ||||||
| HKR,,PortSubClass,1,01 | %QEMU-PCI_SERIAL_4_PORT%=ComPort_inst4, PCI\VEN_1B36&DEV_0004 | ||||||
|  |  | ||||||
| [ComPort.NT] | [ComPort_inst1] | ||||||
| AddReg=ComPort.AddReg, ComPort.NT.AddReg | Include=mf.inf | ||||||
| LogConfig=caa | Needs=MFINSTALL.mf | ||||||
| SyssetupPnPFlags = 1 |  | ||||||
|  |  | ||||||
| [ComPort.NT.HW] | [ComPort_inst2] | ||||||
| AddReg=ComPort.NT.HW.AddReg | Include=mf.inf | ||||||
|  | Needs=MFINSTALL.mf | ||||||
|  |  | ||||||
| [ComPort.NT.AddReg] | [ComPort_inst4] | ||||||
| HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" | Include=mf.inf | ||||||
|  | Needs=MFINSTALL.mf | ||||||
|  |  | ||||||
| [ComPort.NT.HW.AddReg] | [ComPort_inst1.HW] | ||||||
| HKR,,"UpperFilters",0x00010000,"serenum" | AddReg=ComPort_inst1.RegHW | ||||||
|  |  | ||||||
| ;-------------- Service installation | [ComPort_inst2.HW] | ||||||
| ; Port Driver (function driver for this device) | AddReg=ComPort_inst2.RegHW | ||||||
| [ComPort.NT.Services] |  | ||||||
| AddService = Serial, 0x00000002, Serial_Service_Inst, Serial_EventLog_Inst |  | ||||||
| AddService = Serenum,,Serenum_Service_Inst |  | ||||||
|  |  | ||||||
| ; -------------- Serial Port Driver install sections | [ComPort_inst4.HW] | ||||||
| [Serial_Service_Inst] | AddReg=ComPort_inst4.RegHW | ||||||
| DisplayName    = %Serial.SVCDESC% |  | ||||||
| ServiceType    = 1               ; SERVICE_KERNEL_DRIVER |  | ||||||
| StartType      = 1               ; SERVICE_SYSTEM_START (this driver may do detection) |  | ||||||
| ErrorControl   = 0               ; SERVICE_ERROR_IGNORE |  | ||||||
| ServiceBinary  = %12%\serial.sys |  | ||||||
| LoadOrderGroup = Extended base |  | ||||||
|  |  | ||||||
| ; -------------- Serenum Driver install section | [ComPort_inst1.Services] | ||||||
| [Serenum_Service_Inst] | Include=mf.inf | ||||||
| DisplayName    = %Serenum.SVCDESC% | Needs=MFINSTALL.mf.Services | ||||||
| ServiceType    = 1               ; SERVICE_KERNEL_DRIVER |  | ||||||
| StartType      = 3               ; SERVICE_DEMAND_START |  | ||||||
| ErrorControl   = 1               ; SERVICE_ERROR_NORMAL |  | ||||||
| ServiceBinary  = %12%\serenum.sys |  | ||||||
| LoadOrderGroup = PNP Filter |  | ||||||
|  |  | ||||||
| [Serial_EventLog_Inst] | [ComPort_inst2.Services] | ||||||
| AddReg = Serial_EventLog_AddReg | Include=mf.inf | ||||||
|  | Needs=MFINSTALL.mf.Services | ||||||
|  |  | ||||||
| [Serial_EventLog_AddReg] | [ComPort_inst4.Services] | ||||||
| HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\serial.sys" | Include=mf.inf | ||||||
| HKR,,TypesSupported,0x00010001,7 | Needs=MFINSTALL.mf.Services | ||||||
|  |  | ||||||
| ; The following sections are COM port resource configs. | [ComPort_inst1.RegHW] | ||||||
| ; Section name format means: | HKR,Child0000,HardwareID,,*PNP0501 | ||||||
| ; Char 1 = c (COM port) | HKR,Child0000,VaryingResourceMap,1,00, 00,00,00,00, 08,00,00,00 | ||||||
| ; Char 2 = I/O config: 1 (3f8), 2 (2f8), 3 (3e8), 4 (2e8), a (any) | HKR,Child0000,ResourceMap,1,02 | ||||||
| ; Char 3 = IRQ config: #, a (any) |  | ||||||
|  |  | ||||||
| [caa]                   ; Any base, any IRQ | [ComPort_inst2.RegHW] | ||||||
| ConfigPriority=HARDRECONFIG | HKR,Child0000,HardwareID,,*PNP0501 | ||||||
| IOConfig=8@100-ffff%fff8(3ff::) | HKR,Child0000,VaryingResourceMap,1,00, 00,00,00,00, 08,00,00,00 | ||||||
| IRQConfig=S:3,4,5,7,9,10,11,12,14,15 | HKR,Child0000,ResourceMap,1,02 | ||||||
|  | HKR,Child0001,HardwareID,,*PNP0501 | ||||||
|  | HKR,Child0001,VaryingResourceMap,1,00, 08,00,00,00, 08,00,00,00 | ||||||
|  | HKR,Child0001,ResourceMap,1,02 | ||||||
|  |  | ||||||
|  | [ComPort_inst4.RegHW] | ||||||
|  | HKR,Child0000,HardwareID,,*PNP0501 | ||||||
|  | HKR,Child0000,VaryingResourceMap,1,00, 00,00,00,00, 08,00,00,00 | ||||||
|  | HKR,Child0000,ResourceMap,1,02 | ||||||
|  | HKR,Child0001,HardwareID,,*PNP0501 | ||||||
|  | HKR,Child0001,VaryingResourceMap,1,00, 08,00,00,00, 08,00,00,00 | ||||||
|  | HKR,Child0001,ResourceMap,1,02 | ||||||
|  | HKR,Child0002,HardwareID,,*PNP0501 | ||||||
|  | HKR,Child0002,VaryingResourceMap,1,00, 10,00,00,00, 08,00,00,00 | ||||||
|  | HKR,Child0002,ResourceMap,1,02 | ||||||
|  | HKR,Child0003,HardwareID,,*PNP0501 | ||||||
|  | HKR,Child0003,VaryingResourceMap,1,00, 18,00,00,00, 08,00,00,00 | ||||||
|  | HKR,Child0003,ResourceMap,1,02 | ||||||
|  |  | ||||||
| [Strings] | [Strings] | ||||||
| QEMU="QEMU" | QEMU="QEMU" | ||||||
| QEMU-PCI_SERIAL.DeviceDesc="QEMU Serial PCI Card" | QEMU-PCI_SERIAL_1_PORT="1x QEMU PCI Serial Card" | ||||||
|  | QEMU-PCI_SERIAL_2_PORT="2x QEMU PCI Serial Card" | ||||||
| Serial.SVCDESC   = "Serial port driver" | QEMU-PCI_SERIAL_4_PORT="4x QEMU PCI Serial Card" | ||||||
| Serenum.SVCDESC = "Serenum Filter Driver" |  | ||||||
|   | |||||||
							
								
								
									
										118
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								exec.c
									
									
									
									
									
								
							| @@ -33,6 +33,7 @@ | |||||||
| #include "hw/xen/xen.h" | #include "hw/xen/xen.h" | ||||||
| #include "qemu/timer.h" | #include "qemu/timer.h" | ||||||
| #include "qemu/config-file.h" | #include "qemu/config-file.h" | ||||||
|  | #include "qemu/error-report.h" | ||||||
| #include "exec/memory.h" | #include "exec/memory.h" | ||||||
| #include "sysemu/dma.h" | #include "sysemu/dma.h" | ||||||
| #include "exec/address-spaces.h" | #include "exec/address-spaces.h" | ||||||
| @@ -484,8 +485,8 @@ void cpu_exec_init(CPUArchState *env) | |||||||
|     } |     } | ||||||
|     cpu->cpu_index = cpu_index; |     cpu->cpu_index = cpu_index; | ||||||
|     cpu->numa_node = 0; |     cpu->numa_node = 0; | ||||||
|     QTAILQ_INIT(&env->breakpoints); |     QTAILQ_INIT(&cpu->breakpoints); | ||||||
|     QTAILQ_INIT(&env->watchpoints); |     QTAILQ_INIT(&cpu->watchpoints); | ||||||
| #ifndef CONFIG_USER_ONLY | #ifndef CONFIG_USER_ONLY | ||||||
|     cpu->as = &address_space_memory; |     cpu->as = &address_space_memory; | ||||||
|     cpu->thread_id = qemu_get_thread_id(); |     cpu->thread_id = qemu_get_thread_id(); | ||||||
| @@ -527,29 +528,29 @@ static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) | |||||||
| #endif /* TARGET_HAS_ICE */ | #endif /* TARGET_HAS_ICE */ | ||||||
|  |  | ||||||
| #if defined(CONFIG_USER_ONLY) | #if defined(CONFIG_USER_ONLY) | ||||||
| void cpu_watchpoint_remove_all(CPUArchState *env, int mask) | void cpu_watchpoint_remove_all(CPUState *cpu, int mask) | ||||||
|  |  | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len, | int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, | ||||||
|                           int flags, CPUWatchpoint **watchpoint) |                           int flags, CPUWatchpoint **watchpoint) | ||||||
| { | { | ||||||
|     return -ENOSYS; |     return -ENOSYS; | ||||||
| } | } | ||||||
| #else | #else | ||||||
| /* Add a watchpoint.  */ | /* Add a watchpoint.  */ | ||||||
| int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len, | int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, | ||||||
|                           int flags, CPUWatchpoint **watchpoint) |                           int flags, CPUWatchpoint **watchpoint) | ||||||
| { | { | ||||||
|     target_ulong len_mask = ~(len - 1); |     vaddr len_mask = ~(len - 1); | ||||||
|     CPUWatchpoint *wp; |     CPUWatchpoint *wp; | ||||||
|  |  | ||||||
|     /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */ |     /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */ | ||||||
|     if ((len & (len - 1)) || (addr & ~len_mask) || |     if ((len & (len - 1)) || (addr & ~len_mask) || | ||||||
|             len == 0 || len > TARGET_PAGE_SIZE) { |             len == 0 || len > TARGET_PAGE_SIZE) { | ||||||
|         fprintf(stderr, "qemu: tried to set invalid watchpoint at " |         error_report("tried to set invalid watchpoint at %" | ||||||
|                 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len); |                      VADDR_PRIx ", len=%" VADDR_PRIu, addr, len); | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
|     } |     } | ||||||
|     wp = g_malloc(sizeof(*wp)); |     wp = g_malloc(sizeof(*wp)); | ||||||
| @@ -559,12 +560,13 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len | |||||||
|     wp->flags = flags; |     wp->flags = flags; | ||||||
|  |  | ||||||
|     /* keep all GDB-injected watchpoints in front */ |     /* keep all GDB-injected watchpoints in front */ | ||||||
|     if (flags & BP_GDB) |     if (flags & BP_GDB) { | ||||||
|         QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry); |         QTAILQ_INSERT_HEAD(&cpu->watchpoints, wp, entry); | ||||||
|     else |     } else { | ||||||
|         QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry); |         QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     tlb_flush_page(env, addr); |     tlb_flush_page(cpu, addr); | ||||||
|  |  | ||||||
|     if (watchpoint) |     if (watchpoint) | ||||||
|         *watchpoint = wp; |         *watchpoint = wp; | ||||||
| @@ -572,16 +574,16 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove a specific watchpoint.  */ | /* Remove a specific watchpoint.  */ | ||||||
| int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len, | int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, vaddr len, | ||||||
|                           int flags) |                           int flags) | ||||||
| { | { | ||||||
|     target_ulong len_mask = ~(len - 1); |     vaddr len_mask = ~(len - 1); | ||||||
|     CPUWatchpoint *wp; |     CPUWatchpoint *wp; | ||||||
|  |  | ||||||
|     QTAILQ_FOREACH(wp, &env->watchpoints, entry) { |     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { | ||||||
|         if (addr == wp->vaddr && len_mask == wp->len_mask |         if (addr == wp->vaddr && len_mask == wp->len_mask | ||||||
|                 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { |                 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { | ||||||
|             cpu_watchpoint_remove_by_ref(env, wp); |             cpu_watchpoint_remove_by_ref(cpu, wp); | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -589,29 +591,30 @@ int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove a specific watchpoint by reference.  */ | /* Remove a specific watchpoint by reference.  */ | ||||||
| void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint) | void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint) | ||||||
| { | { | ||||||
|     QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry); |     QTAILQ_REMOVE(&cpu->watchpoints, watchpoint, entry); | ||||||
|  |  | ||||||
|     tlb_flush_page(env, watchpoint->vaddr); |     tlb_flush_page(cpu, watchpoint->vaddr); | ||||||
|  |  | ||||||
|     g_free(watchpoint); |     g_free(watchpoint); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove all matching watchpoints.  */ | /* Remove all matching watchpoints.  */ | ||||||
| void cpu_watchpoint_remove_all(CPUArchState *env, int mask) | void cpu_watchpoint_remove_all(CPUState *cpu, int mask) | ||||||
| { | { | ||||||
|     CPUWatchpoint *wp, *next; |     CPUWatchpoint *wp, *next; | ||||||
|  |  | ||||||
|     QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) { |     QTAILQ_FOREACH_SAFE(wp, &cpu->watchpoints, entry, next) { | ||||||
|         if (wp->flags & mask) |         if (wp->flags & mask) { | ||||||
|             cpu_watchpoint_remove_by_ref(env, wp); |             cpu_watchpoint_remove_by_ref(cpu, wp); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* Add a breakpoint.  */ | /* Add a breakpoint.  */ | ||||||
| int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags, | int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, | ||||||
|                           CPUBreakpoint **breakpoint) |                           CPUBreakpoint **breakpoint) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) | #if defined(TARGET_HAS_ICE) | ||||||
| @@ -624,12 +627,12 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags, | |||||||
|  |  | ||||||
|     /* keep all GDB-injected breakpoints in front */ |     /* keep all GDB-injected breakpoints in front */ | ||||||
|     if (flags & BP_GDB) { |     if (flags & BP_GDB) { | ||||||
|         QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry); |         QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry); | ||||||
|     } else { |     } else { | ||||||
|         QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry); |         QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     breakpoint_invalidate(ENV_GET_CPU(env), pc); |     breakpoint_invalidate(cpu, pc); | ||||||
|  |  | ||||||
|     if (breakpoint) { |     if (breakpoint) { | ||||||
|         *breakpoint = bp; |         *breakpoint = bp; | ||||||
| @@ -641,14 +644,14 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags, | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove a specific breakpoint.  */ | /* Remove a specific breakpoint.  */ | ||||||
| int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags) | int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) | #if defined(TARGET_HAS_ICE) | ||||||
|     CPUBreakpoint *bp; |     CPUBreakpoint *bp; | ||||||
|  |  | ||||||
|     QTAILQ_FOREACH(bp, &env->breakpoints, entry) { |     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { | ||||||
|         if (bp->pc == pc && bp->flags == flags) { |         if (bp->pc == pc && bp->flags == flags) { | ||||||
|             cpu_breakpoint_remove_by_ref(env, bp); |             cpu_breakpoint_remove_by_ref(cpu, bp); | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -659,26 +662,27 @@ int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove a specific breakpoint by reference.  */ | /* Remove a specific breakpoint by reference.  */ | ||||||
| void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint) | void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) | #if defined(TARGET_HAS_ICE) | ||||||
|     QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry); |     QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry); | ||||||
|  |  | ||||||
|     breakpoint_invalidate(ENV_GET_CPU(env), breakpoint->pc); |     breakpoint_invalidate(cpu, breakpoint->pc); | ||||||
|  |  | ||||||
|     g_free(breakpoint); |     g_free(breakpoint); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove all matching breakpoints. */ | /* Remove all matching breakpoints. */ | ||||||
| void cpu_breakpoint_remove_all(CPUArchState *env, int mask) | void cpu_breakpoint_remove_all(CPUState *cpu, int mask) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) | #if defined(TARGET_HAS_ICE) | ||||||
|     CPUBreakpoint *bp, *next; |     CPUBreakpoint *bp, *next; | ||||||
|  |  | ||||||
|     QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) { |     QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) { | ||||||
|         if (bp->flags & mask) |         if (bp->flags & mask) { | ||||||
|             cpu_breakpoint_remove_by_ref(env, bp); |             cpu_breakpoint_remove_by_ref(cpu, bp); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| @@ -702,9 +706,8 @@ void cpu_single_step(CPUState *cpu, int enabled) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| void cpu_abort(CPUArchState *env, const char *fmt, ...) | void cpu_abort(CPUState *cpu, const char *fmt, ...) | ||||||
| { | { | ||||||
|     CPUState *cpu = ENV_GET_CPU(env); |  | ||||||
|     va_list ap; |     va_list ap; | ||||||
|     va_list ap2; |     va_list ap2; | ||||||
|  |  | ||||||
| @@ -792,7 +795,7 @@ static void cpu_physical_memory_set_dirty_tracking(bool enable) | |||||||
|     in_migration = enable; |     in_migration = enable; | ||||||
| } | } | ||||||
|  |  | ||||||
| hwaddr memory_region_section_get_iotlb(CPUArchState *env, | hwaddr memory_region_section_get_iotlb(CPUState *cpu, | ||||||
|                                        MemoryRegionSection *section, |                                        MemoryRegionSection *section, | ||||||
|                                        target_ulong vaddr, |                                        target_ulong vaddr, | ||||||
|                                        hwaddr paddr, hwaddr xlat, |                                        hwaddr paddr, hwaddr xlat, | ||||||
| @@ -818,7 +821,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, | |||||||
|  |  | ||||||
|     /* Make accesses to pages with watchpoints go via the |     /* Make accesses to pages with watchpoints go via the | ||||||
|        watchpoint trap routines.  */ |        watchpoint trap routines.  */ | ||||||
|     QTAILQ_FOREACH(wp, &env->watchpoints, entry) { |     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { | ||||||
|         if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { |         if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { | ||||||
|             /* Avoid trapping reads of pages with a write breakpoint. */ |             /* Avoid trapping reads of pages with a write breakpoint. */ | ||||||
|             if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) { |             if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) { | ||||||
| @@ -1553,7 +1556,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr, | |||||||
|        flushed */ |        flushed */ | ||||||
|     if (!cpu_physical_memory_is_clean(ram_addr)) { |     if (!cpu_physical_memory_is_clean(ram_addr)) { | ||||||
|         CPUArchState *env = current_cpu->env_ptr; |         CPUArchState *env = current_cpu->env_ptr; | ||||||
|         tlb_set_dirty(env, env->mem_io_vaddr); |         tlb_set_dirty(env, current_cpu->mem_io_vaddr); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1572,34 +1575,35 @@ static const MemoryRegionOps notdirty_mem_ops = { | |||||||
| /* Generate a debug exception if a watchpoint has been hit.  */ | /* Generate a debug exception if a watchpoint has been hit.  */ | ||||||
| static void check_watchpoint(int offset, int len_mask, int flags) | static void check_watchpoint(int offset, int len_mask, int flags) | ||||||
| { | { | ||||||
|     CPUArchState *env = current_cpu->env_ptr; |     CPUState *cpu = current_cpu; | ||||||
|  |     CPUArchState *env = cpu->env_ptr; | ||||||
|     target_ulong pc, cs_base; |     target_ulong pc, cs_base; | ||||||
|     target_ulong vaddr; |     target_ulong vaddr; | ||||||
|     CPUWatchpoint *wp; |     CPUWatchpoint *wp; | ||||||
|     int cpu_flags; |     int cpu_flags; | ||||||
|  |  | ||||||
|     if (env->watchpoint_hit) { |     if (cpu->watchpoint_hit) { | ||||||
|         /* We re-entered the check after replacing the TB. Now raise |         /* We re-entered the check after replacing the TB. Now raise | ||||||
|          * the debug interrupt so that is will trigger after the |          * the debug interrupt so that is will trigger after the | ||||||
|          * current instruction. */ |          * current instruction. */ | ||||||
|         cpu_interrupt(ENV_GET_CPU(env), CPU_INTERRUPT_DEBUG); |         cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset; |     vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset; | ||||||
|     QTAILQ_FOREACH(wp, &env->watchpoints, entry) { |     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { | ||||||
|         if ((vaddr == (wp->vaddr & len_mask) || |         if ((vaddr == (wp->vaddr & len_mask) || | ||||||
|              (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { |              (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { | ||||||
|             wp->flags |= BP_WATCHPOINT_HIT; |             wp->flags |= BP_WATCHPOINT_HIT; | ||||||
|             if (!env->watchpoint_hit) { |             if (!cpu->watchpoint_hit) { | ||||||
|                 env->watchpoint_hit = wp; |                 cpu->watchpoint_hit = wp; | ||||||
|                 tb_check_watchpoint(env); |                 tb_check_watchpoint(cpu); | ||||||
|                 if (wp->flags & BP_STOP_BEFORE_ACCESS) { |                 if (wp->flags & BP_STOP_BEFORE_ACCESS) { | ||||||
|                     env->exception_index = EXCP_DEBUG; |                     cpu->exception_index = EXCP_DEBUG; | ||||||
|                     cpu_loop_exit(env); |                     cpu_loop_exit(cpu); | ||||||
|                 } else { |                 } else { | ||||||
|                     cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags); |                     cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags); | ||||||
|                     tb_gen_code(env, pc, cs_base, cpu_flags, 1); |                     tb_gen_code(cpu, pc, cs_base, cpu_flags, 1); | ||||||
|                     cpu_resume_from_signal(env, NULL); |                     cpu_resume_from_signal(cpu, NULL); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
| @@ -1830,14 +1834,12 @@ static void tcg_commit(MemoryListener *listener) | |||||||
|        reset the modified entries */ |        reset the modified entries */ | ||||||
|     /* XXX: slow ! */ |     /* XXX: slow ! */ | ||||||
|     CPU_FOREACH(cpu) { |     CPU_FOREACH(cpu) { | ||||||
|         CPUArchState *env = cpu->env_ptr; |  | ||||||
|  |  | ||||||
|         /* FIXME: Disentangle the cpu.h circular files deps so we can |         /* FIXME: Disentangle the cpu.h circular files deps so we can | ||||||
|            directly get the right CPU from listener.  */ |            directly get the right CPU from listener.  */ | ||||||
|         if (cpu->tcg_as_listener != listener) { |         if (cpu->tcg_as_listener != listener) { | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         tlb_flush(env, 1); |         tlb_flush(cpu, 1); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								gdbstub.c
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								gdbstub.c
									
									
									
									
									
								
							| @@ -635,7 +635,6 @@ static const int xlat_gdb_type[] = { | |||||||
| static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) | static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) | ||||||
| { | { | ||||||
|     CPUState *cpu; |     CPUState *cpu; | ||||||
|     CPUArchState *env; |  | ||||||
|     int err = 0; |     int err = 0; | ||||||
|  |  | ||||||
|     if (kvm_enabled()) { |     if (kvm_enabled()) { | ||||||
| @@ -646,10 +645,10 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) | |||||||
|     case GDB_BREAKPOINT_SW: |     case GDB_BREAKPOINT_SW: | ||||||
|     case GDB_BREAKPOINT_HW: |     case GDB_BREAKPOINT_HW: | ||||||
|         CPU_FOREACH(cpu) { |         CPU_FOREACH(cpu) { | ||||||
|             env = cpu->env_ptr; |             err = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL); | ||||||
|             err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL); |             if (err) { | ||||||
|             if (err) |  | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         return err; |         return err; | ||||||
| #ifndef CONFIG_USER_ONLY | #ifndef CONFIG_USER_ONLY | ||||||
| @@ -657,8 +656,7 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) | |||||||
|     case GDB_WATCHPOINT_READ: |     case GDB_WATCHPOINT_READ: | ||||||
|     case GDB_WATCHPOINT_ACCESS: |     case GDB_WATCHPOINT_ACCESS: | ||||||
|         CPU_FOREACH(cpu) { |         CPU_FOREACH(cpu) { | ||||||
|             env = cpu->env_ptr; |             err = cpu_watchpoint_insert(cpu, addr, len, xlat_gdb_type[type], | ||||||
|             err = cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type], |  | ||||||
|                                         NULL); |                                         NULL); | ||||||
|             if (err) |             if (err) | ||||||
|                 break; |                 break; | ||||||
| @@ -673,7 +671,6 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) | |||||||
| static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) | static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) | ||||||
| { | { | ||||||
|     CPUState *cpu; |     CPUState *cpu; | ||||||
|     CPUArchState *env; |  | ||||||
|     int err = 0; |     int err = 0; | ||||||
|  |  | ||||||
|     if (kvm_enabled()) { |     if (kvm_enabled()) { | ||||||
| @@ -684,10 +681,10 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) | |||||||
|     case GDB_BREAKPOINT_SW: |     case GDB_BREAKPOINT_SW: | ||||||
|     case GDB_BREAKPOINT_HW: |     case GDB_BREAKPOINT_HW: | ||||||
|         CPU_FOREACH(cpu) { |         CPU_FOREACH(cpu) { | ||||||
|             env = cpu->env_ptr; |             err = cpu_breakpoint_remove(cpu, addr, BP_GDB); | ||||||
|             err = cpu_breakpoint_remove(env, addr, BP_GDB); |             if (err) { | ||||||
|             if (err) |  | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         return err; |         return err; | ||||||
| #ifndef CONFIG_USER_ONLY | #ifndef CONFIG_USER_ONLY | ||||||
| @@ -695,8 +692,7 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) | |||||||
|     case GDB_WATCHPOINT_READ: |     case GDB_WATCHPOINT_READ: | ||||||
|     case GDB_WATCHPOINT_ACCESS: |     case GDB_WATCHPOINT_ACCESS: | ||||||
|         CPU_FOREACH(cpu) { |         CPU_FOREACH(cpu) { | ||||||
|             env = cpu->env_ptr; |             err = cpu_watchpoint_remove(cpu, addr, len, xlat_gdb_type[type]); | ||||||
|             err = cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]); |  | ||||||
|             if (err) |             if (err) | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
| @@ -710,7 +706,6 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) | |||||||
| static void gdb_breakpoint_remove_all(void) | static void gdb_breakpoint_remove_all(void) | ||||||
| { | { | ||||||
|     CPUState *cpu; |     CPUState *cpu; | ||||||
|     CPUArchState *env; |  | ||||||
|  |  | ||||||
|     if (kvm_enabled()) { |     if (kvm_enabled()) { | ||||||
|         kvm_remove_all_breakpoints(gdbserver_state->c_cpu); |         kvm_remove_all_breakpoints(gdbserver_state->c_cpu); | ||||||
| @@ -718,10 +713,9 @@ static void gdb_breakpoint_remove_all(void) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     CPU_FOREACH(cpu) { |     CPU_FOREACH(cpu) { | ||||||
|         env = cpu->env_ptr; |         cpu_breakpoint_remove_all(cpu, BP_GDB); | ||||||
|         cpu_breakpoint_remove_all(env, BP_GDB); |  | ||||||
| #ifndef CONFIG_USER_ONLY | #ifndef CONFIG_USER_ONLY | ||||||
|         cpu_watchpoint_remove_all(env, BP_GDB); |         cpu_watchpoint_remove_all(cpu, BP_GDB); | ||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1086,8 +1080,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) | |||||||
|         } |         } | ||||||
| #ifdef CONFIG_USER_ONLY | #ifdef CONFIG_USER_ONLY | ||||||
|         else if (strncmp(p, "Offsets", 7) == 0) { |         else if (strncmp(p, "Offsets", 7) == 0) { | ||||||
|             CPUArchState *env = s->c_cpu->env_ptr; |             TaskState *ts = s->c_cpu->opaque; | ||||||
|             TaskState *ts = env->opaque; |  | ||||||
|  |  | ||||||
|             snprintf(buf, sizeof(buf), |             snprintf(buf, sizeof(buf), | ||||||
|                      "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx |                      "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx | ||||||
| @@ -1205,8 +1198,8 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) | |||||||
|     } |     } | ||||||
|     switch (state) { |     switch (state) { | ||||||
|     case RUN_STATE_DEBUG: |     case RUN_STATE_DEBUG: | ||||||
|         if (env->watchpoint_hit) { |         if (cpu->watchpoint_hit) { | ||||||
|             switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) { |             switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { | ||||||
|             case BP_MEM_READ: |             case BP_MEM_READ: | ||||||
|                 type = "r"; |                 type = "r"; | ||||||
|                 break; |                 break; | ||||||
| @@ -1220,8 +1213,8 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) | |||||||
|             snprintf(buf, sizeof(buf), |             snprintf(buf, sizeof(buf), | ||||||
|                      "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";", |                      "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";", | ||||||
|                      GDB_SIGNAL_TRAP, cpu_index(cpu), type, |                      GDB_SIGNAL_TRAP, cpu_index(cpu), type, | ||||||
|                      env->watchpoint_hit->vaddr); |                      (target_ulong)cpu->watchpoint_hit->vaddr); | ||||||
|             env->watchpoint_hit = NULL; |             cpu->watchpoint_hit = NULL; | ||||||
|             goto send_packet; |             goto send_packet; | ||||||
|         } |         } | ||||||
|         tb_flush(env); |         tb_flush(env); | ||||||
| @@ -1594,13 +1587,16 @@ int gdbserver_start(int port) | |||||||
| /* Disable gdb stub for child processes.  */ | /* Disable gdb stub for child processes.  */ | ||||||
| void gdbserver_fork(CPUArchState *env) | void gdbserver_fork(CPUArchState *env) | ||||||
| { | { | ||||||
|  |     CPUState *cpu = ENV_GET_CPU(env); | ||||||
|     GDBState *s = gdbserver_state; |     GDBState *s = gdbserver_state; | ||||||
|     if (gdbserver_fd < 0 || s->fd < 0) |  | ||||||
|       return; |     if (gdbserver_fd < 0 || s->fd < 0) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     close(s->fd); |     close(s->fd); | ||||||
|     s->fd = -1; |     s->fd = -1; | ||||||
|     cpu_breakpoint_remove_all(env, BP_GDB); |     cpu_breakpoint_remove_all(cpu, BP_GDB); | ||||||
|     cpu_watchpoint_remove_all(env, BP_GDB); |     cpu_watchpoint_remove_all(cpu, BP_GDB); | ||||||
| } | } | ||||||
| #else | #else | ||||||
| static int gdb_chr_can_receive(void *opaque) | static int gdb_chr_can_receive(void *opaque) | ||||||
|   | |||||||
| @@ -658,14 +658,15 @@ static void spitz_adc_temp_on(void *opaque, int line, int level) | |||||||
|         max111x_set_input(max1111, MAX1111_BATT_TEMP, 0); |         max111x_set_input(max1111, MAX1111_BATT_TEMP, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int corgi_ssp_init(SSISlave *dev) | static int corgi_ssp_init(SSISlave *d) | ||||||
| { | { | ||||||
|     CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev); |     DeviceState *dev = DEVICE(d); | ||||||
|  |     CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, d); | ||||||
|  |  | ||||||
|     qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3); |     qdev_init_gpio_in(dev, corgi_ssp_gpio_cs, 3); | ||||||
|     s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0"); |     s->bus[0] = ssi_create_bus(dev, "ssi0"); | ||||||
|     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1"); |     s->bus[1] = ssi_create_bus(dev, "ssi1"); | ||||||
|     s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2"); |     s->bus[2] = ssi_create_bus(dev, "ssi2"); | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -223,13 +223,13 @@ static void *cur_chip = NULL;	/* current chip point */ | |||||||
| /* static OPLSAMPLE  *bufL,*bufR; */ | /* static OPLSAMPLE  *bufL,*bufR; */ | ||||||
| static OPL_CH *S_CH; | static OPL_CH *S_CH; | ||||||
| static OPL_CH *E_CH; | static OPL_CH *E_CH; | ||||||
| OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2; | static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2; | ||||||
|  |  | ||||||
| static INT32 outd[1]; | static INT32 outd[1]; | ||||||
| static INT32 ams; | static INT32 ams; | ||||||
| static INT32 vib; | static INT32 vib; | ||||||
| INT32  *ams_table; | static INT32 *ams_table; | ||||||
| INT32  *vib_table; | static INT32 *vib_table; | ||||||
| static INT32 amsIncr; | static INT32 amsIncr; | ||||||
| static INT32 vibIncr; | static INT32 vibIncr; | ||||||
| static INT32 feedback2;		/* connect for SLOT 2 */ | static INT32 feedback2;		/* connect for SLOT 2 */ | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ | |||||||
| #include "virtio-blk.h" | #include "virtio-blk.h" | ||||||
| #include "block/aio.h" | #include "block/aio.h" | ||||||
| #include "hw/virtio/virtio-bus.h" | #include "hw/virtio/virtio-bus.h" | ||||||
|  | #include "monitor/monitor.h" /* for object_add() */ | ||||||
|  |  | ||||||
| enum { | enum { | ||||||
|     SEG_MAX = 126,                  /* maximum number of I/O segments */ |     SEG_MAX = 126,                  /* maximum number of I/O segments */ | ||||||
| @@ -44,8 +45,6 @@ struct VirtIOBlockDataPlane { | |||||||
|     bool started; |     bool started; | ||||||
|     bool starting; |     bool starting; | ||||||
|     bool stopping; |     bool stopping; | ||||||
|     QEMUBH *start_bh; |  | ||||||
|     QemuThread thread; |  | ||||||
|  |  | ||||||
|     VirtIOBlkConf *blk; |     VirtIOBlkConf *blk; | ||||||
|     int fd;                         /* image file descriptor */ |     int fd;                         /* image file descriptor */ | ||||||
| @@ -59,12 +58,14 @@ struct VirtIOBlockDataPlane { | |||||||
|      * (because you don't own the file descriptor or handle; you just |      * (because you don't own the file descriptor or handle; you just | ||||||
|      * use it). |      * use it). | ||||||
|      */ |      */ | ||||||
|  |     IOThread *iothread; | ||||||
|  |     bool internal_iothread; | ||||||
|     AioContext *ctx; |     AioContext *ctx; | ||||||
|     EventNotifier io_notifier;      /* Linux AIO completion */ |     EventNotifier io_notifier;      /* Linux AIO completion */ | ||||||
|     EventNotifier host_notifier;    /* doorbell */ |     EventNotifier host_notifier;    /* doorbell */ | ||||||
|  |  | ||||||
|     IOQueue ioqueue;                /* Linux AIO queue (should really be per |     IOQueue ioqueue;                /* Linux AIO queue (should really be per | ||||||
|                                        dataplane thread) */ |                                        IOThread) */ | ||||||
|     VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the |     VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the | ||||||
|                                              queue */ |                                              queue */ | ||||||
|  |  | ||||||
| @@ -342,26 +343,7 @@ static void handle_io(EventNotifier *e) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void *data_plane_thread(void *opaque) | /* Context: QEMU global mutex held */ | ||||||
| { |  | ||||||
|     VirtIOBlockDataPlane *s = opaque; |  | ||||||
|  |  | ||||||
|     while (!s->stopping || s->num_reqs > 0) { |  | ||||||
|         aio_poll(s->ctx, true); |  | ||||||
|     } |  | ||||||
|     return NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void start_data_plane_bh(void *opaque) |  | ||||||
| { |  | ||||||
|     VirtIOBlockDataPlane *s = opaque; |  | ||||||
|  |  | ||||||
|     qemu_bh_delete(s->start_bh); |  | ||||||
|     s->start_bh = NULL; |  | ||||||
|     qemu_thread_create(&s->thread, "data_plane", data_plane_thread, |  | ||||||
|                        s, QEMU_THREAD_JOINABLE); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, | void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, | ||||||
|                                   VirtIOBlockDataPlane **dataplane, |                                   VirtIOBlockDataPlane **dataplane, | ||||||
|                                   Error **errp) |                                   Error **errp) | ||||||
| @@ -408,12 +390,33 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, | |||||||
|     s->fd = fd; |     s->fd = fd; | ||||||
|     s->blk = blk; |     s->blk = blk; | ||||||
|  |  | ||||||
|  |     if (blk->iothread) { | ||||||
|  |         s->internal_iothread = false; | ||||||
|  |         s->iothread = blk->iothread; | ||||||
|  |         object_ref(OBJECT(s->iothread)); | ||||||
|  |     } else { | ||||||
|  |         /* Create per-device IOThread if none specified */ | ||||||
|  |         Error *local_err = NULL; | ||||||
|  |  | ||||||
|  |         s->internal_iothread = true; | ||||||
|  |         object_add(TYPE_IOTHREAD, vdev->name, NULL, NULL, &local_err); | ||||||
|  |         if (error_is_set(&local_err)) { | ||||||
|  |             error_propagate(errp, local_err); | ||||||
|  |             g_free(s); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         s->iothread = iothread_find(vdev->name); | ||||||
|  |         assert(s->iothread); | ||||||
|  |     } | ||||||
|  |     s->ctx = iothread_get_aio_context(s->iothread); | ||||||
|  |  | ||||||
|     /* Prevent block operations that conflict with data plane thread */ |     /* Prevent block operations that conflict with data plane thread */ | ||||||
|     bdrv_set_in_use(blk->conf.bs, 1); |     bdrv_set_in_use(blk->conf.bs, 1); | ||||||
|  |  | ||||||
|     *dataplane = s; |     *dataplane = s; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Context: QEMU global mutex held */ | ||||||
| void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) | void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) | ||||||
| { | { | ||||||
|     if (!s) { |     if (!s) { | ||||||
| @@ -422,9 +425,14 @@ 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_set_in_use(s->blk->conf.bs, 0); | ||||||
|  |     object_unref(OBJECT(s->iothread)); | ||||||
|  |     if (s->internal_iothread) { | ||||||
|  |         object_unparent(OBJECT(s->iothread)); | ||||||
|  |     } | ||||||
|     g_free(s); |     g_free(s); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Context: QEMU global mutex held */ | ||||||
| void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) | void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) | ||||||
| { | { | ||||||
|     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev))); |     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev))); | ||||||
| @@ -448,8 +456,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     s->ctx = aio_context_new(); |  | ||||||
|  |  | ||||||
|     /* Set up guest notifier (irq) */ |     /* Set up guest notifier (irq) */ | ||||||
|     if (k->set_guest_notifiers(qbus->parent, 1, true) != 0) { |     if (k->set_guest_notifiers(qbus->parent, 1, true) != 0) { | ||||||
|         fprintf(stderr, "virtio-blk failed to set guest notifier, " |         fprintf(stderr, "virtio-blk failed to set guest notifier, " | ||||||
| @@ -464,7 +470,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) | |||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
|     s->host_notifier = *virtio_queue_get_host_notifier(vq); |     s->host_notifier = *virtio_queue_get_host_notifier(vq); | ||||||
|     aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify); |  | ||||||
|  |  | ||||||
|     /* Set up ioqueue */ |     /* Set up ioqueue */ | ||||||
|     ioq_init(&s->ioqueue, s->fd, REQ_MAX); |     ioq_init(&s->ioqueue, s->fd, REQ_MAX); | ||||||
| @@ -472,7 +477,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) | |||||||
|         ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb); |         ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb); | ||||||
|     } |     } | ||||||
|     s->io_notifier = *ioq_get_notifier(&s->ioqueue); |     s->io_notifier = *ioq_get_notifier(&s->ioqueue); | ||||||
|     aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io); |  | ||||||
|  |  | ||||||
|     s->starting = false; |     s->starting = false; | ||||||
|     s->started = true; |     s->started = true; | ||||||
| @@ -481,11 +485,14 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) | |||||||
|     /* Kick right away to begin processing requests already in vring */ |     /* Kick right away to begin processing requests already in vring */ | ||||||
|     event_notifier_set(virtio_queue_get_host_notifier(vq)); |     event_notifier_set(virtio_queue_get_host_notifier(vq)); | ||||||
|  |  | ||||||
|     /* Spawn thread in BH so it inherits iothread cpusets */ |     /* Get this show started by hooking up our callbacks */ | ||||||
|     s->start_bh = qemu_bh_new(start_data_plane_bh, s); |     aio_context_acquire(s->ctx); | ||||||
|     qemu_bh_schedule(s->start_bh); |     aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify); | ||||||
|  |     aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io); | ||||||
|  |     aio_context_release(s->ctx); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Context: QEMU global mutex held */ | ||||||
| void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) | void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) | ||||||
| { | { | ||||||
|     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev))); |     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev))); | ||||||
| @@ -496,27 +503,32 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) | |||||||
|     s->stopping = true; |     s->stopping = true; | ||||||
|     trace_virtio_blk_data_plane_stop(s); |     trace_virtio_blk_data_plane_stop(s); | ||||||
|  |  | ||||||
|     /* Stop thread or cancel pending thread creation BH */ |     aio_context_acquire(s->ctx); | ||||||
|     if (s->start_bh) { |  | ||||||
|         qemu_bh_delete(s->start_bh); |     /* Stop notifications for new requests from guest */ | ||||||
|         s->start_bh = NULL; |     aio_set_event_notifier(s->ctx, &s->host_notifier, NULL); | ||||||
|     } else { |  | ||||||
|         aio_notify(s->ctx); |     /* Complete pending requests */ | ||||||
|         qemu_thread_join(&s->thread); |     while (s->num_reqs > 0) { | ||||||
|  |         aio_poll(s->ctx, true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /* Stop ioq callbacks (there are no pending requests left) */ | ||||||
|     aio_set_event_notifier(s->ctx, &s->io_notifier, NULL); |     aio_set_event_notifier(s->ctx, &s->io_notifier, NULL); | ||||||
|  |  | ||||||
|  |     aio_context_release(s->ctx); | ||||||
|  |  | ||||||
|  |     /* Sync vring state back to virtqueue so that non-dataplane request | ||||||
|  |      * processing can continue when we disable the host notifier below. | ||||||
|  |      */ | ||||||
|  |     vring_teardown(&s->vring, s->vdev, 0); | ||||||
|  |  | ||||||
|     ioq_cleanup(&s->ioqueue); |     ioq_cleanup(&s->ioqueue); | ||||||
|  |  | ||||||
|     aio_set_event_notifier(s->ctx, &s->host_notifier, NULL); |  | ||||||
|     k->set_host_notifier(qbus->parent, 0, false); |     k->set_host_notifier(qbus->parent, 0, false); | ||||||
|  |  | ||||||
|     aio_context_unref(s->ctx); |  | ||||||
|  |  | ||||||
|     /* Clean up guest notifier (irq) */ |     /* Clean up guest notifier (irq) */ | ||||||
|     k->set_guest_notifiers(qbus->parent, 1, false); |     k->set_guest_notifiers(qbus->parent, 1, false); | ||||||
|  |  | ||||||
|     vring_teardown(&s->vring, s->vdev, 0); |  | ||||||
|     s->started = false; |     s->started = false; | ||||||
|     s->stopping = false; |     s->stopping = false; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -241,7 +241,8 @@ typedef enum { | |||||||
| } CMDState; | } CMDState; | ||||||
|  |  | ||||||
| typedef struct Flash { | typedef struct Flash { | ||||||
|     SSISlave ssidev; |     SSISlave parent_obj; | ||||||
|  |  | ||||||
|     uint32_t r; |     uint32_t r; | ||||||
|  |  | ||||||
|     BlockDriverState *bdrv; |     BlockDriverState *bdrv; | ||||||
| @@ -545,7 +546,7 @@ static void decode_new_cmd(Flash *s, uint32_t value) | |||||||
|  |  | ||||||
| static int m25p80_cs(SSISlave *ss, bool select) | static int m25p80_cs(SSISlave *ss, bool select) | ||||||
| { | { | ||||||
|     Flash *s = FROM_SSI_SLAVE(Flash, ss); |     Flash *s = M25P80(ss); | ||||||
|  |  | ||||||
|     if (select) { |     if (select) { | ||||||
|         s->len = 0; |         s->len = 0; | ||||||
| @@ -561,7 +562,7 @@ static int m25p80_cs(SSISlave *ss, bool select) | |||||||
|  |  | ||||||
| static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) | static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) | ||||||
| { | { | ||||||
|     Flash *s = FROM_SSI_SLAVE(Flash, ss); |     Flash *s = M25P80(ss); | ||||||
|     uint32_t r = 0; |     uint32_t r = 0; | ||||||
|  |  | ||||||
|     switch (s->state) { |     switch (s->state) { | ||||||
| @@ -610,7 +611,7 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) | |||||||
| static int m25p80_init(SSISlave *ss) | static int m25p80_init(SSISlave *ss) | ||||||
| { | { | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
|     Flash *s = FROM_SSI_SLAVE(Flash, ss); |     Flash *s = M25P80(ss); | ||||||
|     M25P80Class *mc = M25P80_GET_CLASS(s); |     M25P80Class *mc = M25P80_GET_CLASS(s); | ||||||
|  |  | ||||||
|     s->pi = mc->pi; |     s->pi = mc->pi; | ||||||
|   | |||||||
| @@ -15,8 +15,13 @@ | |||||||
| #include "trace.h" | #include "trace.h" | ||||||
| #include "hw/virtio/virtio-serial.h" | #include "hw/virtio/virtio-serial.h" | ||||||
|  |  | ||||||
|  | #define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport" | ||||||
|  | #define VIRTIO_CONSOLE(obj) \ | ||||||
|  |     OBJECT_CHECK(VirtConsole, (obj), TYPE_VIRTIO_CONSOLE_SERIAL_PORT) | ||||||
|  |  | ||||||
| typedef struct VirtConsole { | typedef struct VirtConsole { | ||||||
|     VirtIOSerialPort port; |     VirtIOSerialPort parent_obj; | ||||||
|  |  | ||||||
|     CharDriverState *chr; |     CharDriverState *chr; | ||||||
|     guint watch; |     guint watch; | ||||||
| } VirtConsole; | } VirtConsole; | ||||||
| @@ -31,7 +36,7 @@ static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond, | |||||||
|     VirtConsole *vcon = opaque; |     VirtConsole *vcon = opaque; | ||||||
|  |  | ||||||
|     vcon->watch = 0; |     vcon->watch = 0; | ||||||
|     virtio_serial_throttle_port(&vcon->port, false); |     virtio_serial_throttle_port(VIRTIO_SERIAL_PORT(vcon), false); | ||||||
|     return FALSE; |     return FALSE; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -39,7 +44,7 @@ static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond, | |||||||
| static ssize_t flush_buf(VirtIOSerialPort *port, | static ssize_t flush_buf(VirtIOSerialPort *port, | ||||||
|                          const uint8_t *buf, ssize_t len) |                          const uint8_t *buf, ssize_t len) | ||||||
| { | { | ||||||
|     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |     VirtConsole *vcon = VIRTIO_CONSOLE(port); | ||||||
|     ssize_t ret; |     ssize_t ret; | ||||||
|  |  | ||||||
|     if (!vcon->chr) { |     if (!vcon->chr) { | ||||||
| @@ -75,7 +80,7 @@ static ssize_t flush_buf(VirtIOSerialPort *port, | |||||||
| /* Callback function that's called when the guest opens/closes the port */ | /* Callback function that's called when the guest opens/closes the port */ | ||||||
| static void set_guest_connected(VirtIOSerialPort *port, int guest_connected) | static void set_guest_connected(VirtIOSerialPort *port, int guest_connected) | ||||||
| { | { | ||||||
|     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |     VirtConsole *vcon = VIRTIO_CONSOLE(port); | ||||||
|  |  | ||||||
|     if (!vcon->chr) { |     if (!vcon->chr) { | ||||||
|         return; |         return; | ||||||
| @@ -88,45 +93,49 @@ static int chr_can_read(void *opaque) | |||||||
| { | { | ||||||
|     VirtConsole *vcon = opaque; |     VirtConsole *vcon = opaque; | ||||||
|  |  | ||||||
|     return virtio_serial_guest_ready(&vcon->port); |     return virtio_serial_guest_ready(VIRTIO_SERIAL_PORT(vcon)); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Send data from a char device over to the guest */ | /* Send data from a char device over to the guest */ | ||||||
| static void chr_read(void *opaque, const uint8_t *buf, int size) | static void chr_read(void *opaque, const uint8_t *buf, int size) | ||||||
| { | { | ||||||
|     VirtConsole *vcon = opaque; |     VirtConsole *vcon = opaque; | ||||||
|  |     VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon); | ||||||
|  |  | ||||||
|     trace_virtio_console_chr_read(vcon->port.id, size); |     trace_virtio_console_chr_read(port->id, size); | ||||||
|     virtio_serial_write(&vcon->port, buf, size); |     virtio_serial_write(port, buf, size); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void chr_event(void *opaque, int event) | static void chr_event(void *opaque, int event) | ||||||
| { | { | ||||||
|     VirtConsole *vcon = opaque; |     VirtConsole *vcon = opaque; | ||||||
|  |     VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon); | ||||||
|  |  | ||||||
|     trace_virtio_console_chr_event(vcon->port.id, event); |     trace_virtio_console_chr_event(port->id, event); | ||||||
|     switch (event) { |     switch (event) { | ||||||
|     case CHR_EVENT_OPENED: |     case CHR_EVENT_OPENED: | ||||||
|         virtio_serial_open(&vcon->port); |         virtio_serial_open(port); | ||||||
|         break; |         break; | ||||||
|     case CHR_EVENT_CLOSED: |     case CHR_EVENT_CLOSED: | ||||||
|         if (vcon->watch) { |         if (vcon->watch) { | ||||||
|             g_source_remove(vcon->watch); |             g_source_remove(vcon->watch); | ||||||
|             vcon->watch = 0; |             vcon->watch = 0; | ||||||
|         } |         } | ||||||
|         virtio_serial_close(&vcon->port); |         virtio_serial_close(port); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static int virtconsole_initfn(VirtIOSerialPort *port) | static void virtconsole_realize(DeviceState *dev, Error **errp) | ||||||
| { | { | ||||||
|     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |     VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); | ||||||
|     VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); |     VirtConsole *vcon = VIRTIO_CONSOLE(dev); | ||||||
|  |     VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev); | ||||||
|  |  | ||||||
|     if (port->id == 0 && !k->is_console) { |     if (port->id == 0 && !k->is_console) { | ||||||
|         error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility."); |         error_setg(errp, "Port number 0 on virtio-serial devices reserved " | ||||||
|         return -1; |                    "for virtconsole devices for backward compatibility."); | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (vcon->chr) { |     if (vcon->chr) { | ||||||
| @@ -134,43 +143,27 @@ static int virtconsole_initfn(VirtIOSerialPort *port) | |||||||
|         qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, |         qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, | ||||||
|                               vcon); |                               vcon); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int virtconsole_exitfn(VirtIOSerialPort *port) | static void virtconsole_unrealize(DeviceState *dev, Error **errp) | ||||||
| { | { | ||||||
|     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |     VirtConsole *vcon = VIRTIO_CONSOLE(dev); | ||||||
|  |  | ||||||
|     if (vcon->watch) { |     if (vcon->watch) { | ||||||
|         g_source_remove(vcon->watch); |         g_source_remove(vcon->watch); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static Property virtconsole_properties[] = { |  | ||||||
|     DEFINE_PROP_CHR("chardev", VirtConsole, chr), |  | ||||||
|     DEFINE_PROP_END_OF_LIST(), |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static void virtconsole_class_init(ObjectClass *klass, void *data) | static void virtconsole_class_init(ObjectClass *klass, void *data) | ||||||
| { | { | ||||||
|     DeviceClass *dc = DEVICE_CLASS(klass); |  | ||||||
|     VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass); |     VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass); | ||||||
|  |  | ||||||
|     k->is_console = true; |     k->is_console = true; | ||||||
|     k->init = virtconsole_initfn; |  | ||||||
|     k->exit = virtconsole_exitfn; |  | ||||||
|     k->have_data = flush_buf; |  | ||||||
|     k->set_guest_connected = set_guest_connected; |  | ||||||
|     dc->props = virtconsole_properties; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static const TypeInfo virtconsole_info = { | static const TypeInfo virtconsole_info = { | ||||||
|     .name          = "virtconsole", |     .name          = "virtconsole", | ||||||
|     .parent        = TYPE_VIRTIO_SERIAL_PORT, |     .parent        = TYPE_VIRTIO_CONSOLE_SERIAL_PORT, | ||||||
|     .instance_size = sizeof(VirtConsole), |  | ||||||
|     .class_init    = virtconsole_class_init, |     .class_init    = virtconsole_class_init, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -184,15 +177,15 @@ static void virtserialport_class_init(ObjectClass *klass, void *data) | |||||||
|     DeviceClass *dc = DEVICE_CLASS(klass); |     DeviceClass *dc = DEVICE_CLASS(klass); | ||||||
|     VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass); |     VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass); | ||||||
|  |  | ||||||
|     k->init = virtconsole_initfn; |     k->realize = virtconsole_realize; | ||||||
|     k->exit = virtconsole_exitfn; |     k->unrealize = virtconsole_unrealize; | ||||||
|     k->have_data = flush_buf; |     k->have_data = flush_buf; | ||||||
|     k->set_guest_connected = set_guest_connected; |     k->set_guest_connected = set_guest_connected; | ||||||
|     dc->props = virtserialport_properties; |     dc->props = virtserialport_properties; | ||||||
| } | } | ||||||
|  |  | ||||||
| static const TypeInfo virtserialport_info = { | static const TypeInfo virtserialport_info = { | ||||||
|     .name          = "virtserialport", |     .name          = TYPE_VIRTIO_CONSOLE_SERIAL_PORT, | ||||||
|     .parent        = TYPE_VIRTIO_SERIAL_PORT, |     .parent        = TYPE_VIRTIO_SERIAL_PORT, | ||||||
|     .instance_size = sizeof(VirtConsole), |     .instance_size = sizeof(VirtConsole), | ||||||
|     .class_init    = virtserialport_class_init, |     .class_init    = virtserialport_class_init, | ||||||
| @@ -200,8 +193,8 @@ static const TypeInfo virtserialport_info = { | |||||||
|  |  | ||||||
| static void virtconsole_register_types(void) | static void virtconsole_register_types(void) | ||||||
| { | { | ||||||
|     type_register_static(&virtconsole_info); |  | ||||||
|     type_register_static(&virtserialport_info); |     type_register_static(&virtserialport_info); | ||||||
|  |     type_register_static(&virtconsole_info); | ||||||
| } | } | ||||||
|  |  | ||||||
| type_init(virtconsole_register_types) | type_init(virtconsole_register_types) | ||||||
|   | |||||||
| @@ -808,13 +808,14 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id) | |||||||
|     send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1); |     send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int virtser_port_qdev_init(DeviceState *qdev) | static void virtser_port_device_realize(DeviceState *dev, Error **errp) | ||||||
| { | { | ||||||
|     VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev); |     VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); | ||||||
|     VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); |     VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); | ||||||
|     VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus); |     VirtIOSerialBus *bus = VIRTIO_SERIAL_BUS(qdev_get_parent_bus(dev)); | ||||||
|     int ret, max_nr_ports; |     int max_nr_ports; | ||||||
|     bool plugging_port0; |     bool plugging_port0; | ||||||
|  |     Error *err = NULL; | ||||||
|  |  | ||||||
|     port->vser = bus->vser; |     port->vser = bus->vser; | ||||||
|     port->bh = qemu_bh_new(flush_queued_data_bh, port); |     port->bh = qemu_bh_new(flush_queued_data_bh, port); | ||||||
| @@ -829,9 +830,9 @@ static int virtser_port_qdev_init(DeviceState *qdev) | |||||||
|     plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0); |     plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0); | ||||||
|  |  | ||||||
|     if (find_port_by_id(port->vser, port->id)) { |     if (find_port_by_id(port->vser, port->id)) { | ||||||
|         error_report("virtio-serial-bus: A port already exists at id %u", |         error_setg(errp, "virtio-serial-bus: A port already exists at id %u", | ||||||
|                      port->id); |                    port->id); | ||||||
|         return -1; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (port->id == VIRTIO_CONSOLE_BAD_ID) { |     if (port->id == VIRTIO_CONSOLE_BAD_ID) { | ||||||
| @@ -840,22 +841,24 @@ static int virtser_port_qdev_init(DeviceState *qdev) | |||||||
|         } else { |         } else { | ||||||
|             port->id = find_free_port_id(port->vser); |             port->id = find_free_port_id(port->vser); | ||||||
|             if (port->id == VIRTIO_CONSOLE_BAD_ID) { |             if (port->id == VIRTIO_CONSOLE_BAD_ID) { | ||||||
|                 error_report("virtio-serial-bus: Maximum port limit for this device reached"); |                 error_setg(errp, "virtio-serial-bus: Maximum port limit for " | ||||||
|                 return -1; |                                  "this device reached"); | ||||||
|  |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     max_nr_ports = tswap32(port->vser->config.max_nr_ports); |     max_nr_ports = tswap32(port->vser->config.max_nr_ports); | ||||||
|     if (port->id >= max_nr_ports) { |     if (port->id >= max_nr_ports) { | ||||||
|         error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u", |         error_setg(errp, "virtio-serial-bus: Out-of-range port id specified, " | ||||||
|                      max_nr_ports - 1); |                          "max. allowed: %u", max_nr_ports - 1); | ||||||
|         return -1; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ret = vsc->init(port); |     vsc->realize(dev, &err); | ||||||
|     if (ret) { |     if (err != NULL) { | ||||||
|         return ret; |         error_propagate(errp, err); | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     port->elem.out_num = 0; |     port->elem.out_num = 0; | ||||||
| @@ -868,14 +871,12 @@ static int virtser_port_qdev_init(DeviceState *qdev) | |||||||
|  |  | ||||||
|     /* Send an update to the guest about this new port added */ |     /* Send an update to the guest about this new port added */ | ||||||
|     virtio_notify_config(VIRTIO_DEVICE(port->vser)); |     virtio_notify_config(VIRTIO_DEVICE(port->vser)); | ||||||
|  |  | ||||||
|     return ret; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int virtser_port_qdev_exit(DeviceState *qdev) | static void virtser_port_device_unrealize(DeviceState *dev, Error **errp) | ||||||
| { | { | ||||||
|     VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev); |     VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); | ||||||
|     VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); |     VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(dev); | ||||||
|     VirtIOSerial *vser = port->vser; |     VirtIOSerial *vser = port->vser; | ||||||
|  |  | ||||||
|     qemu_bh_delete(port->bh); |     qemu_bh_delete(port->bh); | ||||||
| @@ -883,10 +884,9 @@ static int virtser_port_qdev_exit(DeviceState *qdev) | |||||||
|  |  | ||||||
|     QTAILQ_REMOVE(&vser->ports, port, next); |     QTAILQ_REMOVE(&vser->ports, port, next); | ||||||
|  |  | ||||||
|     if (vsc->exit) { |     if (vsc->unrealize) { | ||||||
|         vsc->exit(port); |         vsc->unrealize(dev, errp); | ||||||
|     } |     } | ||||||
|     return 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void virtio_serial_device_realize(DeviceState *dev, Error **errp) | static void virtio_serial_device_realize(DeviceState *dev, Error **errp) | ||||||
| @@ -971,10 +971,11 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) | |||||||
| static void virtio_serial_port_class_init(ObjectClass *klass, void *data) | static void virtio_serial_port_class_init(ObjectClass *klass, void *data) | ||||||
| { | { | ||||||
|     DeviceClass *k = DEVICE_CLASS(klass); |     DeviceClass *k = DEVICE_CLASS(klass); | ||||||
|     k->init = virtser_port_qdev_init; |  | ||||||
|     set_bit(DEVICE_CATEGORY_INPUT, k->categories); |     set_bit(DEVICE_CATEGORY_INPUT, k->categories); | ||||||
|     k->bus_type = TYPE_VIRTIO_SERIAL_BUS; |     k->bus_type = TYPE_VIRTIO_SERIAL_BUS; | ||||||
|     k->exit = virtser_port_qdev_exit; |     k->realize = virtser_port_device_realize; | ||||||
|  |     k->unrealize = virtser_port_device_unrealize; | ||||||
|     k->unplug = qdev_simple_unplug_cb; |     k->unplug = qdev_simple_unplug_cb; | ||||||
|     k->props = virtser_props; |     k->props = virtser_props; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o | |||||||
| common-obj-$(CONFIG_XILINX_AXI) += stream.o | common-obj-$(CONFIG_XILINX_AXI) += stream.o | ||||||
| common-obj-$(CONFIG_PTIMER) += ptimer.o | common-obj-$(CONFIG_PTIMER) += ptimer.o | ||||||
| common-obj-$(CONFIG_SOFTMMU) += sysbus.o | common-obj-$(CONFIG_SOFTMMU) += sysbus.o | ||||||
|  | common-obj-$(CONFIG_SOFTMMU) += machine.o | ||||||
| common-obj-$(CONFIG_SOFTMMU) += null-machine.o | common-obj-$(CONFIG_SOFTMMU) += null-machine.o | ||||||
| common-obj-$(CONFIG_SOFTMMU) += loader.o | common-obj-$(CONFIG_SOFTMMU) += loader.o | ||||||
| common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o | common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,7 +54,8 @@ | |||||||
|  |  | ||||||
| #include <zlib.h> | #include <zlib.h> | ||||||
|  |  | ||||||
| bool rom_file_in_ram = true; | bool option_rom_has_mr = false; | ||||||
|  | bool rom_file_has_mr = true; | ||||||
|  |  | ||||||
| static int roms_loaded; | static int roms_loaded; | ||||||
|  |  | ||||||
| @@ -642,7 +643,8 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name) | |||||||
| } | } | ||||||
|  |  | ||||||
| int rom_add_file(const char *file, const char *fw_dir, | int rom_add_file(const char *file, const char *fw_dir, | ||||||
|                  hwaddr addr, int32_t bootindex) |                  hwaddr addr, int32_t bootindex, | ||||||
|  |                  bool option_rom) | ||||||
| { | { | ||||||
|     Rom *rom; |     Rom *rom; | ||||||
|     int rc, fd = -1; |     int rc, fd = -1; | ||||||
| @@ -694,7 +696,7 @@ int rom_add_file(const char *file, const char *fw_dir, | |||||||
|                  basename); |                  basename); | ||||||
|         snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); |         snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); | ||||||
|  |  | ||||||
|         if (rom_file_in_ram) { |         if ((!option_rom || option_rom_has_mr) && rom_file_has_mr) { | ||||||
|             data = rom_set_mr(rom, OBJECT(fw_cfg), devpath); |             data = rom_set_mr(rom, OBJECT(fw_cfg), devpath); | ||||||
|         } else { |         } else { | ||||||
|             data = rom->data; |             data = rom->data; | ||||||
| @@ -738,7 +740,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len, | |||||||
|  |  | ||||||
|         snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); |         snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); | ||||||
|  |  | ||||||
|         if (rom_file_in_ram) { |         if (rom_file_has_mr) { | ||||||
|             data = rom_set_mr(rom, OBJECT(fw_cfg), devpath); |             data = rom_set_mr(rom, OBJECT(fw_cfg), devpath); | ||||||
|         } else { |         } else { | ||||||
|             data = rom->data; |             data = rom->data; | ||||||
| @@ -773,12 +775,12 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize, | |||||||
|  |  | ||||||
| int rom_add_vga(const char *file) | int rom_add_vga(const char *file) | ||||||
| { | { | ||||||
|     return rom_add_file(file, "vgaroms", 0, -1); |     return rom_add_file(file, "vgaroms", 0, -1, true); | ||||||
| } | } | ||||||
|  |  | ||||||
| int rom_add_option(const char *file, int32_t bootindex) | int rom_add_option(const char *file, int32_t bootindex) | ||||||
| { | { | ||||||
|     return rom_add_file(file, "genroms", 0, bootindex); |     return rom_add_file(file, "genroms", 0, bootindex, true); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void rom_reset(void *unused) | static void rom_reset(void *unused) | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								hw/core/machine.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								hw/core/machine.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | /* | ||||||
|  |  * QEMU Machine | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2014 Red Hat Inc | ||||||
|  |  * | ||||||
|  |  * Authors: | ||||||
|  |  *   Marcel Apfelbaum <marcel.a@redhat.com> | ||||||
|  |  * | ||||||
|  |  * This work is licensed under the terms of the GNU GPL, version 2 or later. | ||||||
|  |  * See the COPYING file in the top-level directory. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "hw/boards.h" | ||||||
|  |  | ||||||
|  | static const TypeInfo machine_info = { | ||||||
|  |     .name = TYPE_MACHINE, | ||||||
|  |     .parent = TYPE_OBJECT, | ||||||
|  |     .abstract = true, | ||||||
|  |     .class_size = sizeof(MachineClass), | ||||||
|  |     .instance_size = sizeof(MachineState), | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static void machine_register_types(void) | ||||||
|  | { | ||||||
|  |     type_register_static(&machine_info); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type_init(machine_register_types) | ||||||
| @@ -18,17 +18,19 @@ | |||||||
| #include "net/hub.h" | #include "net/hub.h" | ||||||
| #include "qapi/visitor.h" | #include "qapi/visitor.h" | ||||||
| #include "sysemu/char.h" | #include "sysemu/char.h" | ||||||
|  | #include "sysemu/iothread.h" | ||||||
|  |  | ||||||
| static void get_pointer(Object *obj, Visitor *v, Property *prop, | static void get_pointer(Object *obj, Visitor *v, Property *prop, | ||||||
|                         const char *(*print)(void *ptr), |                         char *(*print)(void *ptr), | ||||||
|                         const char *name, Error **errp) |                         const char *name, Error **errp) | ||||||
| { | { | ||||||
|     DeviceState *dev = DEVICE(obj); |     DeviceState *dev = DEVICE(obj); | ||||||
|     void **ptr = qdev_get_prop_ptr(dev, prop); |     void **ptr = qdev_get_prop_ptr(dev, prop); | ||||||
|     char *p; |     char *p; | ||||||
|  |  | ||||||
|     p = (char *) (*ptr ? print(*ptr) : ""); |     p = *ptr ? print(*ptr) : g_strdup(""); | ||||||
|     visit_type_str(v, &p, name, errp); |     visit_type_str(v, &p, name, errp); | ||||||
|  |     g_free(p); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void set_pointer(Object *obj, Visitor *v, Property *prop, | static void set_pointer(Object *obj, Visitor *v, Property *prop, | ||||||
| @@ -91,9 +93,9 @@ static void release_drive(Object *obj, const char *name, void *opaque) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static const char *print_drive(void *ptr) | static char *print_drive(void *ptr) | ||||||
| { | { | ||||||
|     return bdrv_get_device_name(ptr); |     return g_strdup(bdrv_get_device_name(ptr)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void get_drive(Object *obj, Visitor *v, void *opaque, | static void get_drive(Object *obj, Visitor *v, void *opaque, | ||||||
| @@ -145,11 +147,12 @@ static void release_chr(Object *obj, const char *name, void *opaque) | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static const char *print_chr(void *ptr) | static char *print_chr(void *ptr) | ||||||
| { | { | ||||||
|     CharDriverState *chr = ptr; |     CharDriverState *chr = ptr; | ||||||
|  |     const char *val = chr->label ? chr->label : ""; | ||||||
|  |  | ||||||
|     return chr->label ? chr->label : ""; |     return g_strdup(val); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void get_chr(Object *obj, Visitor *v, void *opaque, | static void get_chr(Object *obj, Visitor *v, void *opaque, | ||||||
| @@ -224,11 +227,12 @@ err: | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| static const char *print_netdev(void *ptr) | static char *print_netdev(void *ptr) | ||||||
| { | { | ||||||
|     NetClientState *netdev = ptr; |     NetClientState *netdev = ptr; | ||||||
|  |     const char *val = netdev->name ? netdev->name : ""; | ||||||
|  |  | ||||||
|     return netdev->name ? netdev->name : ""; |     return g_strdup(val); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void get_netdev(Object *obj, Visitor *v, void *opaque, | static void get_netdev(Object *obj, Visitor *v, void *opaque, | ||||||
| @@ -382,6 +386,56 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) | |||||||
|     nd->instantiated = 1; |     nd->instantiated = 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* --- iothread --- */ | ||||||
|  |  | ||||||
|  | static char *print_iothread(void *ptr) | ||||||
|  | { | ||||||
|  |     return iothread_get_id(ptr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int parse_iothread(DeviceState *dev, const char *str, void **ptr) | ||||||
|  | { | ||||||
|  |     IOThread *iothread; | ||||||
|  |  | ||||||
|  |     iothread = iothread_find(str); | ||||||
|  |     if (!iothread) { | ||||||
|  |         return -ENOENT; | ||||||
|  |     } | ||||||
|  |     object_ref(OBJECT(iothread)); | ||||||
|  |     *ptr = iothread; | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void get_iothread(Object *obj, struct Visitor *v, void *opaque, | ||||||
|  |                          const char *name, Error **errp) | ||||||
|  | { | ||||||
|  |     get_pointer(obj, v, opaque, print_iothread, name, errp); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void set_iothread(Object *obj, struct Visitor *v, void *opaque, | ||||||
|  |                          const char *name, Error **errp) | ||||||
|  | { | ||||||
|  |     set_pointer(obj, v, opaque, parse_iothread, name, errp); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void release_iothread(Object *obj, const char *name, void *opaque) | ||||||
|  | { | ||||||
|  |     DeviceState *dev = DEVICE(obj); | ||||||
|  |     Property *prop = opaque; | ||||||
|  |     IOThread **ptr = qdev_get_prop_ptr(dev, prop); | ||||||
|  |  | ||||||
|  |     if (*ptr) { | ||||||
|  |         object_unref(OBJECT(*ptr)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | PropertyInfo qdev_prop_iothread = { | ||||||
|  |     .name = "iothread", | ||||||
|  |     .get = get_iothread, | ||||||
|  |     .set = set_iothread, | ||||||
|  |     .release = release_iothread, | ||||||
|  | }; | ||||||
|  |  | ||||||
| static int qdev_add_one_global(QemuOpts *opts, void *opaque) | static int qdev_add_one_global(QemuOpts *opts, void *opaque) | ||||||
| { | { | ||||||
|     GlobalProperty *g; |     GlobalProperty *g; | ||||||
|   | |||||||
| @@ -501,6 +501,45 @@ static void bus_unparent(Object *obj) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static bool bus_get_realized(Object *obj, Error **err) | ||||||
|  | { | ||||||
|  |     BusState *bus = BUS(obj); | ||||||
|  |  | ||||||
|  |     return bus->realized; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void bus_set_realized(Object *obj, bool value, Error **err) | ||||||
|  | { | ||||||
|  |     BusState *bus = BUS(obj); | ||||||
|  |     BusClass *bc = BUS_GET_CLASS(bus); | ||||||
|  |     Error *local_err = NULL; | ||||||
|  |  | ||||||
|  |     if (value && !bus->realized) { | ||||||
|  |         if (bc->realize) { | ||||||
|  |             bc->realize(bus, &local_err); | ||||||
|  |  | ||||||
|  |             if (local_err != NULL) { | ||||||
|  |                 goto error; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |     } else if (!value && bus->realized) { | ||||||
|  |         if (bc->unrealize) { | ||||||
|  |             bc->unrealize(bus, &local_err); | ||||||
|  |  | ||||||
|  |             if (local_err != NULL) { | ||||||
|  |                 goto error; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bus->realized = value; | ||||||
|  |     return; | ||||||
|  |  | ||||||
|  | error: | ||||||
|  |     error_propagate(err, local_err); | ||||||
|  | } | ||||||
|  |  | ||||||
| void qbus_create_inplace(void *bus, size_t size, const char *typename, | void qbus_create_inplace(void *bus, size_t size, const char *typename, | ||||||
|                          DeviceState *parent, const char *name) |                          DeviceState *parent, const char *name) | ||||||
| { | { | ||||||
| @@ -677,6 +716,7 @@ static void device_set_realized(Object *obj, bool value, Error **err) | |||||||
| { | { | ||||||
|     DeviceState *dev = DEVICE(obj); |     DeviceState *dev = DEVICE(obj); | ||||||
|     DeviceClass *dc = DEVICE_GET_CLASS(dev); |     DeviceClass *dc = DEVICE_GET_CLASS(dev); | ||||||
|  |     BusState *bus; | ||||||
|     Error *local_err = NULL; |     Error *local_err = NULL; | ||||||
|  |  | ||||||
|     if (dev->hotplugged && !dc->hotpluggable) { |     if (dev->hotplugged && !dc->hotpluggable) { | ||||||
| @@ -710,14 +750,30 @@ static void device_set_realized(Object *obj, bool value, Error **err) | |||||||
|                                            dev->instance_id_alias, |                                            dev->instance_id_alias, | ||||||
|                                            dev->alias_required_for_version); |                                            dev->alias_required_for_version); | ||||||
|         } |         } | ||||||
|  |         if (local_err == NULL) { | ||||||
|  |             QLIST_FOREACH(bus, &dev->child_bus, sibling) { | ||||||
|  |                 object_property_set_bool(OBJECT(bus), true, "realized", | ||||||
|  |                                          &local_err); | ||||||
|  |                 if (local_err != NULL) { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         if (dev->hotplugged && local_err == NULL) { |         if (dev->hotplugged && local_err == NULL) { | ||||||
|             device_reset(dev); |             device_reset(dev); | ||||||
|         } |         } | ||||||
|     } else if (!value && dev->realized) { |     } else if (!value && dev->realized) { | ||||||
|         if (qdev_get_vmsd(dev)) { |         QLIST_FOREACH(bus, &dev->child_bus, sibling) { | ||||||
|  |             object_property_set_bool(OBJECT(bus), false, "realized", | ||||||
|  |                                      &local_err); | ||||||
|  |             if (local_err != NULL) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (qdev_get_vmsd(dev) && local_err == NULL) { | ||||||
|             vmstate_unregister(dev, qdev_get_vmsd(dev), dev); |             vmstate_unregister(dev, qdev_get_vmsd(dev), dev); | ||||||
|         } |         } | ||||||
|         if (dc->unrealize) { |         if (dc->unrealize && local_err == NULL) { | ||||||
|             dc->unrealize(dev, &local_err); |             dc->unrealize(dev, &local_err); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -735,7 +791,8 @@ static bool device_get_hotpluggable(Object *obj, Error **err) | |||||||
|     DeviceClass *dc = DEVICE_GET_CLASS(obj); |     DeviceClass *dc = DEVICE_GET_CLASS(obj); | ||||||
|     DeviceState *dev = DEVICE(obj); |     DeviceState *dev = DEVICE(obj); | ||||||
|  |  | ||||||
|     return dc->hotpluggable && dev->parent_bus->allow_hotplug; |     return dc->hotpluggable && (dev->parent_bus == NULL || | ||||||
|  |                                 dev->parent_bus->allow_hotplug); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void device_initfn(Object *obj) | static void device_initfn(Object *obj) | ||||||
| @@ -792,14 +849,6 @@ static void device_class_base_init(ObjectClass *class, void *data) | |||||||
|      * so do not propagate them to the subclasses. |      * so do not propagate them to the subclasses. | ||||||
|      */ |      */ | ||||||
|     klass->props = NULL; |     klass->props = NULL; | ||||||
|  |  | ||||||
|     /* by default all devices were considered as hotpluggable, |  | ||||||
|      * so with intent to check it in generic qdev_unplug() / |  | ||||||
|      * device_set_realized() functions make every device |  | ||||||
|      * hotpluggable. Devices that shouldn't be hotpluggable, |  | ||||||
|      * should override it in their class_init() |  | ||||||
|      */ |  | ||||||
|     klass->hotpluggable = true; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void device_unparent(Object *obj) | static void device_unparent(Object *obj) | ||||||
| @@ -809,13 +858,13 @@ static void device_unparent(Object *obj) | |||||||
|     QObject *event_data; |     QObject *event_data; | ||||||
|     bool have_realized = dev->realized; |     bool have_realized = dev->realized; | ||||||
|  |  | ||||||
|  |     if (dev->realized) { | ||||||
|  |         object_property_set_bool(obj, false, "realized", NULL); | ||||||
|  |     } | ||||||
|     while (dev->num_child_bus) { |     while (dev->num_child_bus) { | ||||||
|         bus = QLIST_FIRST(&dev->child_bus); |         bus = QLIST_FIRST(&dev->child_bus); | ||||||
|         object_unparent(OBJECT(bus)); |         object_unparent(OBJECT(bus)); | ||||||
|     } |     } | ||||||
|     if (dev->realized) { |  | ||||||
|         object_property_set_bool(obj, false, "realized", NULL); |  | ||||||
|     } |  | ||||||
|     if (dev->parent_bus) { |     if (dev->parent_bus) { | ||||||
|         bus_remove_child(dev->parent_bus, dev); |         bus_remove_child(dev->parent_bus, dev); | ||||||
|         object_unref(OBJECT(dev->parent_bus)); |         object_unref(OBJECT(dev->parent_bus)); | ||||||
| @@ -845,6 +894,14 @@ static void device_class_init(ObjectClass *class, void *data) | |||||||
|     class->unparent = device_unparent; |     class->unparent = device_unparent; | ||||||
|     dc->realize = device_realize; |     dc->realize = device_realize; | ||||||
|     dc->unrealize = device_unrealize; |     dc->unrealize = device_unrealize; | ||||||
|  |  | ||||||
|  |     /* by default all devices were considered as hotpluggable, | ||||||
|  |      * so with intent to check it in generic qdev_unplug() / | ||||||
|  |      * device_set_realized() functions make every device | ||||||
|  |      * hotpluggable. Devices that shouldn't be hotpluggable, | ||||||
|  |      * should override it in their class_init() | ||||||
|  |      */ | ||||||
|  |     dc->hotpluggable = true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void device_reset(DeviceState *dev) | void device_reset(DeviceState *dev) | ||||||
| @@ -888,6 +945,8 @@ static void qbus_initfn(Object *obj) | |||||||
|     object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY, |     object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY, | ||||||
|                              TYPE_HOTPLUG_HANDLER, |                              TYPE_HOTPLUG_HANDLER, | ||||||
|                              (Object **)&bus->hotplug_handler, NULL); |                              (Object **)&bus->hotplug_handler, NULL); | ||||||
|  |     object_property_add_bool(obj, "realized", | ||||||
|  |                              bus_get_realized, bus_set_realized, NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
| static char *default_bus_get_fw_dev_path(DeviceState *dev) | static char *default_bus_get_fw_dev_path(DeviceState *dev) | ||||||
|   | |||||||
| @@ -133,11 +133,12 @@ static const VMStateDescription vmstate_ads7846 = { | |||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int ads7846_init(SSISlave *dev) | static int ads7846_init(SSISlave *d) | ||||||
| { | { | ||||||
|     ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev); |     DeviceState *dev = DEVICE(d); | ||||||
|  |     ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, d); | ||||||
|  |  | ||||||
|     qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1); |     qdev_init_gpio_out(dev, &s->interrupt, 1); | ||||||
|  |  | ||||||
|     s->input[0] = ADS_TEMP0;	/* TEMP0 */ |     s->input[0] = ADS_TEMP0;	/* TEMP0 */ | ||||||
|     s->input[2] = ADS_VBAT;	/* VBAT */ |     s->input[2] = ADS_VBAT;	/* VBAT */ | ||||||
|   | |||||||
| @@ -336,18 +336,19 @@ static const GraphicHwOps ssd0323_ops = { | |||||||
|     .gfx_update  = ssd0323_update_display, |     .gfx_update  = ssd0323_update_display, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int ssd0323_init(SSISlave *dev) | static int ssd0323_init(SSISlave *d) | ||||||
| { | { | ||||||
|     ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); |     DeviceState *dev = DEVICE(d); | ||||||
|  |     ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, d); | ||||||
|  |  | ||||||
|     s->col_end = 63; |     s->col_end = 63; | ||||||
|     s->row_end = 79; |     s->row_end = 79; | ||||||
|     s->con = graphic_console_init(DEVICE(dev), 0, &ssd0323_ops, s); |     s->con = graphic_console_init(dev, 0, &ssd0323_ops, s); | ||||||
|     qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY); |     qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY); | ||||||
|  |  | ||||||
|     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1); |     qdev_init_gpio_in(dev, ssd0323_cd, 1); | ||||||
|  |  | ||||||
|     register_savevm(&dev->qdev, "ssd0323_oled", -1, 1, |     register_savevm(dev, "ssd0323_oled", -1, 1, | ||||||
|                     ssd0323_save, ssd0323_load, s); |                     ssd0323_save, ssd0323_load, s); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -466,9 +466,15 @@ static void acpi_align_size(GArray *blob, unsigned align) | |||||||
|     g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); |     g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Get pointer within table in a safe manner */ | /* Set a value within table in a safe manner */ | ||||||
| #define ACPI_BUILD_PTR(table, size, off, type) \ | #define ACPI_BUILD_SET_LE(table, size, off, bits, val) \ | ||||||
|     ((type *)(acpi_data_get_ptr(table, size, off, sizeof(type)))) |     do { \ | ||||||
|  |         uint64_t ACPI_BUILD_SET_LE_val = cpu_to_le64(val); \ | ||||||
|  |         memcpy(acpi_data_get_ptr(table, size, off, \ | ||||||
|  |                                  (bits) / BITS_PER_BYTE), \ | ||||||
|  |                &ACPI_BUILD_SET_LE_val, \ | ||||||
|  |                (bits) / BITS_PER_BYTE); \ | ||||||
|  |     } while (0) | ||||||
|  |  | ||||||
| static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size, | static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size, | ||||||
|                                       unsigned off, unsigned size) |                                       unsigned off, unsigned size) | ||||||
| @@ -974,22 +980,17 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) | |||||||
|  |  | ||||||
| static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size) | static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size) | ||||||
| { | { | ||||||
|     *ACPI_BUILD_PTR(start, size, acpi_pci32_start[0], uint32_t) = |     ACPI_BUILD_SET_LE(start, size, acpi_pci32_start[0], 32, pci->w32.begin); | ||||||
|         cpu_to_le32(pci->w32.begin); |  | ||||||
|  |  | ||||||
|     *ACPI_BUILD_PTR(start, size, acpi_pci32_end[0], uint32_t) = |     ACPI_BUILD_SET_LE(start, size, acpi_pci32_end[0], 32, pci->w32.end - 1); | ||||||
|         cpu_to_le32(pci->w32.end - 1); |  | ||||||
|  |  | ||||||
|     if (pci->w64.end || pci->w64.begin) { |     if (pci->w64.end || pci->w64.begin) { | ||||||
|         *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 1; |         ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 1); | ||||||
|         *ACPI_BUILD_PTR(start, size, acpi_pci64_start[0], uint64_t) = |         ACPI_BUILD_SET_LE(start, size, acpi_pci64_start[0], 64, pci->w64.begin); | ||||||
|             cpu_to_le64(pci->w64.begin); |         ACPI_BUILD_SET_LE(start, size, acpi_pci64_end[0], 64, pci->w64.end - 1); | ||||||
|         *ACPI_BUILD_PTR(start, size, acpi_pci64_end[0], uint64_t) = |         ACPI_BUILD_SET_LE(start, size, acpi_pci64_length[0], 64, pci->w64.end - pci->w64.begin); | ||||||
|             cpu_to_le64(pci->w64.end - 1); |  | ||||||
|         *ACPI_BUILD_PTR(start, size, acpi_pci64_length[0], uint64_t) = |  | ||||||
|             cpu_to_le64(pci->w64.end - pci->w64.begin); |  | ||||||
|     } else { |     } else { | ||||||
|         *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 0; |         ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 0); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -406,7 +406,7 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!kvm_enabled()) { |     if (!kvm_enabled()) { | ||||||
|         cpu_restore_state(env, env->mem_io_pc); |         cpu_restore_state(cs, cs->mem_io_pc); | ||||||
|         cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, |         cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, | ||||||
|                              ¤t_flags); |                              ¤t_flags); | ||||||
|     } |     } | ||||||
| @@ -448,8 +448,8 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip) | |||||||
|  |  | ||||||
|     if (!kvm_enabled()) { |     if (!kvm_enabled()) { | ||||||
|         cs->current_tb = NULL; |         cs->current_tb = NULL; | ||||||
|         tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); |         tb_gen_code(cs, current_pc, current_cs_base, current_flags, 1); | ||||||
|         cpu_resume_from_signal(env, NULL); |         cpu_resume_from_signal(cs, NULL); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -266,13 +266,15 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args) | |||||||
| { | { | ||||||
|     smbios_type1_defaults = false; |     smbios_type1_defaults = false; | ||||||
|     gigabyte_align = false; |     gigabyte_align = false; | ||||||
|  |     option_rom_has_mr = true; | ||||||
|  |     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(QEMUMachineInitArgs *args) | ||||||
| { | { | ||||||
|     pc_compat_1_7(args); |     pc_compat_1_7(args); | ||||||
|     has_pci_info = false; |     has_pci_info = false; | ||||||
|     rom_file_in_ram = false; |     rom_file_has_mr = false; | ||||||
|     has_acpi_build = false; |     has_acpi_build = false; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -298,7 +300,7 @@ static void pc_compat_1_3(QEMUMachineInitArgs *args) | |||||||
| static void pc_compat_1_2(QEMUMachineInitArgs *args) | static void pc_compat_1_2(QEMUMachineInitArgs *args) | ||||||
| { | { | ||||||
|     pc_compat_1_3(args); |     pc_compat_1_3(args); | ||||||
|     disable_kvm_pv_eoi(); |     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pc_init_pci_1_7(QEMUMachineInitArgs *args) | static void pc_init_pci_1_7(QEMUMachineInitArgs *args) | ||||||
| @@ -344,7 +346,7 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args) | |||||||
|     has_pci_info = false; |     has_pci_info = false; | ||||||
|     has_acpi_build = false; |     has_acpi_build = false; | ||||||
|     smbios_type1_defaults = false; |     smbios_type1_defaults = false; | ||||||
|     disable_kvm_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(args, 1, 0); | ||||||
| } | } | ||||||
| @@ -357,7 +359,7 @@ static void pc_init_isa(QEMUMachineInitArgs *args) | |||||||
|     if (!args->cpu_model) { |     if (!args->cpu_model) { | ||||||
|         args->cpu_model = "486"; |         args->cpu_model = "486"; | ||||||
|     } |     } | ||||||
|     disable_kvm_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(args, 0, 1); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -244,13 +244,15 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args) | |||||||
| { | { | ||||||
|     smbios_type1_defaults = false; |     smbios_type1_defaults = false; | ||||||
|     gigabyte_align = false; |     gigabyte_align = false; | ||||||
|  |     option_rom_has_mr = true; | ||||||
|  |     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(QEMUMachineInitArgs *args) | ||||||
| { | { | ||||||
|     pc_compat_1_7(args); |     pc_compat_1_7(args); | ||||||
|     has_pci_info = false; |     has_pci_info = false; | ||||||
|     rom_file_in_ram = false; |     rom_file_has_mr = false; | ||||||
|     has_acpi_build = false; |     has_acpi_build = false; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -148,7 +148,7 @@ typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu, | |||||||
|                                   uint32_t *field, bool to_kernel); |                                   uint32_t *field, bool to_kernel); | ||||||
|  |  | ||||||
| /* synthetic translate function used for clear/set registers to completely | /* synthetic translate function used for clear/set registers to completely | ||||||
|  * clear a setting using a clear-register before setting the remaing bits |  * clear a setting using a clear-register before setting the remaining bits | ||||||
|  * using a set-register */ |  * using a set-register */ | ||||||
| static void translate_clear(GICState *s, int irq, int cpu, | static void translate_clear(GICState *s, int irq, int cpu, | ||||||
|                             uint32_t *field, bool to_kernel) |                             uint32_t *field, bool to_kernel) | ||||||
|   | |||||||
| @@ -269,7 +269,16 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val) | |||||||
|  |  | ||||||
| static void ics_kvm_reset(DeviceState *dev) | static void ics_kvm_reset(DeviceState *dev) | ||||||
| { | { | ||||||
|     ics_set_kvm_state(ICS(dev), 1); |     ICSState *ics = ICS(dev); | ||||||
|  |     int i; | ||||||
|  |  | ||||||
|  |     memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs); | ||||||
|  |     for (i = 0; i < ics->nr_irqs; i++) { | ||||||
|  |         ics->irqs[i].priority = 0xff; | ||||||
|  |         ics->irqs[i].saved_priority = 0xff; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ics_set_kvm_state(ics, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ics_kvm_realize(DeviceState *dev, Error **errp) | static void ics_kvm_realize(DeviceState *dev, Error **errp) | ||||||
|   | |||||||
| @@ -13,7 +13,8 @@ | |||||||
| #include "hw/ssi.h" | #include "hw/ssi.h" | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     SSISlave ssidev; |     SSISlave parent_obj; | ||||||
|  |  | ||||||
|     qemu_irq interrupt; |     qemu_irq interrupt; | ||||||
|     uint8_t tb1, rb2, rb3; |     uint8_t tb1, rb2, rb3; | ||||||
|     int cycle; |     int cycle; | ||||||
| @@ -22,6 +23,14 @@ typedef struct { | |||||||
|     int inputs, com; |     int inputs, com; | ||||||
| } MAX111xState; | } MAX111xState; | ||||||
|  |  | ||||||
|  | #define TYPE_MAX_111X "max111x" | ||||||
|  |  | ||||||
|  | #define MAX_111X(obj) \ | ||||||
|  |     OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X) | ||||||
|  |  | ||||||
|  | #define TYPE_MAX_1110 "max1110" | ||||||
|  | #define TYPE_MAX_1111 "max1111" | ||||||
|  |  | ||||||
| /* Control-byte bitfields */ | /* Control-byte bitfields */ | ||||||
| #define CB_PD0		(1 << 0) | #define CB_PD0		(1 << 0) | ||||||
| #define CB_PD1		(1 << 1) | #define CB_PD1		(1 << 1) | ||||||
| @@ -92,7 +101,7 @@ static void max111x_write(MAX111xState *s, uint32_t value) | |||||||
|  |  | ||||||
| static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) | static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) | ||||||
| { | { | ||||||
|     MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev); |     MAX111xState *s = MAX_111X(dev); | ||||||
|     max111x_write(s, value); |     max111x_write(s, value); | ||||||
|     return max111x_read(s); |     return max111x_read(s); | ||||||
| } | } | ||||||
| @@ -103,7 +112,7 @@ static const VMStateDescription vmstate_max111x = { | |||||||
|     .minimum_version_id = 1, |     .minimum_version_id = 1, | ||||||
|     .minimum_version_id_old = 1, |     .minimum_version_id_old = 1, | ||||||
|     .fields      = (VMStateField[]) { |     .fields      = (VMStateField[]) { | ||||||
|         VMSTATE_SSI_SLAVE(ssidev, MAX111xState), |         VMSTATE_SSI_SLAVE(parent_obj, MAX111xState), | ||||||
|         VMSTATE_UINT8(tb1, MAX111xState), |         VMSTATE_UINT8(tb1, MAX111xState), | ||||||
|         VMSTATE_UINT8(rb2, MAX111xState), |         VMSTATE_UINT8(rb2, MAX111xState), | ||||||
|         VMSTATE_UINT8(rb3, MAX111xState), |         VMSTATE_UINT8(rb3, MAX111xState), | ||||||
| @@ -115,11 +124,12 @@ static const VMStateDescription vmstate_max111x = { | |||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int max111x_init(SSISlave *dev, int inputs) | static int max111x_init(SSISlave *d, int inputs) | ||||||
| { | { | ||||||
|     MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev); |     DeviceState *dev = DEVICE(d); | ||||||
|  |     MAX111xState *s = MAX_111X(dev); | ||||||
|  |  | ||||||
|     qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1); |     qdev_init_gpio_out(dev, &s->interrupt, 1); | ||||||
|  |  | ||||||
|     s->inputs = inputs; |     s->inputs = inputs; | ||||||
|     /* TODO: add a user interface for setting these */ |     /* TODO: add a user interface for setting these */ | ||||||
| @@ -133,7 +143,7 @@ static int max111x_init(SSISlave *dev, int inputs) | |||||||
|     s->input[7] = 0x80; |     s->input[7] = 0x80; | ||||||
|     s->com = 0; |     s->com = 0; | ||||||
|  |  | ||||||
|     vmstate_register(&dev->qdev, -1, &vmstate_max111x, s); |     vmstate_register(dev, -1, &vmstate_max111x, s); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -149,23 +159,36 @@ static int max1111_init(SSISlave *dev) | |||||||
|  |  | ||||||
| void max111x_set_input(DeviceState *dev, int line, uint8_t value) | void max111x_set_input(DeviceState *dev, int line, uint8_t value) | ||||||
| { | { | ||||||
|     MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, SSI_SLAVE_FROM_QDEV(dev)); |     MAX111xState *s = MAX_111X(dev); | ||||||
|     assert(line >= 0 && line < s->inputs); |     assert(line >= 0 && line < s->inputs); | ||||||
|     s->input[line] = value; |     s->input[line] = value; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void max111x_class_init(ObjectClass *klass, void *data) | ||||||
|  | { | ||||||
|  |     SSISlaveClass *k = SSI_SLAVE_CLASS(klass); | ||||||
|  |  | ||||||
|  |     k->transfer = max111x_transfer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const TypeInfo max111x_info = { | ||||||
|  |     .name          = TYPE_MAX_111X, | ||||||
|  |     .parent        = TYPE_SSI_SLAVE, | ||||||
|  |     .instance_size = sizeof(MAX111xState), | ||||||
|  |     .class_init    = max111x_class_init, | ||||||
|  |     .abstract      = true, | ||||||
|  | }; | ||||||
|  |  | ||||||
| static void max1110_class_init(ObjectClass *klass, void *data) | static void max1110_class_init(ObjectClass *klass, void *data) | ||||||
| { | { | ||||||
|     SSISlaveClass *k = SSI_SLAVE_CLASS(klass); |     SSISlaveClass *k = SSI_SLAVE_CLASS(klass); | ||||||
|  |  | ||||||
|     k->init = max1110_init; |     k->init = max1110_init; | ||||||
|     k->transfer = max111x_transfer; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static const TypeInfo max1110_info = { | static const TypeInfo max1110_info = { | ||||||
|     .name          = "max1110", |     .name          = TYPE_MAX_1110, | ||||||
|     .parent        = TYPE_SSI_SLAVE, |     .parent        = TYPE_MAX_111X, | ||||||
|     .instance_size = sizeof(MAX111xState), |  | ||||||
|     .class_init    = max1110_class_init, |     .class_init    = max1110_class_init, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -174,18 +197,17 @@ static void max1111_class_init(ObjectClass *klass, void *data) | |||||||
|     SSISlaveClass *k = SSI_SLAVE_CLASS(klass); |     SSISlaveClass *k = SSI_SLAVE_CLASS(klass); | ||||||
|  |  | ||||||
|     k->init = max1111_init; |     k->init = max1111_init; | ||||||
|     k->transfer = max111x_transfer; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static const TypeInfo max1111_info = { | static const TypeInfo max1111_info = { | ||||||
|     .name          = "max1111", |     .name          = TYPE_MAX_1111, | ||||||
|     .parent        = TYPE_SSI_SLAVE, |     .parent        = TYPE_MAX_111X, | ||||||
|     .instance_size = sizeof(MAX111xState), |  | ||||||
|     .class_init    = max1111_class_init, |     .class_init    = max1111_class_init, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void max111x_register_types(void) | static void max111x_register_types(void) | ||||||
| { | { | ||||||
|  |     type_register_static(&max111x_info); | ||||||
|     type_register_static(&max1110_info); |     type_register_static(&max1110_info); | ||||||
|     type_register_static(&max1111_info); |     type_register_static(&max1111_info); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -195,8 +195,8 @@ static void process_tx_fcb(eTSEC *etsec) | |||||||
|  |  | ||||||
|     /* if packet is IP4 and IP checksum is requested */ |     /* if packet is IP4 and IP checksum is requested */ | ||||||
|     if (flags & FCB_TX_IP && flags & FCB_TX_CIP) { |     if (flags & FCB_TX_IP && flags & FCB_TX_CIP) { | ||||||
|         /* do IP4 checksum (TODO This funtion does TCP/UDP checksum but not sure |         /* do IP4 checksum (TODO This function does TCP/UDP checksum | ||||||
|          * if it also does IP4 checksum. */ |          * but not sure if it also does IP4 checksum.) */ | ||||||
|         net_checksum_calculate(etsec->tx_buffer + 8, |         net_checksum_calculate(etsec->tx_buffer + 8, | ||||||
|                 etsec->tx_buffer_len - 8); |                 etsec->tx_buffer_len - 8); | ||||||
|     } |     } | ||||||
| @@ -592,7 +592,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr) | |||||||
|  |  | ||||||
|                 /* TODO: Broadcast and Multicast */ |                 /* TODO: Broadcast and Multicast */ | ||||||
|  |  | ||||||
|                 if (bd.flags | BD_INTERRUPT) { |                 if (bd.flags & BD_INTERRUPT) { | ||||||
|                     /* Set RXFx */ |                     /* Set RXFx */ | ||||||
|                     etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr); |                     etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr); | ||||||
|  |  | ||||||
| @@ -601,7 +601,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr) | |||||||
|                 } |                 } | ||||||
|  |  | ||||||
|             } else { |             } else { | ||||||
|                 if (bd.flags | BD_INTERRUPT) { |                 if (bd.flags & BD_INTERRUPT) { | ||||||
|                     /* Set IEVENT */ |                     /* Set IEVENT */ | ||||||
|                     ievent_set(etsec, IEVENT_RXB); |                     ievent_set(etsec, IEVENT_RXB); | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -28,7 +28,9 @@ | |||||||
| #include "hw/pci/pci_bus.h" | #include "hw/pci/pci_bus.h" | ||||||
| #include "hw/pci/pci_host.h" | #include "hw/pci/pci_host.h" | ||||||
| #include "hw/i386/pc.h" | #include "hw/i386/pc.h" | ||||||
|  | #include "hw/loader.h" | ||||||
| #include "exec/address-spaces.h" | #include "exec/address-spaces.h" | ||||||
|  | #include "elf.h" | ||||||
|  |  | ||||||
| #define TYPE_RAVEN_PCI_DEVICE "raven" | #define TYPE_RAVEN_PCI_DEVICE "raven" | ||||||
| #define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" | #define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" | ||||||
| @@ -38,6 +40,10 @@ | |||||||
|  |  | ||||||
| typedef struct RavenPCIState { | typedef struct RavenPCIState { | ||||||
|     PCIDevice dev; |     PCIDevice dev; | ||||||
|  |  | ||||||
|  |     uint32_t elf_machine; | ||||||
|  |     char *bios_name; | ||||||
|  |     MemoryRegion bios; | ||||||
| } RavenPCIState; | } RavenPCIState; | ||||||
|  |  | ||||||
| #define RAVEN_PCI_HOST_BRIDGE(obj) \ | #define RAVEN_PCI_HOST_BRIDGE(obj) \ | ||||||
| @@ -52,6 +58,8 @@ typedef struct PRePPCIState { | |||||||
|     RavenPCIState pci_dev; |     RavenPCIState pci_dev; | ||||||
| } PREPPCIState; | } PREPPCIState; | ||||||
|  |  | ||||||
|  | #define BIOS_SIZE (1024 * 1024) | ||||||
|  |  | ||||||
| static inline uint32_t PPC_PCIIO_config(hwaddr addr) | static inline uint32_t PPC_PCIIO_config(hwaddr addr) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
| @@ -169,10 +177,45 @@ static void raven_pcihost_initfn(Object *obj) | |||||||
|  |  | ||||||
| static int raven_init(PCIDevice *d) | static int raven_init(PCIDevice *d) | ||||||
| { | { | ||||||
|  |     RavenPCIState *s = RAVEN_PCI_DEVICE(d); | ||||||
|  |     char *filename; | ||||||
|  |     int bios_size = -1; | ||||||
|  |  | ||||||
|     d->config[0x0C] = 0x08; // cache_line_size |     d->config[0x0C] = 0x08; // cache_line_size | ||||||
|     d->config[0x0D] = 0x10; // latency_timer |     d->config[0x0D] = 0x10; // latency_timer | ||||||
|     d->config[0x34] = 0x00; // capabilities_pointer |     d->config[0x34] = 0x00; // capabilities_pointer | ||||||
|  |  | ||||||
|  |     memory_region_init_ram(&s->bios, OBJECT(s), "bios", BIOS_SIZE); | ||||||
|  |     memory_region_set_readonly(&s->bios, true); | ||||||
|  |     memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE), | ||||||
|  |                                 &s->bios); | ||||||
|  |     vmstate_register_ram_global(&s->bios); | ||||||
|  |     if (s->bios_name) { | ||||||
|  |         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name); | ||||||
|  |         if (filename) { | ||||||
|  |             if (s->elf_machine != EM_NONE) { | ||||||
|  |                 bios_size = load_elf(filename, NULL, NULL, NULL, | ||||||
|  |                                      NULL, NULL, 1, s->elf_machine, 0); | ||||||
|  |             } | ||||||
|  |             if (bios_size < 0) { | ||||||
|  |                 bios_size = get_image_size(filename); | ||||||
|  |                 if (bios_size > 0 && bios_size <= BIOS_SIZE) { | ||||||
|  |                     hwaddr bios_addr; | ||||||
|  |                     bios_size = (bios_size + 0xfff) & ~0xfff; | ||||||
|  |                     bios_addr = (uint32_t)(-BIOS_SIZE); | ||||||
|  |                     bios_size = load_image_targphys(filename, bios_addr, | ||||||
|  |                                                     bios_size); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (bios_size < 0 || bios_size > BIOS_SIZE) { | ||||||
|  |             hw_error("qemu: could not load bios image '%s'\n", s->bios_name); | ||||||
|  |         } | ||||||
|  |         if (filename) { | ||||||
|  |             g_free(filename); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -212,12 +255,20 @@ static const TypeInfo raven_info = { | |||||||
|     .class_init = raven_class_init, |     .class_init = raven_class_init, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | static Property raven_pcihost_properties[] = { | ||||||
|  |     DEFINE_PROP_UINT32("elf-machine", PREPPCIState, pci_dev.elf_machine, | ||||||
|  |                        EM_NONE), | ||||||
|  |     DEFINE_PROP_STRING("bios-name", PREPPCIState, pci_dev.bios_name), | ||||||
|  |     DEFINE_PROP_END_OF_LIST() | ||||||
|  | }; | ||||||
|  |  | ||||||
| static void raven_pcihost_class_init(ObjectClass *klass, void *data) | static void raven_pcihost_class_init(ObjectClass *klass, void *data) | ||||||
| { | { | ||||||
|     DeviceClass *dc = DEVICE_CLASS(klass); |     DeviceClass *dc = DEVICE_CLASS(klass); | ||||||
|  |  | ||||||
|     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); |     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); | ||||||
|     dc->realize = raven_pcihost_realizefn; |     dc->realize = raven_pcihost_realizefn; | ||||||
|  |     dc->props = raven_pcihost_properties; | ||||||
|     dc->fw_name = "pci"; |     dc->fw_name = "pci"; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -272,7 +272,7 @@ static void mch_update_smram(MCHPCIState *mch) | |||||||
|     PCIDevice *pd = PCI_DEVICE(mch); |     PCIDevice *pd = PCI_DEVICE(mch); | ||||||
|  |  | ||||||
|     memory_region_transaction_begin(); |     memory_region_transaction_begin(); | ||||||
|     smram_update(&mch->smram_region, pd->config[MCH_HOST_BRDIGE_SMRAM], |     smram_update(&mch->smram_region, pd->config[MCH_HOST_BRIDGE_SMRAM], | ||||||
|                     mch->smm_enabled); |                     mch->smm_enabled); | ||||||
|     memory_region_transaction_commit(); |     memory_region_transaction_commit(); | ||||||
| } | } | ||||||
| @@ -283,7 +283,7 @@ static void mch_set_smm(int smm, void *arg) | |||||||
|     PCIDevice *pd = PCI_DEVICE(mch); |     PCIDevice *pd = PCI_DEVICE(mch); | ||||||
|  |  | ||||||
|     memory_region_transaction_begin(); |     memory_region_transaction_begin(); | ||||||
|     smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRDIGE_SMRAM], |     smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRIDGE_SMRAM], | ||||||
|                     &mch->smram_region); |                     &mch->smram_region); | ||||||
|     memory_region_transaction_commit(); |     memory_region_transaction_commit(); | ||||||
| } | } | ||||||
| @@ -306,8 +306,8 @@ static void mch_write_config(PCIDevice *d, | |||||||
|         mch_update_pciexbar(mch); |         mch_update_pciexbar(mch); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (ranges_overlap(address, len, MCH_HOST_BRDIGE_SMRAM, |     if (ranges_overlap(address, len, MCH_HOST_BRIDGE_SMRAM, | ||||||
|                        MCH_HOST_BRDIGE_SMRAM_SIZE)) { |                        MCH_HOST_BRIDGE_SMRAM_SIZE)) { | ||||||
|         mch_update_smram(mch); |         mch_update_smram(mch); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -347,7 +347,7 @@ static void mch_reset(DeviceState *qdev) | |||||||
|     pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR, |     pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR, | ||||||
|                  MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT); |                  MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT); | ||||||
|  |  | ||||||
|     d->config[MCH_HOST_BRDIGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT; |     d->config[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT; | ||||||
|  |  | ||||||
|     mch_update(mch); |     mch_update(mch); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								hw/pci/pci.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								hw/pci/pci.c
									
									
									
									
									
								
							| @@ -48,7 +48,6 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent); | |||||||
| static char *pcibus_get_dev_path(DeviceState *dev); | static char *pcibus_get_dev_path(DeviceState *dev); | ||||||
| static char *pcibus_get_fw_dev_path(DeviceState *dev); | static char *pcibus_get_fw_dev_path(DeviceState *dev); | ||||||
| static void pcibus_reset(BusState *qbus); | static void pcibus_reset(BusState *qbus); | ||||||
| static void pci_bus_finalize(Object *obj); |  | ||||||
|  |  | ||||||
| static Property pci_props[] = { | static Property pci_props[] = { | ||||||
|     DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), |     DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), | ||||||
| @@ -61,6 +60,34 @@ static Property pci_props[] = { | |||||||
|     DEFINE_PROP_END_OF_LIST() |     DEFINE_PROP_END_OF_LIST() | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | static const VMStateDescription vmstate_pcibus = { | ||||||
|  |     .name = "PCIBUS", | ||||||
|  |     .version_id = 1, | ||||||
|  |     .minimum_version_id = 1, | ||||||
|  |     .minimum_version_id_old = 1, | ||||||
|  |     .fields      = (VMStateField[]) { | ||||||
|  |         VMSTATE_INT32_EQUAL(nirq, PCIBus), | ||||||
|  |         VMSTATE_VARRAY_INT32(irq_count, PCIBus, | ||||||
|  |                              nirq, 0, vmstate_info_int32, | ||||||
|  |                              int32_t), | ||||||
|  |         VMSTATE_END_OF_LIST() | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static void pci_bus_realize(BusState *qbus, Error **errp) | ||||||
|  | { | ||||||
|  |     PCIBus *bus = PCI_BUS(qbus); | ||||||
|  |  | ||||||
|  |     vmstate_register(NULL, -1, &vmstate_pcibus, bus); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pci_bus_unrealize(BusState *qbus, Error **errp) | ||||||
|  | { | ||||||
|  |     PCIBus *bus = PCI_BUS(qbus); | ||||||
|  |  | ||||||
|  |     vmstate_unregister(NULL, &vmstate_pcibus, bus); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void pci_bus_class_init(ObjectClass *klass, void *data) | static void pci_bus_class_init(ObjectClass *klass, void *data) | ||||||
| { | { | ||||||
|     BusClass *k = BUS_CLASS(klass); |     BusClass *k = BUS_CLASS(klass); | ||||||
| @@ -68,6 +95,8 @@ static void pci_bus_class_init(ObjectClass *klass, void *data) | |||||||
|     k->print_dev = pcibus_dev_print; |     k->print_dev = pcibus_dev_print; | ||||||
|     k->get_dev_path = pcibus_get_dev_path; |     k->get_dev_path = pcibus_get_dev_path; | ||||||
|     k->get_fw_dev_path = pcibus_get_fw_dev_path; |     k->get_fw_dev_path = pcibus_get_fw_dev_path; | ||||||
|  |     k->realize = pci_bus_realize; | ||||||
|  |     k->unrealize = pci_bus_unrealize; | ||||||
|     k->reset = pcibus_reset; |     k->reset = pcibus_reset; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -75,7 +104,6 @@ static const TypeInfo pci_bus_info = { | |||||||
|     .name = TYPE_PCI_BUS, |     .name = TYPE_PCI_BUS, | ||||||
|     .parent = TYPE_BUS, |     .parent = TYPE_BUS, | ||||||
|     .instance_size = sizeof(PCIBus), |     .instance_size = sizeof(PCIBus), | ||||||
|     .instance_finalize = pci_bus_finalize, |  | ||||||
|     .class_init = pci_bus_class_init, |     .class_init = pci_bus_class_init, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -95,17 +123,6 @@ static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; | |||||||
|  |  | ||||||
| static QLIST_HEAD(, PCIHostState) pci_host_bridges; | static QLIST_HEAD(, PCIHostState) pci_host_bridges; | ||||||
|  |  | ||||||
| static const VMStateDescription vmstate_pcibus = { |  | ||||||
|     .name = "PCIBUS", |  | ||||||
|     .version_id = 1, |  | ||||||
|     .minimum_version_id = 1, |  | ||||||
|     .minimum_version_id_old = 1, |  | ||||||
|     .fields      = (VMStateField []) { |  | ||||||
|         VMSTATE_INT32_EQUAL(nirq, PCIBus), |  | ||||||
|         VMSTATE_VARRAY_INT32(irq_count, PCIBus, nirq, 0, vmstate_info_int32, int32_t), |  | ||||||
|         VMSTATE_END_OF_LIST() |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| static int pci_bar(PCIDevice *d, int reg) | static int pci_bar(PCIDevice *d, int reg) | ||||||
| { | { | ||||||
|     uint8_t type; |     uint8_t type; | ||||||
| @@ -299,8 +316,6 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent, | |||||||
|     QLIST_INIT(&bus->child); |     QLIST_INIT(&bus->child); | ||||||
|  |  | ||||||
|     pci_host_bus_register(bus, parent); |     pci_host_bus_register(bus, parent); | ||||||
|  |  | ||||||
|     vmstate_register(NULL, -1, &vmstate_pcibus, bus); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| bool pci_bus_is_express(PCIBus *bus) | bool pci_bus_is_express(PCIBus *bus) | ||||||
| @@ -369,12 +384,6 @@ int pci_bus_num(PCIBus *s) | |||||||
|     return s->parent_dev->config[PCI_SECONDARY_BUS]; |     return s->parent_dev->config[PCI_SECONDARY_BUS]; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void pci_bus_finalize(Object *obj) |  | ||||||
| { |  | ||||||
|     PCIBus *bus = PCI_BUS(obj); |  | ||||||
|     vmstate_unregister(NULL, &vmstate_pcibus, bus); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) | static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) | ||||||
| { | { | ||||||
|     PCIDevice *s = container_of(pv, PCIDevice, config); |     PCIDevice *s = container_of(pv, PCIDevice, config); | ||||||
|   | |||||||
| @@ -472,14 +472,13 @@ static void ppce500_cpu_reset_sec(void *opaque) | |||||||
| { | { | ||||||
|     PowerPCCPU *cpu = opaque; |     PowerPCCPU *cpu = opaque; | ||||||
|     CPUState *cs = CPU(cpu); |     CPUState *cs = CPU(cpu); | ||||||
|     CPUPPCState *env = &cpu->env; |  | ||||||
|  |  | ||||||
|     cpu_reset(cs); |     cpu_reset(cs); | ||||||
|  |  | ||||||
|     /* Secondary CPU starts in halted state for now. Needs to change when |     /* Secondary CPU starts in halted state for now. Needs to change when | ||||||
|        implementing non-kernel boot. */ |        implementing non-kernel boot. */ | ||||||
|     cs->halted = 1; |     cs->halted = 1; | ||||||
|     env->exception_index = EXCP_HLT; |     cs->exception_index = EXCP_HLT; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ppce500_cpu_reset(void *opaque) | static void ppce500_cpu_reset(void *opaque) | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ | |||||||
| ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, | ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, | ||||||
|                                 uint32_t flags) |                                 uint32_t flags) | ||||||
| { | { | ||||||
|     CPUState *cs = ENV_GET_CPU(env); |     CPUState *cs = CPU(ppc_env_get_cpu(env)); | ||||||
|     ram_addr_t bdloc; |     ram_addr_t bdloc; | ||||||
|     int i, n; |     int i, n; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -117,7 +117,7 @@ static void spin_kick(void *data) | |||||||
|     mmubooke_create_initial_mapping(env, 0, map_start, map_size); |     mmubooke_create_initial_mapping(env, 0, map_start, map_size); | ||||||
|  |  | ||||||
|     cpu->halted = 0; |     cpu->halted = 0; | ||||||
|     env->exception_index = -1; |     cpu->exception_index = -1; | ||||||
|     cpu->stopped = false; |     cpu->stopped = false; | ||||||
|     qemu_cpu_kick(cpu); |     qemu_cpu_kick(cpu); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -456,7 +456,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) | |||||||
|     MemoryRegion *sysmem = get_system_memory(); |     MemoryRegion *sysmem = get_system_memory(); | ||||||
|     PowerPCCPU *cpu = NULL; |     PowerPCCPU *cpu = NULL; | ||||||
|     CPUPPCState *env = NULL; |     CPUPPCState *env = NULL; | ||||||
|     char *filename; |  | ||||||
|     nvram_t nvram; |     nvram_t nvram; | ||||||
|     M48t59State *m48t59; |     M48t59State *m48t59; | ||||||
|     MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1); |     MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1); | ||||||
| @@ -464,9 +463,8 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) | |||||||
| #if 0 | #if 0 | ||||||
|     MemoryRegion *xcsr = g_new(MemoryRegion, 1); |     MemoryRegion *xcsr = g_new(MemoryRegion, 1); | ||||||
| #endif | #endif | ||||||
|     int linux_boot, i, nb_nics1, bios_size; |     int linux_boot, i, nb_nics1; | ||||||
|     MemoryRegion *ram = g_new(MemoryRegion, 1); |     MemoryRegion *ram = g_new(MemoryRegion, 1); | ||||||
|     MemoryRegion *bios = g_new(MemoryRegion, 1); |  | ||||||
|     uint32_t kernel_base, initrd_base; |     uint32_t kernel_base, initrd_base; | ||||||
|     long kernel_size, initrd_size; |     long kernel_size, initrd_size; | ||||||
|     DeviceState *dev; |     DeviceState *dev; | ||||||
| @@ -509,43 +507,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) | |||||||
|     vmstate_register_ram_global(ram); |     vmstate_register_ram_global(ram); | ||||||
|     memory_region_add_subregion(sysmem, 0, ram); |     memory_region_add_subregion(sysmem, 0, ram); | ||||||
|  |  | ||||||
|     /* allocate and load BIOS */ |  | ||||||
|     memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE); |  | ||||||
|     memory_region_set_readonly(bios, true); |  | ||||||
|     memory_region_add_subregion(sysmem, (uint32_t)(-BIOS_SIZE), bios); |  | ||||||
|     vmstate_register_ram_global(bios); |  | ||||||
|     if (bios_name == NULL) |  | ||||||
|         bios_name = BIOS_FILENAME; |  | ||||||
|     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); |  | ||||||
|     if (filename) { |  | ||||||
|         bios_size = load_elf(filename, NULL, NULL, NULL, |  | ||||||
|                              NULL, NULL, 1, ELF_MACHINE, 0); |  | ||||||
|         if (bios_size < 0) { |  | ||||||
|             bios_size = get_image_size(filename); |  | ||||||
|             if (bios_size > 0 && bios_size <= BIOS_SIZE) { |  | ||||||
|                 hwaddr bios_addr; |  | ||||||
|                 bios_size = (bios_size + 0xfff) & ~0xfff; |  | ||||||
|                 bios_addr = (uint32_t)(-bios_size); |  | ||||||
|                 bios_size = load_image_targphys(filename, bios_addr, bios_size); |  | ||||||
|             } |  | ||||||
|             if (bios_size > BIOS_SIZE) { |  | ||||||
|                 fprintf(stderr, "qemu: PReP bios '%s' is too large (0x%x)\n", |  | ||||||
|                         bios_name, bios_size); |  | ||||||
|                 exit(1); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         bios_size = -1; |  | ||||||
|     } |  | ||||||
|     if (bios_size < 0 && !qtest_enabled()) { |  | ||||||
|         fprintf(stderr, "qemu: could not load PPC PReP bios '%s'\n", |  | ||||||
|                 bios_name); |  | ||||||
|         exit(1); |  | ||||||
|     } |  | ||||||
|     if (filename) { |  | ||||||
|         g_free(filename); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (linux_boot) { |     if (linux_boot) { | ||||||
|         kernel_base = KERNEL_LOAD_ADDR; |         kernel_base = KERNEL_LOAD_ADDR; | ||||||
|         /* now we can load the kernel */ |         /* now we can load the kernel */ | ||||||
| @@ -593,6 +554,11 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     dev = qdev_create(NULL, "raven-pcihost"); |     dev = qdev_create(NULL, "raven-pcihost"); | ||||||
|  |     if (bios_name == NULL) { | ||||||
|  |         bios_name = BIOS_FILENAME; | ||||||
|  |     } | ||||||
|  |     qdev_prop_set_string(dev, "bios-name", bios_name); | ||||||
|  |     qdev_prop_set_uint32(dev, "elf-machine", ELF_MACHINE); | ||||||
|     pcihost = PCI_HOST_BRIDGE(dev); |     pcihost = PCI_HOST_BRIDGE(dev); | ||||||
|     object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL); |     object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL); | ||||||
|     qdev_init_nofail(dev); |     qdev_init_nofail(dev); | ||||||
|   | |||||||
| @@ -781,13 +781,15 @@ static int spapr_vga_init(PCIBus *pci_bus) | |||||||
| { | { | ||||||
|     switch (vga_interface_type) { |     switch (vga_interface_type) { | ||||||
|     case VGA_NONE: |     case VGA_NONE: | ||||||
|  |         return false; | ||||||
|  |     case VGA_DEVICE: | ||||||
|  |         return true; | ||||||
|     case VGA_STD: |     case VGA_STD: | ||||||
|         return pci_vga_init(pci_bus) != NULL; |         return pci_vga_init(pci_bus) != NULL; | ||||||
|     default: |     default: | ||||||
|         fprintf(stderr, "This vga model is not supported," |         fprintf(stderr, "This vga model is not supported," | ||||||
|                 "currently it only supports -vga std\n"); |                 "currently it only supports -vga std\n"); | ||||||
|         exit(0); |         exit(0); | ||||||
|         break; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -356,7 +356,7 @@ static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|  |  | ||||||
| static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa) | static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa) | ||||||
| { | { | ||||||
|     CPUState *cs = ENV_GET_CPU(env); |     CPUState *cs = CPU(ppc_env_get_cpu(env)); | ||||||
|     uint16_t size; |     uint16_t size; | ||||||
|     uint8_t tmp; |     uint8_t tmp; | ||||||
|  |  | ||||||
| @@ -406,7 +406,7 @@ static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa) | |||||||
|  |  | ||||||
| static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr) | static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr) | ||||||
| { | { | ||||||
|     CPUState *cs = ENV_GET_CPU(env); |     CPUState *cs = CPU(ppc_env_get_cpu(env)); | ||||||
|     uint32_t size; |     uint32_t size; | ||||||
|  |  | ||||||
|     if (addr == 0) { |     if (addr == 0) { | ||||||
| @@ -442,7 +442,7 @@ static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr) | |||||||
|  |  | ||||||
| static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) | static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) | ||||||
| { | { | ||||||
|     CPUState *cs = ENV_GET_CPU(env); |     CPUState *cs = CPU(ppc_env_get_cpu(env)); | ||||||
|     uint32_t size; |     uint32_t size; | ||||||
|  |  | ||||||
|     if (addr == 0) { |     if (addr == 0) { | ||||||
| @@ -529,7 +529,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|     hreg_compute_hflags(env); |     hreg_compute_hflags(env); | ||||||
|     if (!cpu_has_work(cs)) { |     if (!cpu_has_work(cs)) { | ||||||
|         cs->halted = 1; |         cs->halted = 1; | ||||||
|         env->exception_index = EXCP_HLT; |         cs->exception_index = EXCP_HLT; | ||||||
|         cs->exit_request = 1; |         cs->exit_request = 1; | ||||||
|     } |     } | ||||||
|     return H_SUCCESS; |     return H_SUCCESS; | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ | |||||||
| #include "exec/address-spaces.h" | #include "exec/address-spaces.h" | ||||||
| #include <libfdt.h> | #include <libfdt.h> | ||||||
| #include "trace.h" | #include "trace.h" | ||||||
|  | #include "qemu/error-report.h" | ||||||
|  |  | ||||||
| #include "hw/pci/pci_bus.h" | #include "hw/pci/pci_bus.h" | ||||||
|  |  | ||||||
| @@ -292,7 +293,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|         ret_intr_type = RTAS_TYPE_MSIX; |         ret_intr_type = RTAS_TYPE_MSIX; | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func); |         error_report("rtas_ibm_change_msi(%u) is not implemented", func); | ||||||
|         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); |         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -326,7 +327,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|     /* Find a device number in the map to add or reuse the existing one */ |     /* Find a device number in the map to add or reuse the existing one */ | ||||||
|     ndev = spapr_msicfg_find(phb, config_addr, true); |     ndev = spapr_msicfg_find(phb, config_addr, true); | ||||||
|     if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) { |     if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) { | ||||||
|         fprintf(stderr, "No free entry for a new MSI device\n"); |         error_report("No free entry for a new MSI device"); | ||||||
|         rtas_st(rets, 0, RTAS_OUT_HW_ERROR); |         rtas_st(rets, 0, RTAS_OUT_HW_ERROR); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -335,7 +336,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|     /* Check if there is an old config and MSI number has not changed */ |     /* Check if there is an old config and MSI number has not changed */ | ||||||
|     if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) { |     if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) { | ||||||
|         /* Unexpected behaviour */ |         /* Unexpected behaviour */ | ||||||
|         fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev); |         error_report("Cannot reuse MSI config for device#%d", ndev); | ||||||
|         rtas_st(rets, 0, RTAS_OUT_HW_ERROR); |         rtas_st(rets, 0, RTAS_OUT_HW_ERROR); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -345,7 +346,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|         irq = spapr_allocate_irq_block(req_num, false, |         irq = spapr_allocate_irq_block(req_num, false, | ||||||
|                                        ret_intr_type == RTAS_TYPE_MSI); |                                        ret_intr_type == RTAS_TYPE_MSI); | ||||||
|         if (irq < 0) { |         if (irq < 0) { | ||||||
|             fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev); |             error_report("Cannot allocate MSIs for device#%d", ndev); | ||||||
|             rtas_st(rets, 0, RTAS_OUT_HW_ERROR); |             rtas_st(rets, 0, RTAS_OUT_HW_ERROR); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -505,12 +506,11 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) | |||||||
|     return &phb->iommu_as; |     return &phb->iommu_as; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int spapr_phb_init(SysBusDevice *s) | static void spapr_phb_realize(DeviceState *dev, Error **errp) | ||||||
| { | { | ||||||
|     DeviceState *dev = DEVICE(s); |     SysBusDevice *s = SYS_BUS_DEVICE(dev); | ||||||
|     sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); |     sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); | ||||||
|     PCIHostState *phb = PCI_HOST_BRIDGE(s); |     PCIHostState *phb = PCI_HOST_BRIDGE(s); | ||||||
|     const char *busname; |  | ||||||
|     char *namebuf; |     char *namebuf; | ||||||
|     int i; |     int i; | ||||||
|     PCIBus *bus; |     PCIBus *bus; | ||||||
| @@ -521,9 +521,9 @@ static int spapr_phb_init(SysBusDevice *s) | |||||||
|         if ((sphb->buid != -1) || (sphb->dma_liobn != -1) |         if ((sphb->buid != -1) || (sphb->dma_liobn != -1) | ||||||
|             || (sphb->mem_win_addr != -1) |             || (sphb->mem_win_addr != -1) | ||||||
|             || (sphb->io_win_addr != -1)) { |             || (sphb->io_win_addr != -1)) { | ||||||
|             fprintf(stderr, "Either \"index\" or other parameters must" |             error_setg(errp, "Either \"index\" or other parameters must" | ||||||
|                     " be specified for PAPR PHB, not both\n"); |                        " be specified for PAPR PHB, not both"); | ||||||
|             return -1; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index; |         sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index; | ||||||
| @@ -536,28 +536,28 @@ static int spapr_phb_init(SysBusDevice *s) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (sphb->buid == -1) { |     if (sphb->buid == -1) { | ||||||
|         fprintf(stderr, "BUID not specified for PHB\n"); |         error_setg(errp, "BUID not specified for PHB"); | ||||||
|         return -1; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (sphb->dma_liobn == -1) { |     if (sphb->dma_liobn == -1) { | ||||||
|         fprintf(stderr, "LIOBN not specified for PHB\n"); |         error_setg(errp, "LIOBN not specified for PHB"); | ||||||
|         return -1; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (sphb->mem_win_addr == -1) { |     if (sphb->mem_win_addr == -1) { | ||||||
|         fprintf(stderr, "Memory window address not specified for PHB\n"); |         error_setg(errp, "Memory window address not specified for PHB"); | ||||||
|         return -1; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (sphb->io_win_addr == -1) { |     if (sphb->io_win_addr == -1) { | ||||||
|         fprintf(stderr, "IO window address not specified for PHB\n"); |         error_setg(errp, "IO window address not specified for PHB"); | ||||||
|         return -1; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (find_phb(spapr, sphb->buid)) { |     if (find_phb(spapr, sphb->buid)) { | ||||||
|         fprintf(stderr, "PCI host bridges must have unique BUIDs\n"); |         error_setg(errp, "PCI host bridges must have unique BUIDs"); | ||||||
|         return -1; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid); |     sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid); | ||||||
| @@ -594,26 +594,8 @@ static int spapr_phb_init(SysBusDevice *s) | |||||||
|                              get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE); |                              get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE); | ||||||
|     memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, |     memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, | ||||||
|                                 &sphb->iowindow); |                                 &sphb->iowindow); | ||||||
|     /* |  | ||||||
|      * Selecting a busname is more complex than you'd think, due to |     bus = pci_register_bus(dev, NULL, | ||||||
|      * interacting constraints.  If the user has specified an id |  | ||||||
|      * explicitly for the phb , then we want to use the qdev default |  | ||||||
|      * of naming the bus based on the bridge device (so the user can |  | ||||||
|      * then assign devices to it in the way they expect).  For the |  | ||||||
|      * first / default PCI bus (index=0) we want to use just "pci" |  | ||||||
|      * because libvirt expects there to be a bus called, simply, |  | ||||||
|      * "pci".  Otherwise, we use the same name as in the device tree, |  | ||||||
|      * since it's unique by construction, and makes the guest visible |  | ||||||
|      * BUID clear. |  | ||||||
|      */ |  | ||||||
|     if (dev->id) { |  | ||||||
|         busname = NULL; |  | ||||||
|     } else if (sphb->index == 0) { |  | ||||||
|         busname = "pci"; |  | ||||||
|     } else { |  | ||||||
|         busname = sphb->dtbusname; |  | ||||||
|     } |  | ||||||
|     bus = pci_register_bus(dev, busname, |  | ||||||
|                            pci_spapr_set_irq, pci_spapr_map_irq, sphb, |                            pci_spapr_set_irq, pci_spapr_map_irq, sphb, | ||||||
|                            &sphb->memspace, &sphb->iospace, |                            &sphb->memspace, &sphb->iospace, | ||||||
|                            PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS); |                            PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS); | ||||||
| @@ -624,8 +606,9 @@ static int spapr_phb_init(SysBusDevice *s) | |||||||
|     sphb->tcet = spapr_tce_new_table(dev, sphb->dma_liobn, |     sphb->tcet = spapr_tce_new_table(dev, sphb->dma_liobn, | ||||||
|                                      sphb->dma_window_size); |                                      sphb->dma_window_size); | ||||||
|     if (!sphb->tcet) { |     if (!sphb->tcet) { | ||||||
|         fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname); |         error_setg(errp, "Unable to create TCE table for %s", | ||||||
|         return -1; |                    sphb->dtbusname); | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
|     address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet), |     address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet), | ||||||
|                        sphb->dtbusname); |                        sphb->dtbusname); | ||||||
| @@ -642,13 +625,12 @@ static int spapr_phb_init(SysBusDevice *s) | |||||||
|  |  | ||||||
|         irq = spapr_allocate_lsi(0); |         irq = spapr_allocate_lsi(0); | ||||||
|         if (!irq) { |         if (!irq) { | ||||||
|             return -1; |             error_setg(errp, "spapr_allocate_lsi failed"); | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         sphb->lsi_table[i].irq = irq; |         sphb->lsi_table[i].irq = irq; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void spapr_phb_reset(DeviceState *qdev) | static void spapr_phb_reset(DeviceState *qdev) | ||||||
| @@ -731,11 +713,10 @@ static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge, | |||||||
| static void spapr_phb_class_init(ObjectClass *klass, void *data) | static void spapr_phb_class_init(ObjectClass *klass, void *data) | ||||||
| { | { | ||||||
|     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); |     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); | ||||||
|     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); |  | ||||||
|     DeviceClass *dc = DEVICE_CLASS(klass); |     DeviceClass *dc = DEVICE_CLASS(klass); | ||||||
|  |  | ||||||
|     hc->root_bus_path = spapr_phb_root_bus_path; |     hc->root_bus_path = spapr_phb_root_bus_path; | ||||||
|     sdc->init = spapr_phb_init; |     dc->realize = spapr_phb_realize; | ||||||
|     dc->props = spapr_phb_properties; |     dc->props = spapr_phb_properties; | ||||||
|     dc->reset = spapr_phb_reset; |     dc->reset = spapr_phb_reset; | ||||||
|     dc->vmsd = &vmstate_spapr_pci; |     dc->vmsd = &vmstate_spapr_pci; | ||||||
|   | |||||||
| @@ -135,25 +135,23 @@ static unsigned s390_running_cpus; | |||||||
| void s390_add_running_cpu(S390CPU *cpu) | void s390_add_running_cpu(S390CPU *cpu) | ||||||
| { | { | ||||||
|     CPUState *cs = CPU(cpu); |     CPUState *cs = CPU(cpu); | ||||||
|     CPUS390XState *env = &cpu->env; |  | ||||||
|  |  | ||||||
|     if (cs->halted) { |     if (cs->halted) { | ||||||
|         s390_running_cpus++; |         s390_running_cpus++; | ||||||
|         cs->halted = 0; |         cs->halted = 0; | ||||||
|         env->exception_index = -1; |         cs->exception_index = -1; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| unsigned s390_del_running_cpu(S390CPU *cpu) | unsigned s390_del_running_cpu(S390CPU *cpu) | ||||||
| { | { | ||||||
|     CPUState *cs = CPU(cpu); |     CPUState *cs = CPU(cpu); | ||||||
|     CPUS390XState *env = &cpu->env; |  | ||||||
|  |  | ||||||
|     if (cs->halted == 0) { |     if (cs->halted == 0) { | ||||||
|         assert(s390_running_cpus >= 1); |         assert(s390_running_cpus >= 1); | ||||||
|         s390_running_cpus--; |         s390_running_cpus--; | ||||||
|         cs->halted = 1; |         cs->halted = 1; | ||||||
|         env->exception_index = EXCP_HLT; |         cs->exception_index = EXCP_HLT; | ||||||
|     } |     } | ||||||
|     return s390_running_cpus; |     return s390_running_cpus; | ||||||
| } | } | ||||||
| @@ -196,7 +194,7 @@ void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys) | |||||||
|  |  | ||||||
|         ipi_states[i] = cpu; |         ipi_states[i] = cpu; | ||||||
|         cs->halted = 1; |         cs->halted = 1; | ||||||
|         cpu->env.exception_index = EXCP_HLT; |         cs->exception_index = EXCP_HLT; | ||||||
|         cpu->env.storage_keys = storage_keys; |         cpu->env.storage_keys = storage_keys; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1905,6 +1905,26 @@ static const VMStateInfo vmstate_info_scsi_requests = { | |||||||
|     .put  = put_scsi_requests, |     .put  = put_scsi_requests, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | static bool scsi_sense_state_needed(void *opaque) | ||||||
|  | { | ||||||
|  |     SCSIDevice *s = opaque; | ||||||
|  |  | ||||||
|  |     return s->sense_len > SCSI_SENSE_BUF_SIZE_OLD; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const VMStateDescription vmstate_scsi_sense_state = { | ||||||
|  |     .name = "SCSIDevice/sense", | ||||||
|  |     .version_id = 1, | ||||||
|  |     .minimum_version_id = 1, | ||||||
|  |     .minimum_version_id_old = 1, | ||||||
|  |     .fields      = (VMStateField []) { | ||||||
|  |         VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice, | ||||||
|  |                                 SCSI_SENSE_BUF_SIZE_OLD, | ||||||
|  |                                 SCSI_SENSE_BUF_SIZE - SCSI_SENSE_BUF_SIZE_OLD), | ||||||
|  |         VMSTATE_END_OF_LIST() | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
| const VMStateDescription vmstate_scsi_device = { | const VMStateDescription vmstate_scsi_device = { | ||||||
|     .name = "SCSIDevice", |     .name = "SCSIDevice", | ||||||
|     .version_id = 1, |     .version_id = 1, | ||||||
| @@ -1915,7 +1935,7 @@ const VMStateDescription vmstate_scsi_device = { | |||||||
|         VMSTATE_UINT8(unit_attention.asc, SCSIDevice), |         VMSTATE_UINT8(unit_attention.asc, SCSIDevice), | ||||||
|         VMSTATE_UINT8(unit_attention.ascq, SCSIDevice), |         VMSTATE_UINT8(unit_attention.ascq, SCSIDevice), | ||||||
|         VMSTATE_BOOL(sense_is_ua, SCSIDevice), |         VMSTATE_BOOL(sense_is_ua, SCSIDevice), | ||||||
|         VMSTATE_UINT8_ARRAY(sense, SCSIDevice, SCSI_SENSE_BUF_SIZE), |         VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice, 0, SCSI_SENSE_BUF_SIZE_OLD), | ||||||
|         VMSTATE_UINT32(sense_len, SCSIDevice), |         VMSTATE_UINT32(sense_len, SCSIDevice), | ||||||
|         { |         { | ||||||
|             .name         = "requests", |             .name         = "requests", | ||||||
| @@ -1927,6 +1947,14 @@ const VMStateDescription vmstate_scsi_device = { | |||||||
|             .offset       = 0, |             .offset       = 0, | ||||||
|         }, |         }, | ||||||
|         VMSTATE_END_OF_LIST() |         VMSTATE_END_OF_LIST() | ||||||
|  |     }, | ||||||
|  |     .subsections = (VMStateSubsection []) { | ||||||
|  |         { | ||||||
|  |             .vmsd = &vmstate_scsi_sense_state, | ||||||
|  |             .needed = scsi_sense_state_needed, | ||||||
|  |         }, { | ||||||
|  |             /* empty */ | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -195,9 +195,9 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req, | |||||||
|     req->crq.s.IU_data_ptr = req->iu.srp.rsp.tag; /* right byte order */ |     req->crq.s.IU_data_ptr = req->iu.srp.rsp.tag; /* right byte order */ | ||||||
|  |  | ||||||
|     if (rc == 0) { |     if (rc == 0) { | ||||||
|         req->crq.s.status = 0x99; /* Just needs to be non-zero */ |         req->crq.s.status = VIOSRP_OK; | ||||||
|     } else { |     } else { | ||||||
|         req->crq.s.status = 0x00; |         req->crq.s.status = VIOSRP_ADAPTER_FAIL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     rc1 = spapr_vio_send_crq(&s->vdev, req->crq.raw); |     rc1 = spapr_vio_send_crq(&s->vdev, req->crq.raw); | ||||||
|   | |||||||
| @@ -304,6 +304,8 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, | |||||||
|                                          size_t resid) |                                          size_t resid) | ||||||
| { | { | ||||||
|     VirtIOSCSIReq *req = r->hba_private; |     VirtIOSCSIReq *req = r->hba_private; | ||||||
|  |     VirtIOSCSI *s = req->dev; | ||||||
|  |     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); | ||||||
|     uint32_t sense_len; |     uint32_t sense_len; | ||||||
|  |  | ||||||
|     if (r->io_canceled) { |     if (r->io_canceled) { | ||||||
| @@ -317,7 +319,7 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, | |||||||
|     } else { |     } else { | ||||||
|         req->resp.cmd->resid = 0; |         req->resp.cmd->resid = 0; | ||||||
|         sense_len = scsi_req_get_sense(r, req->resp.cmd->sense, |         sense_len = scsi_req_get_sense(r, req->resp.cmd->sense, | ||||||
|                                        VIRTIO_SCSI_SENSE_SIZE); |                                        vs->sense_size); | ||||||
|         req->resp.cmd->sense_len = tswap32(sense_len); |         req->resp.cmd->sense_len = tswap32(sense_len); | ||||||
|     } |     } | ||||||
|     virtio_scsi_complete_req(req); |     virtio_scsi_complete_req(req); | ||||||
|   | |||||||
| @@ -238,9 +238,10 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int ssi_sd_init(SSISlave *dev) | static int ssi_sd_init(SSISlave *d) | ||||||
| { | { | ||||||
|     ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev); |     DeviceState *dev = DEVICE(d); | ||||||
|  |     ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d); | ||||||
|     DriveInfo *dinfo; |     DriveInfo *dinfo; | ||||||
|  |  | ||||||
|     s->mode = SSI_SD_CMD; |     s->mode = SSI_SD_CMD; | ||||||
| @@ -249,7 +250,7 @@ static int ssi_sd_init(SSISlave *dev) | |||||||
|     if (s->sd == NULL) { |     if (s->sd == NULL) { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); |     register_savevm(dev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -416,7 +416,7 @@ static void sh7750_mem_writel(void *opaque, hwaddr addr, | |||||||
|     case SH7750_PTEH_A7: |     case SH7750_PTEH_A7: | ||||||
|         /* If asid changes, clear all registered tlb entries. */ |         /* If asid changes, clear all registered tlb entries. */ | ||||||
|         if ((s->cpu->env.pteh & 0xff) != (mem_value & 0xff)) { |         if ((s->cpu->env.pteh & 0xff) != (mem_value & 0xff)) { | ||||||
|             tlb_flush(&s->cpu->env, 1); |             tlb_flush(CPU(s->cpu), 1); | ||||||
|         } |         } | ||||||
|         s->cpu->env.pteh = mem_value; |         s->cpu->env.pteh = mem_value; | ||||||
|         return; |         return; | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								hw/ssi/ssi.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								hw/ssi/ssi.c
									
									
									
									
									
								
							| @@ -15,7 +15,7 @@ | |||||||
| #include "hw/ssi.h" | #include "hw/ssi.h" | ||||||
|  |  | ||||||
| struct SSIBus { | struct SSIBus { | ||||||
|     BusState qbus; |     BusState parent_obj; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define TYPE_SSI_BUS "SSI" | #define TYPE_SSI_BUS "SSI" | ||||||
| @@ -60,7 +60,7 @@ static int ssi_slave_init(DeviceState *dev) | |||||||
|  |  | ||||||
|     if (ssc->transfer_raw == ssi_transfer_raw_default && |     if (ssc->transfer_raw == ssi_transfer_raw_default && | ||||||
|             ssc->cs_polarity != SSI_CS_NONE) { |             ssc->cs_polarity != SSI_CS_NONE) { | ||||||
|         qdev_init_gpio_in(&s->qdev, ssi_cs_default, 1); |         qdev_init_gpio_in(dev, ssi_cs_default, 1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return ssc->init(s); |     return ssc->init(s); | ||||||
| @@ -88,7 +88,7 @@ static const TypeInfo ssi_slave_info = { | |||||||
|  |  | ||||||
| DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name) | DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name) | ||||||
| { | { | ||||||
|     return qdev_create(&bus->qbus, name); |     return qdev_create(BUS(bus), name); | ||||||
| } | } | ||||||
|  |  | ||||||
| DeviceState *ssi_create_slave(SSIBus *bus, const char *name) | DeviceState *ssi_create_slave(SSIBus *bus, const char *name) | ||||||
| @@ -108,11 +108,12 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char *name) | |||||||
|  |  | ||||||
| uint32_t ssi_transfer(SSIBus *bus, uint32_t val) | uint32_t ssi_transfer(SSIBus *bus, uint32_t val) | ||||||
| { | { | ||||||
|  |     BusState *b = BUS(bus); | ||||||
|     BusChild *kid; |     BusChild *kid; | ||||||
|     SSISlaveClass *ssc; |     SSISlaveClass *ssc; | ||||||
|     uint32_t r = 0; |     uint32_t r = 0; | ||||||
|  |  | ||||||
|     QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { |     QTAILQ_FOREACH(kid, &b->children, sibling) { | ||||||
|         SSISlave *slave = SSI_SLAVE(kid->child); |         SSISlave *slave = SSI_SLAVE(kid->child); | ||||||
|         ssc = SSI_SLAVE_GET_CLASS(slave); |         ssc = SSI_SLAVE_GET_CLASS(slave); | ||||||
|         r |= ssc->transfer_raw(slave, val); |         r |= ssc->transfer_raw(slave, val); | ||||||
| @@ -156,7 +157,7 @@ static int ssi_auto_connect_slave(Object *child, void *opaque) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     cs_line = qdev_get_gpio_in(DEVICE(dev), 0); |     cs_line = qdev_get_gpio_in(DEVICE(dev), 0); | ||||||
|     qdev_set_parent_bus(DEVICE(dev), &arg->bus->qbus); |     qdev_set_parent_bus(DEVICE(dev), BUS(arg->bus)); | ||||||
|     **arg->cs_linep = cs_line; |     **arg->cs_linep = cs_line; | ||||||
|     (*arg->cs_linep)++; |     (*arg->cs_linep)++; | ||||||
|     return 0; |     return 0; | ||||||
|   | |||||||
| @@ -106,9 +106,9 @@ static void grlib_gptimer_enable(GPTimer *timer) | |||||||
|     /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at |     /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at | ||||||
|        underflow. Set count + 1 to simulate the GPTimer behavior. */ |        underflow. Set count + 1 to simulate the GPTimer behavior. */ | ||||||
|  |  | ||||||
|     trace_grlib_gptimer_enable(timer->id, timer->counter + 1); |     trace_grlib_gptimer_enable(timer->id, timer->counter); | ||||||
|  |  | ||||||
|     ptimer_set_count(timer->ptimer, timer->counter + 1); |     ptimer_set_count(timer->ptimer, (uint64_t)timer->counter + 1); | ||||||
|     ptimer_run(timer->ptimer, 1); |     ptimer_run(timer->ptimer, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ | |||||||
| #include "qemu/queue.h" | #include "qemu/queue.h" | ||||||
| #include "qemu/event_notifier.h" | #include "qemu/event_notifier.h" | ||||||
| #include "qemu/thread.h" | #include "qemu/thread.h" | ||||||
|  | #include "qemu/rfifolock.h" | ||||||
| #include "qemu/timer.h" | #include "qemu/timer.h" | ||||||
|  |  | ||||||
| typedef struct BlockDriverAIOCB BlockDriverAIOCB; | typedef struct BlockDriverAIOCB BlockDriverAIOCB; | ||||||
| @@ -47,6 +48,9 @@ typedef void IOHandler(void *opaque); | |||||||
| struct AioContext { | struct AioContext { | ||||||
|     GSource source; |     GSource source; | ||||||
|  |  | ||||||
|  |     /* Protects all fields from multi-threaded access */ | ||||||
|  |     RFifoLock lock; | ||||||
|  |  | ||||||
|     /* The list of registered AIO handlers */ |     /* The list of registered AIO handlers */ | ||||||
|     QLIST_HEAD(, AioHandler) aio_handlers; |     QLIST_HEAD(, AioHandler) aio_handlers; | ||||||
|  |  | ||||||
| @@ -104,6 +108,20 @@ void aio_context_ref(AioContext *ctx); | |||||||
|  */ |  */ | ||||||
| void aio_context_unref(AioContext *ctx); | void aio_context_unref(AioContext *ctx); | ||||||
|  |  | ||||||
|  | /* Take ownership of the AioContext.  If the AioContext will be shared between | ||||||
|  |  * threads, a thread must have ownership when calling aio_poll(). | ||||||
|  |  * | ||||||
|  |  * Note that multiple threads calling aio_poll() means timers, BHs, and | ||||||
|  |  * callbacks may be invoked from a different thread than they were registered | ||||||
|  |  * from.  Therefore, code must use AioContext acquire/release or use | ||||||
|  |  * fine-grained synchronization to protect shared state if other threads will | ||||||
|  |  * be accessing it simultaneously. | ||||||
|  |  */ | ||||||
|  | void aio_context_acquire(AioContext *ctx); | ||||||
|  |  | ||||||
|  | /* Relinquish ownership of the AioContext. */ | ||||||
|  | void aio_context_release(AioContext *ctx); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * aio_bh_new: Allocate a new bottom half structure. |  * aio_bh_new: Allocate a new bottom half structure. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -286,15 +286,6 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); | |||||||
| int bdrv_amend_options(BlockDriverState *bs_new, QEMUOptionParameter *options); | int bdrv_amend_options(BlockDriverState *bs_new, QEMUOptionParameter *options); | ||||||
|  |  | ||||||
| /* external snapshots */ | /* external snapshots */ | ||||||
|  |  | ||||||
| typedef enum { |  | ||||||
|     BS_IS_A_FILTER, |  | ||||||
|     BS_FILTER_PASS_DOWN, |  | ||||||
|     BS_AUTHORIZATION_COUNT, |  | ||||||
| } BsAuthorization; |  | ||||||
|  |  | ||||||
| bool bdrv_generic_is_first_non_filter(BlockDriverState *bs, |  | ||||||
|                                       BlockDriverState *candidate); |  | ||||||
| bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs, | bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs, | ||||||
|                                       BlockDriverState *candidate); |                                       BlockDriverState *candidate); | ||||||
| bool bdrv_is_first_non_filter(BlockDriverState *candidate); | bool bdrv_is_first_non_filter(BlockDriverState *candidate); | ||||||
|   | |||||||
| @@ -76,10 +76,10 @@ struct BlockDriver { | |||||||
|     const char *format_name; |     const char *format_name; | ||||||
|     int instance_size; |     int instance_size; | ||||||
|  |  | ||||||
|     /* this table of boolean contains authorizations for the block operations */ |     /* set to true if the BlockDriver is a block filter */ | ||||||
|     bool authorizations[BS_AUTHORIZATION_COUNT]; |     bool is_filter; | ||||||
|     /* for snapshots complex block filter like Quorum can implement the |     /* for snapshots block filter like Quorum can implement the | ||||||
|      * following recursive callback instead of BS_IS_A_FILTER. |      * following recursive callback. | ||||||
|      * It's purpose is to recurse on the filter children while calling |      * It's purpose is to recurse on the filter children while calling | ||||||
|      * bdrv_recurse_is_first_non_filter on them. |      * bdrv_recurse_is_first_non_filter on them. | ||||||
|      * For a sample implementation look in the future Quorum block filter. |      * For a sample implementation look in the future Quorum block filter. | ||||||
|   | |||||||
| @@ -360,9 +360,6 @@ int page_check_range(target_ulong start, target_ulong len, int flags); | |||||||
|  |  | ||||||
| CPUArchState *cpu_copy(CPUArchState *env); | CPUArchState *cpu_copy(CPUArchState *env); | ||||||
|  |  | ||||||
| void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...) |  | ||||||
|     GCC_FMT_ATTR(2, 3); |  | ||||||
|  |  | ||||||
| /* Flags for use in ENV->INTERRUPT_PENDING. | /* Flags for use in ENV->INTERRUPT_PENDING. | ||||||
|  |  | ||||||
|    The numbers assigned here are non-sequential in order to preserve |    The numbers assigned here are non-sequential in order to preserve | ||||||
| @@ -413,27 +410,6 @@ void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...) | |||||||
|      | CPU_INTERRUPT_TGT_EXT_3   \ |      | CPU_INTERRUPT_TGT_EXT_3   \ | ||||||
|      | CPU_INTERRUPT_TGT_EXT_4) |      | CPU_INTERRUPT_TGT_EXT_4) | ||||||
|  |  | ||||||
| /* Breakpoint/watchpoint flags */ |  | ||||||
| #define BP_MEM_READ           0x01 |  | ||||||
| #define BP_MEM_WRITE          0x02 |  | ||||||
| #define BP_MEM_ACCESS         (BP_MEM_READ | BP_MEM_WRITE) |  | ||||||
| #define BP_STOP_BEFORE_ACCESS 0x04 |  | ||||||
| #define BP_WATCHPOINT_HIT     0x08 |  | ||||||
| #define BP_GDB                0x10 |  | ||||||
| #define BP_CPU                0x20 |  | ||||||
|  |  | ||||||
| int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags, |  | ||||||
|                           CPUBreakpoint **breakpoint); |  | ||||||
| int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags); |  | ||||||
| void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint); |  | ||||||
| void cpu_breakpoint_remove_all(CPUArchState *env, int mask); |  | ||||||
| int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len, |  | ||||||
|                           int flags, CPUWatchpoint **watchpoint); |  | ||||||
| int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, |  | ||||||
|                           target_ulong len, int flags); |  | ||||||
| void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint); |  | ||||||
| void cpu_watchpoint_remove_all(CPUArchState *env, int mask); |  | ||||||
|  |  | ||||||
| #if !defined(CONFIG_USER_ONLY) | #if !defined(CONFIG_USER_ONLY) | ||||||
|  |  | ||||||
| /* memory API */ | /* memory API */ | ||||||
|   | |||||||
| @@ -24,7 +24,6 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "config.h" | #include "config.h" | ||||||
| #include <setjmp.h> |  | ||||||
| #include <inttypes.h> | #include <inttypes.h> | ||||||
| #include "qemu/osdep.h" | #include "qemu/osdep.h" | ||||||
| #include "qemu/queue.h" | #include "qemu/queue.h" | ||||||
| @@ -61,9 +60,6 @@ typedef uint64_t target_ulong; | |||||||
| #define EXCP_HALTED     0x10003 /* cpu is halted (waiting for external event) */ | #define EXCP_HALTED     0x10003 /* cpu is halted (waiting for external event) */ | ||||||
| #define EXCP_YIELD      0x10004 /* cpu wants to yield timeslice to another */ | #define EXCP_YIELD      0x10004 /* cpu wants to yield timeslice to another */ | ||||||
|  |  | ||||||
| #define TB_JMP_CACHE_BITS 12 |  | ||||||
| #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) |  | ||||||
|  |  | ||||||
| /* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for | /* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for | ||||||
|    addresses on the same page.  The top bits are the same.  This allows |    addresses on the same page.  The top bits are the same.  This allows | ||||||
|    TLB invalidation to quickly clear a subset of the hash table.  */ |    TLB invalidation to quickly clear a subset of the hash table.  */ | ||||||
| @@ -118,66 +114,9 @@ QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS)); | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef HOST_WORDS_BIGENDIAN |  | ||||||
| typedef struct icount_decr_u16 { |  | ||||||
|     uint16_t high; |  | ||||||
|     uint16_t low; |  | ||||||
| } icount_decr_u16; |  | ||||||
| #else |  | ||||||
| typedef struct icount_decr_u16 { |  | ||||||
|     uint16_t low; |  | ||||||
|     uint16_t high; |  | ||||||
| } icount_decr_u16; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| typedef struct CPUBreakpoint { |  | ||||||
|     target_ulong pc; |  | ||||||
|     int flags; /* BP_* */ |  | ||||||
|     QTAILQ_ENTRY(CPUBreakpoint) entry; |  | ||||||
| } CPUBreakpoint; |  | ||||||
|  |  | ||||||
| typedef struct CPUWatchpoint { |  | ||||||
|     target_ulong vaddr; |  | ||||||
|     target_ulong len_mask; |  | ||||||
|     int flags; /* BP_* */ |  | ||||||
|     QTAILQ_ENTRY(CPUWatchpoint) entry; |  | ||||||
| } CPUWatchpoint; |  | ||||||
|  |  | ||||||
| #define CPU_TEMP_BUF_NLONGS 128 | #define CPU_TEMP_BUF_NLONGS 128 | ||||||
| #define CPU_COMMON                                                      \ | #define CPU_COMMON                                                      \ | ||||||
|     /* soft mmu support */                                              \ |     /* soft mmu support */                                              \ | ||||||
|     /* in order to avoid passing too many arguments to the MMIO         \ |  | ||||||
|        helpers, we store some rarely used information in the CPU        \ |  | ||||||
|        context) */                                                      \ |  | ||||||
|     uintptr_t mem_io_pc; /* host pc at which the memory was             \ |  | ||||||
|                             accessed */                                 \ |  | ||||||
|     target_ulong mem_io_vaddr; /* target virtual addr at which the      \ |  | ||||||
|                                      memory was accessed */             \ |  | ||||||
|     CPU_COMMON_TLB                                                      \ |     CPU_COMMON_TLB                                                      \ | ||||||
|     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];           \ |  | ||||||
|                                                                         \ |  | ||||||
|     int64_t icount_extra; /* Instructions until next timer event.  */   \ |  | ||||||
|     /* Number of cycles left, with interrupt flag in high bit.          \ |  | ||||||
|        This allows a single read-compare-cbranch-write sequence to test \ |  | ||||||
|        for both decrementer underflow and exceptions.  */               \ |  | ||||||
|     union {                                                             \ |  | ||||||
|         uint32_t u32;                                                   \ |  | ||||||
|         icount_decr_u16 u16;                                            \ |  | ||||||
|     } icount_decr;                                                      \ |  | ||||||
|     uint32_t can_do_io; /* nonzero if memory mapped IO is safe.  */     \ |  | ||||||
|                                                                         \ |  | ||||||
|     /* from this point: preserved by CPU reset */                       \ |  | ||||||
|     /* ice debug support */                                             \ |  | ||||||
|     QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;            \ |  | ||||||
|                                                                         \ |  | ||||||
|     QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints;            \ |  | ||||||
|     CPUWatchpoint *watchpoint_hit;                                      \ |  | ||||||
|                                                                         \ |  | ||||||
|     /* Core interrupt code */                                           \ |  | ||||||
|     sigjmp_buf jmp_env;                                                 \ |  | ||||||
|     int exception_index;                                                \ |  | ||||||
|                                                                         \ |  | ||||||
|     /* user data */                                                     \ |  | ||||||
|     void *opaque;                                                       \ |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ | |||||||
| #if !defined(CONFIG_USER_ONLY) | #if !defined(CONFIG_USER_ONLY) | ||||||
| /* cputlb.c */ | /* cputlb.c */ | ||||||
| void tlb_protect_code(ram_addr_t ram_addr); | void tlb_protect_code(ram_addr_t ram_addr); | ||||||
| void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr, | void tlb_unprotect_code_phys(CPUState *cpu, ram_addr_t ram_addr, | ||||||
|                              target_ulong vaddr); |                              target_ulong vaddr); | ||||||
| void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start, | void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start, | ||||||
|                            uintptr_t length); |                            uintptr_t length); | ||||||
| @@ -31,12 +31,12 @@ void tlb_set_dirty(CPUArchState *env, target_ulong vaddr); | |||||||
| extern int tlb_flush_count; | extern int tlb_flush_count; | ||||||
|  |  | ||||||
| /* exec.c */ | /* exec.c */ | ||||||
| void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr); | void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr); | ||||||
|  |  | ||||||
| MemoryRegionSection * | MemoryRegionSection * | ||||||
| address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat, | address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat, | ||||||
|                                   hwaddr *plen); |                                   hwaddr *plen); | ||||||
| hwaddr memory_region_section_get_iotlb(CPUArchState *env, | hwaddr memory_region_section_get_iotlb(CPUState *cpu, | ||||||
|                                        MemoryRegionSection *section, |                                        MemoryRegionSection *section, | ||||||
|                                        target_ulong vaddr, |                                        target_ulong vaddr, | ||||||
|                                        hwaddr paddr, hwaddr xlat, |                                        hwaddr paddr, hwaddr xlat, | ||||||
|   | |||||||
| @@ -80,16 +80,16 @@ void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb, | |||||||
| void cpu_gen_init(void); | void cpu_gen_init(void); | ||||||
| int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb, | int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb, | ||||||
|                  int *gen_code_size_ptr); |                  int *gen_code_size_ptr); | ||||||
| bool cpu_restore_state(CPUArchState *env, uintptr_t searched_pc); | bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc); | ||||||
| void page_size_init(void); | void page_size_init(void); | ||||||
|  |  | ||||||
| void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc); | void QEMU_NORETURN cpu_resume_from_signal(CPUState *cpu, void *puc); | ||||||
| void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, uintptr_t retaddr); | void QEMU_NORETURN cpu_io_recompile(CPUState *cpu, uintptr_t retaddr); | ||||||
| TranslationBlock *tb_gen_code(CPUArchState *env,  | TranslationBlock *tb_gen_code(CPUState *cpu, | ||||||
|                               target_ulong pc, target_ulong cs_base, int flags, |                               target_ulong pc, target_ulong cs_base, int flags, | ||||||
|                               int cflags); |                               int cflags); | ||||||
| void cpu_exec_init(CPUArchState *env); | void cpu_exec_init(CPUArchState *env); | ||||||
| void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1); | void QEMU_NORETURN cpu_loop_exit(CPUState *cpu); | ||||||
| int page_unprotect(target_ulong address, uintptr_t pc, void *puc); | int page_unprotect(target_ulong address, uintptr_t pc, void *puc); | ||||||
| void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, | void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, | ||||||
|                                    int is_cpu_write_access); |                                    int is_cpu_write_access); | ||||||
| @@ -98,18 +98,18 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end, | |||||||
| #if !defined(CONFIG_USER_ONLY) | #if !defined(CONFIG_USER_ONLY) | ||||||
| void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as); | void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as); | ||||||
| /* cputlb.c */ | /* cputlb.c */ | ||||||
| void tlb_flush_page(CPUArchState *env, target_ulong addr); | void tlb_flush_page(CPUState *cpu, target_ulong addr); | ||||||
| void tlb_flush(CPUArchState *env, int flush_global); | void tlb_flush(CPUState *cpu, int flush_global); | ||||||
| void tlb_set_page(CPUArchState *env, target_ulong vaddr, | void tlb_set_page(CPUState *cpu, target_ulong vaddr, | ||||||
|                   hwaddr paddr, int prot, |                   hwaddr paddr, int prot, | ||||||
|                   int mmu_idx, target_ulong size); |                   int mmu_idx, target_ulong size); | ||||||
| void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr); | void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr); | ||||||
| #else | #else | ||||||
| static inline void tlb_flush_page(CPUArchState *env, target_ulong addr) | static inline void tlb_flush_page(CPUState *cpu, target_ulong addr) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline void tlb_flush(CPUArchState *env, int flush_global) | static inline void tlb_flush(CPUState *cpu, int flush_global) | ||||||
| { | { | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -332,7 +332,7 @@ bool io_mem_read(struct MemoryRegion *mr, hwaddr addr, | |||||||
| bool io_mem_write(struct MemoryRegion *mr, hwaddr addr, | bool io_mem_write(struct MemoryRegion *mr, hwaddr addr, | ||||||
|                   uint64_t value, unsigned size); |                   uint64_t value, unsigned size); | ||||||
|  |  | ||||||
| void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, | void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx, | ||||||
|               uintptr_t retaddr); |               uintptr_t retaddr); | ||||||
|  |  | ||||||
| uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | ||||||
| @@ -380,20 +380,25 @@ extern int singlestep; | |||||||
| /* cpu-exec.c */ | /* cpu-exec.c */ | ||||||
| extern volatile sig_atomic_t exit_request; | extern volatile sig_atomic_t exit_request; | ||||||
|  |  | ||||||
| /* Deterministic execution requires that IO only be performed on the last | /** | ||||||
|    instruction of a TB so that interrupts take effect immediately.  */ |  * cpu_can_do_io: | ||||||
| static inline int can_do_io(CPUArchState *env) |  * @cpu: The CPU for which to check IO. | ||||||
|  |  * | ||||||
|  |  * Deterministic execution requires that IO only be performed on the last | ||||||
|  |  * instruction of a TB so that interrupts take effect immediately. | ||||||
|  |  * | ||||||
|  |  * Returns: %true if memory-mapped IO is safe, %false otherwise. | ||||||
|  |  */ | ||||||
|  | static inline bool cpu_can_do_io(CPUState *cpu) | ||||||
| { | { | ||||||
|     CPUState *cpu = ENV_GET_CPU(env); |  | ||||||
|  |  | ||||||
|     if (!use_icount) { |     if (!use_icount) { | ||||||
|         return 1; |         return true; | ||||||
|     } |     } | ||||||
|     /* If not executing code then assume we are ok.  */ |     /* If not executing code then assume we are ok.  */ | ||||||
|     if (cpu->current_tb == NULL) { |     if (cpu->current_tb == NULL) { | ||||||
|         return 1; |         return true; | ||||||
|     } |     } | ||||||
|     return env->can_do_io != 0; |     return cpu->can_do_io != 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -26,13 +26,15 @@ static inline void gen_tb_start(void) | |||||||
|  |  | ||||||
|     icount_label = gen_new_label(); |     icount_label = gen_new_label(); | ||||||
|     count = tcg_temp_local_new_i32(); |     count = tcg_temp_local_new_i32(); | ||||||
|     tcg_gen_ld_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u32)); |     tcg_gen_ld_i32(count, cpu_env, | ||||||
|  |                    -ENV_OFFSET + offsetof(CPUState, icount_decr.u32)); | ||||||
|     /* This is a horrid hack to allow fixing up the value later.  */ |     /* This is a horrid hack to allow fixing up the value later.  */ | ||||||
|     icount_arg = tcg_ctx.gen_opparam_ptr + 1; |     icount_arg = tcg_ctx.gen_opparam_ptr + 1; | ||||||
|     tcg_gen_subi_i32(count, count, 0xdeadbeef); |     tcg_gen_subi_i32(count, count, 0xdeadbeef); | ||||||
|  |  | ||||||
|     tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label); |     tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label); | ||||||
|     tcg_gen_st16_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u16.low)); |     tcg_gen_st16_i32(count, cpu_env, | ||||||
|  |                      -ENV_OFFSET + offsetof(CPUState, icount_decr.u16.low)); | ||||||
|     tcg_temp_free_i32(count); |     tcg_temp_free_i32(count); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -51,14 +53,14 @@ static void gen_tb_end(TranslationBlock *tb, int num_insns) | |||||||
| static inline void gen_io_start(void) | static inline void gen_io_start(void) | ||||||
| { | { | ||||||
|     TCGv_i32 tmp = tcg_const_i32(1); |     TCGv_i32 tmp = tcg_const_i32(1); | ||||||
|     tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUArchState, can_do_io)); |     tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io)); | ||||||
|     tcg_temp_free_i32(tmp); |     tcg_temp_free_i32(tmp); | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline void gen_io_end(void) | static inline void gen_io_end(void) | ||||||
| { | { | ||||||
|     TCGv_i32 tmp = tcg_const_i32(0); |     TCGv_i32 tmp = tcg_const_i32(0); | ||||||
|     tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUArchState, can_do_io)); |     tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io)); | ||||||
|     tcg_temp_free_i32(tmp); |     tcg_temp_free_i32(tmp); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -126,12 +126,12 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, | |||||||
|     MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr); |     MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr); | ||||||
|  |  | ||||||
|     physaddr = (physaddr & TARGET_PAGE_MASK) + addr; |     physaddr = (physaddr & TARGET_PAGE_MASK) + addr; | ||||||
|     env->mem_io_pc = retaddr; |     cpu->mem_io_pc = retaddr; | ||||||
|     if (mr != &io_mem_rom && mr != &io_mem_notdirty && !can_do_io(env)) { |     if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu_can_do_io(cpu)) { | ||||||
|         cpu_io_recompile(env, retaddr); |         cpu_io_recompile(cpu, retaddr); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     env->mem_io_vaddr = addr; |     cpu->mem_io_vaddr = addr; | ||||||
|     io_mem_read(mr, physaddr, &val, 1 << SHIFT); |     io_mem_read(mr, physaddr, &val, 1 << SHIFT); | ||||||
|     return val; |     return val; | ||||||
| } | } | ||||||
| @@ -158,7 +158,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, | |||||||
|             do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); |             do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); |         tlb_fill(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE, mmu_idx, retaddr); | ||||||
|         tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; |         tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -240,7 +240,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, | |||||||
|             do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); |             do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); |         tlb_fill(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE, mmu_idx, retaddr); | ||||||
|         tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; |         tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -333,12 +333,12 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env, | |||||||
|     MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr); |     MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr); | ||||||
|  |  | ||||||
|     physaddr = (physaddr & TARGET_PAGE_MASK) + addr; |     physaddr = (physaddr & TARGET_PAGE_MASK) + addr; | ||||||
|     if (mr != &io_mem_rom && mr != &io_mem_notdirty && !can_do_io(env)) { |     if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu_can_do_io(cpu)) { | ||||||
|         cpu_io_recompile(env, retaddr); |         cpu_io_recompile(cpu, retaddr); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     env->mem_io_vaddr = addr; |     cpu->mem_io_vaddr = addr; | ||||||
|     env->mem_io_pc = retaddr; |     cpu->mem_io_pc = retaddr; | ||||||
|     io_mem_write(mr, physaddr, val, 1 << SHIFT); |     io_mem_write(mr, physaddr, val, 1 << SHIFT); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -360,7 +360,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, | |||||||
|             do_unaligned_access(env, addr, 1, mmu_idx, retaddr); |             do_unaligned_access(env, addr, 1, mmu_idx, retaddr); | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         tlb_fill(env, addr, 1, mmu_idx, retaddr); |         tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr); | ||||||
|         tlb_addr = env->tlb_table[mmu_idx][index].addr_write; |         tlb_addr = env->tlb_table[mmu_idx][index].addr_write; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -436,7 +436,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, | |||||||
|             do_unaligned_access(env, addr, 1, mmu_idx, retaddr); |             do_unaligned_access(env, addr, 1, mmu_idx, retaddr); | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         tlb_fill(env, addr, 1, mmu_idx, retaddr); |         tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr); | ||||||
|         tlb_addr = env->tlb_table[mmu_idx][index].addr_write; |         tlb_addr = env->tlb_table[mmu_idx][index].addr_write; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ | |||||||
| #define HW_BOARDS_H | #define HW_BOARDS_H | ||||||
|  |  | ||||||
| #include "sysemu/blockdev.h" | #include "sysemu/blockdev.h" | ||||||
| #include "sysemu/qemumachine.h" |  | ||||||
| #include "hw/qdev.h" | #include "hw/qdev.h" | ||||||
|  | #include "qom/object.h" | ||||||
|  |  | ||||||
| typedef struct QEMUMachineInitArgs { | typedef struct QEMUMachineInitArgs { | ||||||
|     const QEMUMachine *machine; |     const QEMUMachine *machine; | ||||||
| @@ -50,9 +50,59 @@ struct QEMUMachine { | |||||||
|     const char *hw_version; |     const char *hw_version; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | #define TYPE_MACHINE_SUFFIX "-machine" | ||||||
| int qemu_register_machine(QEMUMachine *m); | int qemu_register_machine(QEMUMachine *m); | ||||||
| QEMUMachine *find_default_machine(void); |  | ||||||
|  |  | ||||||
| extern QEMUMachine *current_machine; | #define TYPE_MACHINE "machine" | ||||||
|  | #define MACHINE(obj) \ | ||||||
|  |     OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE) | ||||||
|  | #define MACHINE_GET_CLASS(obj) \ | ||||||
|  |     OBJECT_GET_CLASS(MachineClass, (obj), TYPE_MACHINE) | ||||||
|  | #define MACHINE_CLASS(klass) \ | ||||||
|  |     OBJECT_CLASS_CHECK(MachineClass, (klass), TYPE_MACHINE) | ||||||
|  |  | ||||||
|  | typedef struct MachineState MachineState; | ||||||
|  | typedef struct MachineClass MachineClass; | ||||||
|  |  | ||||||
|  | MachineClass *find_default_machine(void); | ||||||
|  | extern MachineState *current_machine; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * MachineClass: | ||||||
|  |  * @qemu_machine: #QEMUMachine | ||||||
|  |  */ | ||||||
|  | struct MachineClass { | ||||||
|  |     /*< private >*/ | ||||||
|  |     ObjectClass parent_class; | ||||||
|  |     /*< public >*/ | ||||||
|  |  | ||||||
|  |     QEMUMachine *qemu_machine; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * MachineState: | ||||||
|  |  */ | ||||||
|  | struct MachineState { | ||||||
|  |     /*< private >*/ | ||||||
|  |     Object parent_obj; | ||||||
|  |     /*< public >*/ | ||||||
|  |  | ||||||
|  |     char *accel; | ||||||
|  |     bool kernel_irqchip; | ||||||
|  |     int kvm_shadow_mem; | ||||||
|  |     char *kernel; | ||||||
|  |     char *initrd; | ||||||
|  |     char *append; | ||||||
|  |     char *dtb; | ||||||
|  |     char *dumpdtb; | ||||||
|  |     int phandle_start; | ||||||
|  |     char *dt_compatible; | ||||||
|  |     bool dump_guest_core; | ||||||
|  |     bool mem_merge; | ||||||
|  |     bool usb; | ||||||
|  |     char *firmware; | ||||||
|  |  | ||||||
|  |     QEMUMachineInitArgs init_args; | ||||||
|  | }; | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -102,7 +102,7 @@ Object *ich9_lpc_find(void); | |||||||
| #define ICH9_USB_UHCI1_DEV                      29 | #define ICH9_USB_UHCI1_DEV                      29 | ||||||
| #define ICH9_USB_UHCI1_FUNC                     0 | #define ICH9_USB_UHCI1_FUNC                     0 | ||||||
|  |  | ||||||
| /* D30:F0 DMI-to-PCI brdige */ | /* D30:F0 DMI-to-PCI bridge */ | ||||||
| #define ICH9_D2P_BRIDGE                         "ICH9 D2P BRIDGE" | #define ICH9_D2P_BRIDGE                         "ICH9 D2P BRIDGE" | ||||||
| #define ICH9_D2P_BRIDGE_SAVEVM_VERSION          0 | #define ICH9_D2P_BRIDGE_SAVEVM_VERSION          0 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -49,10 +49,12 @@ void pstrcpy_targphys(const char *name, | |||||||
|                       hwaddr dest, int buf_size, |                       hwaddr dest, int buf_size, | ||||||
|                       const char *source); |                       const char *source); | ||||||
|  |  | ||||||
| extern bool rom_file_in_ram; | extern bool option_rom_has_mr; | ||||||
|  | extern bool rom_file_has_mr; | ||||||
|  |  | ||||||
| int rom_add_file(const char *file, const char *fw_dir, | int rom_add_file(const char *file, const char *fw_dir, | ||||||
|                  hwaddr addr, int32_t bootindex); |                  hwaddr addr, int32_t bootindex, | ||||||
|  |                  bool option_rom); | ||||||
| void *rom_add_blob(const char *name, const void *blob, size_t len, | void *rom_add_blob(const char *name, const void *blob, size_t len, | ||||||
|                    hwaddr addr, const char *fw_file_name, |                    hwaddr addr, const char *fw_file_name, | ||||||
|                    FWCfgReadCallback fw_callback, void *callback_opaque); |                    FWCfgReadCallback fw_callback, void *callback_opaque); | ||||||
| @@ -66,7 +68,7 @@ void *rom_ptr(hwaddr addr); | |||||||
| void do_info_roms(Monitor *mon, const QDict *qdict); | void do_info_roms(Monitor *mon, const QDict *qdict); | ||||||
|  |  | ||||||
| #define rom_add_file_fixed(_f, _a, _i)          \ | #define rom_add_file_fixed(_f, _a, _i)          \ | ||||||
|     rom_add_file(_f, NULL, _a, _i) |     rom_add_file(_f, NULL, _a, _i, false) | ||||||
| #define rom_add_blob_fixed(_f, _b, _l, _a)      \ | #define rom_add_blob_fixed(_f, _b, _l, _a)      \ | ||||||
|     rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL) |     rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -125,8 +125,8 @@ typedef struct Q35PCIHost { | |||||||
| #define MCH_HOST_BRIDGE_PAM_RE                 ((uint8_t)0x1) | #define MCH_HOST_BRIDGE_PAM_RE                 ((uint8_t)0x1) | ||||||
| #define MCH_HOST_BRIDGE_PAM_MASK               ((uint8_t)0x3) | #define MCH_HOST_BRIDGE_PAM_MASK               ((uint8_t)0x3) | ||||||
|  |  | ||||||
| #define MCH_HOST_BRDIGE_SMRAM                  0x9d | #define MCH_HOST_BRIDGE_SMRAM                  0x9d | ||||||
| #define MCH_HOST_BRDIGE_SMRAM_SIZE             1 | #define MCH_HOST_BRIDGE_SMRAM_SIZE             1 | ||||||
| #define MCH_HOST_BRIDGE_SMRAM_DEFAULT          ((uint8_t)0x2) | #define MCH_HOST_BRIDGE_SMRAM_DEFAULT          ((uint8_t)0x2) | ||||||
| #define MCH_HOST_BRIDGE_SMRAM_D_OPEN           ((uint8_t)(1 << 6)) | #define MCH_HOST_BRIDGE_SMRAM_D_OPEN           ((uint8_t)(1 << 6)) | ||||||
| #define MCH_HOST_BRIDGE_SMRAM_D_CLS            ((uint8_t)(1 << 5)) | #define MCH_HOST_BRIDGE_SMRAM_D_CLS            ((uint8_t)(1 << 5)) | ||||||
| @@ -140,16 +140,16 @@ typedef struct Q35PCIHost { | |||||||
| #define MCH_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END  0x100000 | #define MCH_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END  0x100000 | ||||||
|  |  | ||||||
| #define MCH_HOST_BRIDGE_ESMRAMC                0x9e | #define MCH_HOST_BRIDGE_ESMRAMC                0x9e | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_H_SMRAME       ((uint8_t)(1 << 6)) | #define MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME       ((uint8_t)(1 << 6)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_E_SMERR        ((uint8_t)(1 << 5)) | #define MCH_HOST_BRIDGE_ESMRAMC_E_SMERR        ((uint8_t)(1 << 5)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_SM_CACHE       ((uint8_t)(1 << 4)) | #define MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE       ((uint8_t)(1 << 4)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_SM_L1          ((uint8_t)(1 << 3)) | #define MCH_HOST_BRIDGE_ESMRAMC_SM_L1          ((uint8_t)(1 << 3)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_SM_L2          ((uint8_t)(1 << 2)) | #define MCH_HOST_BRIDGE_ESMRAMC_SM_L2          ((uint8_t)(1 << 2)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_MASK   ((uint8_t)(0x3 << 1)) | #define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK   ((uint8_t)(0x3 << 1)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_1MB    ((uint8_t)(0x0 << 1)) | #define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB    ((uint8_t)(0x0 << 1)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_2MB    ((uint8_t)(0x1 << 1)) | #define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB    ((uint8_t)(0x1 << 1)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_8MB    ((uint8_t)(0x2 << 1)) | #define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB    ((uint8_t)(0x2 << 1)) | ||||||
| #define MCH_HOST_BRDIGE_ESMRAMC_T_EN           ((uint8_t)1) | #define MCH_HOST_BRIDGE_ESMRAMC_T_EN           ((uint8_t)1) | ||||||
|  |  | ||||||
| /* D1:F0 PCIE* port*/ | /* D1:F0 PCIE* port*/ | ||||||
| #define MCH_PCIE_DEV                           1 | #define MCH_PCIE_DEV                           1 | ||||||
|   | |||||||
| @@ -36,6 +36,8 @@ typedef int (*qdev_event)(DeviceState *dev); | |||||||
| typedef void (*qdev_resetfn)(DeviceState *dev); | typedef void (*qdev_resetfn)(DeviceState *dev); | ||||||
| typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); | typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); | ||||||
| typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp); | typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp); | ||||||
|  | typedef void (*BusRealize)(BusState *bus, Error **errp); | ||||||
|  | typedef void (*BusUnrealize)(BusState *bus, Error **errp); | ||||||
|  |  | ||||||
| struct VMStateDescription; | struct VMStateDescription; | ||||||
|  |  | ||||||
| @@ -174,6 +176,9 @@ struct BusClass { | |||||||
|      */ |      */ | ||||||
|     char *(*get_fw_dev_path)(DeviceState *dev); |     char *(*get_fw_dev_path)(DeviceState *dev); | ||||||
|     void (*reset)(BusState *bus); |     void (*reset)(BusState *bus); | ||||||
|  |     BusRealize realize; | ||||||
|  |     BusUnrealize unrealize; | ||||||
|  |  | ||||||
|     /* maximum devices allowed on the bus, 0: no limit. */ |     /* maximum devices allowed on the bus, 0: no limit. */ | ||||||
|     int max_dev; |     int max_dev; | ||||||
|     /* number of automatically allocated bus ids (e.g. ide.0) */ |     /* number of automatically allocated bus ids (e.g. ide.0) */ | ||||||
| @@ -199,6 +204,7 @@ struct BusState { | |||||||
|     int allow_hotplug; |     int allow_hotplug; | ||||||
|     HotplugHandler *hotplug_handler; |     HotplugHandler *hotplug_handler; | ||||||
|     int max_index; |     int max_index; | ||||||
|  |     bool realized; | ||||||
|     QTAILQ_HEAD(ChildrenHead, BusChild) children; |     QTAILQ_HEAD(ChildrenHead, BusChild) children; | ||||||
|     QLIST_ENTRY(BusState) sibling; |     QLIST_ENTRY(BusState) sibling; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ extern PropertyInfo qdev_prop_bios_chs_trans; | |||||||
| extern PropertyInfo qdev_prop_drive; | extern PropertyInfo qdev_prop_drive; | ||||||
| extern PropertyInfo qdev_prop_netdev; | extern PropertyInfo qdev_prop_netdev; | ||||||
| extern PropertyInfo qdev_prop_vlan; | extern PropertyInfo qdev_prop_vlan; | ||||||
|  | extern PropertyInfo qdev_prop_iothread; | ||||||
| extern PropertyInfo qdev_prop_pci_devfn; | extern PropertyInfo qdev_prop_pci_devfn; | ||||||
| extern PropertyInfo qdev_prop_blocksize; | extern PropertyInfo qdev_prop_blocksize; | ||||||
| extern PropertyInfo qdev_prop_pci_host_devaddr; | extern PropertyInfo qdev_prop_pci_host_devaddr; | ||||||
| @@ -142,6 +143,8 @@ extern PropertyInfo qdev_prop_arraylen; | |||||||
|     DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NICPeers) |     DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NICPeers) | ||||||
| #define DEFINE_PROP_DRIVE(_n, _s, _f) \ | #define DEFINE_PROP_DRIVE(_n, _s, _f) \ | ||||||
|     DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *) |     DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *) | ||||||
|  | #define DEFINE_PROP_IOTHREAD(_n, _s, _f)             \ | ||||||
|  |     DEFINE_PROP(_n, _s, _f, qdev_prop_iothread, IOThread *) | ||||||
| #define DEFINE_PROP_MACADDR(_n, _s, _f)         \ | #define DEFINE_PROP_MACADDR(_n, _s, _f)         \ | ||||||
|     DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) |     DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) | ||||||
| #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \ | #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \ | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ typedef struct SCSISense { | |||||||
|     uint8_t ascq; |     uint8_t ascq; | ||||||
| } SCSISense; | } SCSISense; | ||||||
|  |  | ||||||
|  | #define SCSI_SENSE_BUF_SIZE_OLD 96 | ||||||
| #define SCSI_SENSE_BUF_SIZE 252 | #define SCSI_SENSE_BUF_SIZE 252 | ||||||
|  |  | ||||||
| struct SCSICommand { | struct SCSICommand { | ||||||
|   | |||||||
| @@ -56,13 +56,12 @@ typedef struct SSISlaveClass { | |||||||
| } SSISlaveClass; | } SSISlaveClass; | ||||||
|  |  | ||||||
| struct SSISlave { | struct SSISlave { | ||||||
|     DeviceState qdev; |     DeviceState parent_obj; | ||||||
|  |  | ||||||
|     /* Chip select state */ |     /* Chip select state */ | ||||||
|     bool cs; |     bool cs; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define SSI_SLAVE_FROM_QDEV(dev) DO_UPCAST(SSISlave, qdev, dev) |  | ||||||
| #define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev) | #define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev) | ||||||
|  |  | ||||||
| extern const VMStateDescription vmstate_ssi_slave; | extern const VMStateDescription vmstate_ssi_slave; | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ | |||||||
|  |  | ||||||
| #include "hw/virtio/virtio.h" | #include "hw/virtio/virtio.h" | ||||||
| #include "hw/block/block.h" | #include "hw/block/block.h" | ||||||
|  | #include "sysemu/iothread.h" | ||||||
|  |  | ||||||
| #define TYPE_VIRTIO_BLK "virtio-blk-device" | #define TYPE_VIRTIO_BLK "virtio-blk-device" | ||||||
| #define VIRTIO_BLK(obj) \ | #define VIRTIO_BLK(obj) \ | ||||||
| @@ -106,6 +107,7 @@ struct virtio_scsi_inhdr | |||||||
| struct VirtIOBlkConf | struct VirtIOBlkConf | ||||||
| { | { | ||||||
|     BlockConf conf; |     BlockConf conf; | ||||||
|  |     IOThread *iothread; | ||||||
|     char *serial; |     char *serial; | ||||||
|     uint32_t scsi; |     uint32_t scsi; | ||||||
|     uint32_t config_wce; |     uint32_t config_wce; | ||||||
| @@ -140,13 +142,15 @@ typedef struct VirtIOBlock { | |||||||
|         DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \ |         DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \ | ||||||
|         DEFINE_PROP_STRING("serial", _state, _field.serial),                  \ |         DEFINE_PROP_STRING("serial", _state, _field.serial),                  \ | ||||||
|         DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true),    \ |         DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true),    \ | ||||||
|         DEFINE_PROP_BIT("scsi", _state, _field.scsi, 0, true) |         DEFINE_PROP_BIT("scsi", _state, _field.scsi, 0, true),                \ | ||||||
|  |         DEFINE_PROP_IOTHREAD("x-iothread", _state, _field.iothread) | ||||||
| #else | #else | ||||||
| #define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field)                          \ | #define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field)                          \ | ||||||
|         DEFINE_BLOCK_PROPERTIES(_state, _field.conf),                         \ |         DEFINE_BLOCK_PROPERTIES(_state, _field.conf),                         \ | ||||||
|         DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \ |         DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \ | ||||||
|         DEFINE_PROP_STRING("serial", _state, _field.serial),                  \ |         DEFINE_PROP_STRING("serial", _state, _field.serial),                  \ | ||||||
|         DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true) |         DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true),    \ | ||||||
|  |         DEFINE_PROP_IOTHREAD("x-iothread", _state, _field.iothread) | ||||||
| #endif /* __linux__ */ | #endif /* __linux__ */ | ||||||
|  |  | ||||||
| void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk); | void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk); | ||||||
|   | |||||||
| @@ -81,15 +81,15 @@ typedef struct VirtIOSerialPortClass { | |||||||
|     bool is_console; |     bool is_console; | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
|      * The per-port (or per-app) init function that's called when a |      * The per-port (or per-app) realize function that's called when a | ||||||
|      * new device is found on the bus. |      * new device is found on the bus. | ||||||
|      */ |      */ | ||||||
|     int (*init)(VirtIOSerialPort *port); |     DeviceRealize realize; | ||||||
|     /* |     /* | ||||||
|      * Per-port exit function that's called when a port gets |      * Per-port unrealize function that's called when a port gets | ||||||
|      * hot-unplugged or removed. |      * hot-unplugged or removed. | ||||||
|      */ |      */ | ||||||
|     int (*exit)(VirtIOSerialPort *port); |     DeviceUnrealize unrealize; | ||||||
|  |  | ||||||
|     /* Callbacks for guest events */ |     /* Callbacks for guest events */ | ||||||
|         /* Guest opened/closed device. */ |         /* Guest opened/closed device. */ | ||||||
|   | |||||||
| @@ -10,7 +10,6 @@ | |||||||
|  |  | ||||||
| #include "hw/irq.h" | #include "hw/irq.h" | ||||||
| #include "qemu-common.h" | #include "qemu-common.h" | ||||||
| #include "sysemu/qemumachine.h" |  | ||||||
|  |  | ||||||
| /* xen-machine.c */ | /* xen-machine.c */ | ||||||
| enum xen_mode { | enum xen_mode { | ||||||
|   | |||||||
| @@ -650,6 +650,9 @@ extern const VMStateInfo vmstate_info_bitmap; | |||||||
| #define VMSTATE_UINT8_ARRAY(_f, _s, _n)                               \ | #define VMSTATE_UINT8_ARRAY(_f, _s, _n)                               \ | ||||||
|     VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0) |     VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0) | ||||||
|  |  | ||||||
|  | #define VMSTATE_UINT8_SUB_ARRAY(_f, _s, _start, _num)                \ | ||||||
|  |     VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint8, uint8_t) | ||||||
|  |  | ||||||
| #define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2)                       \ | #define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2)                       \ | ||||||
|     VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0) |     VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -159,7 +159,7 @@ void qerror_report_err(Error *err); | |||||||
|     ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax" |     ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax" | ||||||
|  |  | ||||||
| #define QERR_KVM_MISSING_CAP \ | #define QERR_KVM_MISSING_CAP \ | ||||||
|     ERROR_CLASS_K_V_M_MISSING_CAP, "Using KVM without %s, %s unavailable" |     ERROR_CLASS_KVM_MISSING_CAP, "Using KVM without %s, %s unavailable" | ||||||
|  |  | ||||||
| #define QERR_MIGRATION_ACTIVE \ | #define QERR_MIGRATION_ACTIVE \ | ||||||
|     ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress" |     ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress" | ||||||
|   | |||||||
| @@ -38,6 +38,8 @@ typedef struct cmdinfo { | |||||||
|     helpfunc_t  help; |     helpfunc_t  help; | ||||||
| } cmdinfo_t; | } cmdinfo_t; | ||||||
|  |  | ||||||
|  | extern bool qemuio_misalign; | ||||||
|  |  | ||||||
| bool qemuio_command(BlockDriverState *bs, const char *cmd); | bool qemuio_command(BlockDriverState *bs, const char *cmd); | ||||||
|  |  | ||||||
| void qemuio_add_command(const cmdinfo_t *ci); | void qemuio_add_command(const cmdinfo_t *ci); | ||||||
|   | |||||||
							
								
								
									
										54
									
								
								include/qemu/rfifolock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								include/qemu/rfifolock.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | /* | ||||||
|  |  * Recursive FIFO lock | ||||||
|  |  * | ||||||
|  |  * Copyright Red Hat, Inc. 2013 | ||||||
|  |  * | ||||||
|  |  * Authors: | ||||||
|  |  *  Stefan Hajnoczi   <stefanha@redhat.com> | ||||||
|  |  * | ||||||
|  |  * This work is licensed under the terms of the GNU GPL, version 2 or later. | ||||||
|  |  * See the COPYING file in the top-level directory. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef QEMU_RFIFOLOCK_H | ||||||
|  | #define QEMU_RFIFOLOCK_H | ||||||
|  |  | ||||||
|  | #include "qemu/thread.h" | ||||||
|  |  | ||||||
|  | /* Recursive FIFO lock | ||||||
|  |  * | ||||||
|  |  * This lock provides more features than a plain mutex: | ||||||
|  |  * | ||||||
|  |  * 1. Fairness - enforces FIFO order. | ||||||
|  |  * 2. Nesting - can be taken recursively. | ||||||
|  |  * 3. Contention callback - optional, called when thread must wait. | ||||||
|  |  * | ||||||
|  |  * The recursive FIFO lock is heavyweight so prefer other synchronization | ||||||
|  |  * primitives if you do not need its features. | ||||||
|  |  */ | ||||||
|  | typedef struct { | ||||||
|  |     QemuMutex lock;             /* protects all fields */ | ||||||
|  |  | ||||||
|  |     /* FIFO order */ | ||||||
|  |     unsigned int head;          /* active ticket number */ | ||||||
|  |     unsigned int tail;          /* waiting ticket number */ | ||||||
|  |     QemuCond cond;              /* used to wait for our ticket number */ | ||||||
|  |  | ||||||
|  |     /* Nesting */ | ||||||
|  |     QemuThread owner_thread;    /* thread that currently has ownership */ | ||||||
|  |     unsigned int nesting;       /* amount of nesting levels */ | ||||||
|  |  | ||||||
|  |     /* Contention callback */ | ||||||
|  |     void (*cb)(void *);         /* called when thread must wait, with ->lock | ||||||
|  |                                  * held so it may not recursively lock/unlock | ||||||
|  |                                  */ | ||||||
|  |     void *cb_opaque; | ||||||
|  | } RFifoLock; | ||||||
|  |  | ||||||
|  | void rfifolock_init(RFifoLock *r, void (*cb)(void *), void *opaque); | ||||||
|  | void rfifolock_destroy(RFifoLock *r); | ||||||
|  | void rfifolock_lock(RFifoLock *r); | ||||||
|  | void rfifolock_unlock(RFifoLock *r); | ||||||
|  |  | ||||||
|  | #endif /* QEMU_RFIFOLOCK_H */ | ||||||
| @@ -30,6 +30,7 @@ typedef struct MemoryListener MemoryListener; | |||||||
|  |  | ||||||
| typedef struct MemoryMappingList MemoryMappingList; | typedef struct MemoryMappingList MemoryMappingList; | ||||||
|  |  | ||||||
|  | typedef struct QEMUMachine QEMUMachine; | ||||||
| typedef struct NICInfo NICInfo; | typedef struct NICInfo NICInfo; | ||||||
| typedef struct HCIInfo HCIInfo; | typedef struct HCIInfo HCIInfo; | ||||||
| typedef struct AudioState AudioState; | typedef struct AudioState AudioState; | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ | |||||||
| #define QEMU_CPU_H | #define QEMU_CPU_H | ||||||
|  |  | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
|  | #include <setjmp.h> | ||||||
| #include "hw/qdev-core.h" | #include "hw/qdev-core.h" | ||||||
| #include "exec/hwaddr.h" | #include "exec/hwaddr.h" | ||||||
| #include "qemu/queue.h" | #include "qemu/queue.h" | ||||||
| @@ -68,8 +69,10 @@ struct TranslationBlock; | |||||||
|  * CPUClass: |  * CPUClass: | ||||||
|  * @class_by_name: Callback to map -cpu command line model name to an |  * @class_by_name: Callback to map -cpu command line model name to an | ||||||
|  * instantiatable CPU type. |  * instantiatable CPU type. | ||||||
|  |  * @parse_features: Callback to parse command line arguments. | ||||||
|  * @reset: Callback to reset the #CPUState to its initial state. |  * @reset: Callback to reset the #CPUState to its initial state. | ||||||
|  * @reset_dump_flags: #CPUDumpFlags to use for reset logging. |  * @reset_dump_flags: #CPUDumpFlags to use for reset logging. | ||||||
|  |  * @has_work: Callback for checking if there is work to do. | ||||||
|  * @do_interrupt: Callback for interrupt handling. |  * @do_interrupt: Callback for interrupt handling. | ||||||
|  * @do_unassigned_access: Callback for unassigned access handling. |  * @do_unassigned_access: Callback for unassigned access handling. | ||||||
|  * @memory_rw_debug: Callback for GDB memory access. |  * @memory_rw_debug: Callback for GDB memory access. | ||||||
| @@ -81,6 +84,7 @@ struct TranslationBlock; | |||||||
|  * @set_pc: Callback for setting the Program Counter register. |  * @set_pc: Callback for setting the Program Counter register. | ||||||
|  * @synchronize_from_tb: Callback for synchronizing state from a TCG |  * @synchronize_from_tb: Callback for synchronizing state from a TCG | ||||||
|  * #TranslationBlock. |  * #TranslationBlock. | ||||||
|  |  * @handle_mmu_fault: Callback for handling an MMU fault. | ||||||
|  * @get_phys_page_debug: Callback for obtaining a physical address. |  * @get_phys_page_debug: Callback for obtaining a physical address. | ||||||
|  * @gdb_read_register: Callback for letting GDB read a register. |  * @gdb_read_register: Callback for letting GDB read a register. | ||||||
|  * @gdb_write_register: Callback for letting GDB write a register. |  * @gdb_write_register: Callback for letting GDB write a register. | ||||||
| @@ -96,9 +100,11 @@ typedef struct CPUClass { | |||||||
|     /*< public >*/ |     /*< public >*/ | ||||||
|  |  | ||||||
|     ObjectClass *(*class_by_name)(const char *cpu_model); |     ObjectClass *(*class_by_name)(const char *cpu_model); | ||||||
|  |     void (*parse_features)(CPUState *cpu, char *str, Error **errp); | ||||||
|  |  | ||||||
|     void (*reset)(CPUState *cpu); |     void (*reset)(CPUState *cpu); | ||||||
|     int reset_dump_flags; |     int reset_dump_flags; | ||||||
|  |     bool (*has_work)(CPUState *cpu); | ||||||
|     void (*do_interrupt)(CPUState *cpu); |     void (*do_interrupt)(CPUState *cpu); | ||||||
|     CPUUnassignedAccess do_unassigned_access; |     CPUUnassignedAccess do_unassigned_access; | ||||||
|     int (*memory_rw_debug)(CPUState *cpu, vaddr addr, |     int (*memory_rw_debug)(CPUState *cpu, vaddr addr, | ||||||
| @@ -113,6 +119,8 @@ typedef struct CPUClass { | |||||||
|                                Error **errp); |                                Error **errp); | ||||||
|     void (*set_pc)(CPUState *cpu, vaddr value); |     void (*set_pc)(CPUState *cpu, vaddr value); | ||||||
|     void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb); |     void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb); | ||||||
|  |     int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int rw, | ||||||
|  |                             int mmu_index); | ||||||
|     hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr); |     hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr); | ||||||
|     int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg); |     int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg); | ||||||
|     int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg); |     int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg); | ||||||
| @@ -131,9 +139,37 @@ typedef struct CPUClass { | |||||||
|     const char *gdb_core_xml_file; |     const char *gdb_core_xml_file; | ||||||
| } CPUClass; | } CPUClass; | ||||||
|  |  | ||||||
|  | #ifdef HOST_WORDS_BIGENDIAN | ||||||
|  | typedef struct icount_decr_u16 { | ||||||
|  |     uint16_t high; | ||||||
|  |     uint16_t low; | ||||||
|  | } icount_decr_u16; | ||||||
|  | #else | ||||||
|  | typedef struct icount_decr_u16 { | ||||||
|  |     uint16_t low; | ||||||
|  |     uint16_t high; | ||||||
|  | } icount_decr_u16; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | typedef struct CPUBreakpoint { | ||||||
|  |     vaddr pc; | ||||||
|  |     int flags; /* BP_* */ | ||||||
|  |     QTAILQ_ENTRY(CPUBreakpoint) entry; | ||||||
|  | } CPUBreakpoint; | ||||||
|  |  | ||||||
|  | typedef struct CPUWatchpoint { | ||||||
|  |     vaddr vaddr; | ||||||
|  |     vaddr len_mask; | ||||||
|  |     int flags; /* BP_* */ | ||||||
|  |     QTAILQ_ENTRY(CPUWatchpoint) entry; | ||||||
|  | } CPUWatchpoint; | ||||||
|  |  | ||||||
| struct KVMState; | struct KVMState; | ||||||
| struct kvm_run; | struct kvm_run; | ||||||
|  |  | ||||||
|  | #define TB_JMP_CACHE_BITS 12 | ||||||
|  | #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * CPUState: |  * CPUState: | ||||||
|  * @cpu_index: CPU index (informative). |  * @cpu_index: CPU index (informative). | ||||||
| @@ -150,12 +186,20 @@ struct kvm_run; | |||||||
|  * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this |  * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this | ||||||
|  *           CPU and return to its top level loop. |  *           CPU and return to its top level loop. | ||||||
|  * @singlestep_enabled: Flags for single-stepping. |  * @singlestep_enabled: Flags for single-stepping. | ||||||
|  |  * @icount_extra: Instructions until next timer event. | ||||||
|  |  * @icount_decr: Number of cycles left, with interrupt flag in high bit. | ||||||
|  |  * This allows a single read-compare-cbranch-write sequence to test | ||||||
|  |  * for both decrementer underflow and exceptions. | ||||||
|  |  * @can_do_io: Nonzero if memory-mapped IO is safe. | ||||||
|  * @env_ptr: Pointer to subclass-specific CPUArchState field. |  * @env_ptr: Pointer to subclass-specific CPUArchState field. | ||||||
|  * @current_tb: Currently executing TB. |  * @current_tb: Currently executing TB. | ||||||
|  * @gdb_regs: Additional GDB registers. |  * @gdb_regs: Additional GDB registers. | ||||||
|  * @gdb_num_regs: Number of total registers accessible to GDB. |  * @gdb_num_regs: Number of total registers accessible to GDB. | ||||||
|  * @gdb_num_g_regs: Number of registers in GDB 'g' packets. |  * @gdb_num_g_regs: Number of registers in GDB 'g' packets. | ||||||
|  * @next_cpu: Next CPU sharing TB cache. |  * @next_cpu: Next CPU sharing TB cache. | ||||||
|  |  * @opaque: User data. | ||||||
|  |  * @mem_io_pc: Host Program Counter at which the memory was accessed. | ||||||
|  |  * @mem_io_vaddr: Target virtual address at which the memory was accessed. | ||||||
|  * @kvm_fd: vCPU file descriptor for KVM. |  * @kvm_fd: vCPU file descriptor for KVM. | ||||||
|  * |  * | ||||||
|  * State of one CPU core or thread. |  * State of one CPU core or thread. | ||||||
| @@ -186,17 +230,34 @@ struct CPUState { | |||||||
|     volatile sig_atomic_t tcg_exit_req; |     volatile sig_atomic_t tcg_exit_req; | ||||||
|     uint32_t interrupt_request; |     uint32_t interrupt_request; | ||||||
|     int singlestep_enabled; |     int singlestep_enabled; | ||||||
|  |     int64_t icount_extra; | ||||||
|  |     sigjmp_buf jmp_env; | ||||||
|  |  | ||||||
|     AddressSpace *as; |     AddressSpace *as; | ||||||
|     MemoryListener *tcg_as_listener; |     MemoryListener *tcg_as_listener; | ||||||
|  |  | ||||||
|     void *env_ptr; /* CPUArchState */ |     void *env_ptr; /* CPUArchState */ | ||||||
|     struct TranslationBlock *current_tb; |     struct TranslationBlock *current_tb; | ||||||
|  |     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; | ||||||
|     struct GDBRegisterState *gdb_regs; |     struct GDBRegisterState *gdb_regs; | ||||||
|     int gdb_num_regs; |     int gdb_num_regs; | ||||||
|     int gdb_num_g_regs; |     int gdb_num_g_regs; | ||||||
|     QTAILQ_ENTRY(CPUState) node; |     QTAILQ_ENTRY(CPUState) node; | ||||||
|  |  | ||||||
|  |     /* ice debug support */ | ||||||
|  |     QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; | ||||||
|  |  | ||||||
|  |     QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; | ||||||
|  |     CPUWatchpoint *watchpoint_hit; | ||||||
|  |  | ||||||
|  |     void *opaque; | ||||||
|  |  | ||||||
|  |     /* In order to avoid passing too many arguments to the MMIO helpers, | ||||||
|  |      * we store some rarely used information in the CPU context. | ||||||
|  |      */ | ||||||
|  |     uintptr_t mem_io_pc; | ||||||
|  |     vaddr mem_io_vaddr; | ||||||
|  |  | ||||||
|     int kvm_fd; |     int kvm_fd; | ||||||
|     bool kvm_vcpu_dirty; |     bool kvm_vcpu_dirty; | ||||||
|     struct KVMState *kvm_state; |     struct KVMState *kvm_state; | ||||||
| @@ -205,6 +266,12 @@ struct CPUState { | |||||||
|     /* TODO Move common fields from CPUArchState here. */ |     /* TODO Move common fields from CPUArchState here. */ | ||||||
|     int cpu_index; /* used by alpha TCG */ |     int cpu_index; /* used by alpha TCG */ | ||||||
|     uint32_t halted; /* used by alpha, cris, ppc TCG */ |     uint32_t halted; /* used by alpha, cris, ppc TCG */ | ||||||
|  |     union { | ||||||
|  |         uint32_t u32; | ||||||
|  |         icount_decr_u16 u16; | ||||||
|  |     } icount_decr; | ||||||
|  |     uint32_t can_do_io; | ||||||
|  |     int32_t exception_index; /* used by m68k TCG */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| QTAILQ_HEAD(CPUTailQ, CPUState); | QTAILQ_HEAD(CPUTailQ, CPUState); | ||||||
| @@ -348,14 +415,31 @@ void cpu_reset(CPUState *cpu); | |||||||
| ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model); | ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * qemu_cpu_has_work: |  * cpu_generic_init: | ||||||
|  |  * @typename: The CPU base type. | ||||||
|  |  * @cpu_model: The model string including optional parameters. | ||||||
|  |  * | ||||||
|  |  * Instantiates a CPU, processes optional parameters and realizes the CPU. | ||||||
|  |  * | ||||||
|  |  * Returns: A #CPUState or %NULL if an error occurred. | ||||||
|  |  */ | ||||||
|  | CPUState *cpu_generic_init(const char *typename, const char *cpu_model); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * cpu_has_work: | ||||||
|  * @cpu: The vCPU to check. |  * @cpu: The vCPU to check. | ||||||
|  * |  * | ||||||
|  * Checks whether the CPU has work to do. |  * Checks whether the CPU has work to do. | ||||||
|  * |  * | ||||||
|  * Returns: %true if the CPU has work, %false otherwise. |  * Returns: %true if the CPU has work, %false otherwise. | ||||||
|  */ |  */ | ||||||
| bool qemu_cpu_has_work(CPUState *cpu); | static inline bool cpu_has_work(CPUState *cpu) | ||||||
|  | { | ||||||
|  |     CPUClass *cc = CPU_GET_CLASS(cpu); | ||||||
|  |  | ||||||
|  |     g_assert(cc->has_work); | ||||||
|  |     return cc->has_work(cpu); | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * qemu_cpu_is_self: |  * qemu_cpu_is_self: | ||||||
| @@ -511,6 +595,31 @@ void qemu_init_vcpu(CPUState *cpu); | |||||||
|  */ |  */ | ||||||
| void cpu_single_step(CPUState *cpu, int enabled); | void cpu_single_step(CPUState *cpu, int enabled); | ||||||
|  |  | ||||||
|  | /* Breakpoint/watchpoint flags */ | ||||||
|  | #define BP_MEM_READ           0x01 | ||||||
|  | #define BP_MEM_WRITE          0x02 | ||||||
|  | #define BP_MEM_ACCESS         (BP_MEM_READ | BP_MEM_WRITE) | ||||||
|  | #define BP_STOP_BEFORE_ACCESS 0x04 | ||||||
|  | #define BP_WATCHPOINT_HIT     0x08 | ||||||
|  | #define BP_GDB                0x10 | ||||||
|  | #define BP_CPU                0x20 | ||||||
|  |  | ||||||
|  | int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, | ||||||
|  |                           CPUBreakpoint **breakpoint); | ||||||
|  | int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags); | ||||||
|  | void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint); | ||||||
|  | void cpu_breakpoint_remove_all(CPUState *cpu, int mask); | ||||||
|  |  | ||||||
|  | int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, | ||||||
|  |                           int flags, CPUWatchpoint **watchpoint); | ||||||
|  | int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, | ||||||
|  |                           vaddr len, int flags); | ||||||
|  | void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint); | ||||||
|  | void cpu_watchpoint_remove_all(CPUState *cpu, int mask); | ||||||
|  |  | ||||||
|  | void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...) | ||||||
|  |     GCC_FMT_ATTR(2, 3); | ||||||
|  |  | ||||||
| #ifdef CONFIG_SOFTMMU | #ifdef CONFIG_SOFTMMU | ||||||
| extern const struct VMStateDescription vmstate_cpu_common; | extern const struct VMStateDescription vmstate_cpu_common; | ||||||
| #else | #else | ||||||
|   | |||||||
| @@ -973,6 +973,14 @@ const char *object_property_get_type(Object *obj, const char *name, | |||||||
|  */ |  */ | ||||||
| Object *object_get_root(void); | Object *object_get_root(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * object_get_canonical_path_component: | ||||||
|  |  * | ||||||
|  |  * Returns: The final component in the object's canonical path.  The canonical | ||||||
|  |  * path is the path within the composition tree starting from the root. | ||||||
|  |  */ | ||||||
|  | gchar *object_get_canonical_path_component(Object *obj); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * object_get_canonical_path: |  * object_get_canonical_path: | ||||||
|  * |  * | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								include/sysemu/iothread.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/sysemu/iothread.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | /* | ||||||
|  |  * Event loop thread | ||||||
|  |  * | ||||||
|  |  * Copyright Red Hat Inc., 2013 | ||||||
|  |  * | ||||||
|  |  * Authors: | ||||||
|  |  *  Stefan Hajnoczi   <stefanha@redhat.com> | ||||||
|  |  * | ||||||
|  |  * This work is licensed under the terms of the GNU GPL, version 2 or later. | ||||||
|  |  * See the COPYING file in the top-level directory. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef IOTHREAD_H | ||||||
|  | #define IOTHREAD_H | ||||||
|  |  | ||||||
|  | #include "block/aio.h" | ||||||
|  |  | ||||||
|  | #define TYPE_IOTHREAD "iothread" | ||||||
|  |  | ||||||
|  | typedef struct IOThread IOThread; | ||||||
|  |  | ||||||
|  | #define IOTHREAD(obj) \ | ||||||
|  |    OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD) | ||||||
|  |  | ||||||
|  | IOThread *iothread_find(const char *id); | ||||||
|  | char *iothread_get_id(IOThread *iothread); | ||||||
|  | AioContext *iothread_get_aio_context(IOThread *iothread); | ||||||
|  |  | ||||||
|  | #endif /* IOTHREAD_H */ | ||||||
| @@ -18,7 +18,6 @@ | |||||||
| #include "config-host.h" | #include "config-host.h" | ||||||
| #include "qemu/queue.h" | #include "qemu/queue.h" | ||||||
| #include "qom/cpu.h" | #include "qom/cpu.h" | ||||||
| #include "sysemu/qemumachine.h" |  | ||||||
|  |  | ||||||
| #ifdef CONFIG_KVM | #ifdef CONFIG_KVM | ||||||
| #include <linux/kvm.h> | #include <linux/kvm.h> | ||||||
|   | |||||||
| @@ -1,16 +0,0 @@ | |||||||
| /* |  | ||||||
|  * QEMU Machine typedef |  | ||||||
|  * |  | ||||||
|  * Copyright Alexander Graf <agraf@suse.de> |  | ||||||
|  * |  | ||||||
|  * This work is licensed under the terms of the GNU GPL, version 2 or later. |  | ||||||
|  * See the COPYING file in the top-level directory. |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #ifndef QEMUMACHINE_H |  | ||||||
| #define QEMUMACHINE_H |  | ||||||
|  |  | ||||||
| typedef struct QEMUMachine QEMUMachine; |  | ||||||
|  |  | ||||||
| #endif /* !QEMUMACHINE_H */ |  | ||||||
| @@ -16,7 +16,6 @@ | |||||||
|  |  | ||||||
| #include "qemu-common.h" | #include "qemu-common.h" | ||||||
| #include "qapi/error.h" | #include "qapi/error.h" | ||||||
| #include "sysemu/qemumachine.h" |  | ||||||
|  |  | ||||||
| extern bool qtest_allowed; | extern bool qtest_allowed; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -104,7 +104,7 @@ extern int autostart; | |||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|     VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL, |     VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL, | ||||||
|     VGA_TCX, VGA_CG3, |     VGA_TCX, VGA_CG3, VGA_DEVICE | ||||||
| } VGAInterfaceType; | } VGAInterfaceType; | ||||||
|  |  | ||||||
| extern int vga_interface_type; | extern int vga_interface_type; | ||||||
|   | |||||||
| @@ -345,6 +345,6 @@ int index_from_key(const char *key); | |||||||
|  |  | ||||||
| /* gtk.c */ | /* gtk.c */ | ||||||
| void early_gtk_display_init(void); | void early_gtk_display_init(void); | ||||||
| void gtk_display_init(DisplayState *ds, bool full_screen); | void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user