Compare commits
	
		
			247 Commits
		
	
	
		
			pull-input
			...
			pull-trivi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8bc8912796 | ||
| 
						 | 
					2a2c4830c0 | ||
| 
						 | 
					05fedeef83 | ||
| 
						 | 
					706808585a | ||
| 
						 | 
					c5cb1afc46 | ||
| 
						 | 
					a491af471b | ||
| 
						 | 
					075ccb6cd3 | ||
| 
						 | 
					b21631f3b5 | ||
| 
						 | 
					ddd6b45ce2 | ||
| 
						 | 
					e70871d8b5 | ||
| 
						 | 
					e3bb532cc7 | ||
| 
						 | 
					84007e8181 | ||
| 
						 | 
					c68a0409b3 | ||
| 
						 | 
					d0ece345cb | ||
| 
						 | 
					8e5977797d | ||
| 
						 | 
					b87ef3518b | ||
| 
						 | 
					c998acb03d | ||
| 
						 | 
					24aeeace7a | ||
| 
						 | 
					2f859f80c2 | ||
| 
						 | 
					22227f121b | ||
| 
						 | 
					92ba1401e0 | ||
| 
						 | 
					ae3f88f60f | ||
| 
						 | 
					fa7a1e5219 | ||
| 
						 | 
					f50def915e | ||
| 
						 | 
					0a337ed067 | ||
| 
						 | 
					932f2d7e0f | ||
| 
						 | 
					c4af6d4b13 | ||
| 
						 | 
					f35f961ac9 | ||
| 
						 | 
					1e501653ab | ||
| 
						 | 
					605474815d | ||
| 
						 | 
					b85159a3a3 | ||
| 
						 | 
					80b346040d | ||
| 
						 | 
					88dae46d18 | ||
| 
						 | 
					adfc3e91e2 | ||
| 
						 | 
					7224f66ec3 | ||
| 
						 | 
					747eb78baa | ||
| 
						 | 
					adf9d70b0d | ||
| 
						 | 
					6ad3f09bd4 | ||
| 
						 | 
					b7b5233ad7 | ||
| 
						 | 
					591b320ad0 | ||
| 
						 | 
					6b24119b7f | ||
| 
						 | 
					b780bf8eff | ||
| 
						 | 
					1a2858995d | ||
| 
						 | 
					e2bb4ae746 | ||
| 
						 | 
					4380be0e99 | ||
| 
						 | 
					fec0da9cbf | ||
| 
						 | 
					ec15993d9d | ||
| 
						 | 
					6b1dd54b6a | ||
| 
						 | 
					a10678b08e | ||
| 
						 | 
					6998b6c11b | ||
| 
						 | 
					d1180c1e57 | ||
| 
						 | 
					89218c218f | ||
| 
						 | 
					fc4bde9025 | ||
| 
						 | 
					029ad4bcf3 | ||
| 
						 | 
					e3a17ef6cc | ||
| 
						 | 
					f46b9cc71c | ||
| 
						 | 
					c1d7572793 | ||
| 
						 | 
					a1fa7992a9 | ||
| 
						 | 
					f9b5426fd5 | ||
| 
						 | 
					7179585688 | ||
| 
						 | 
					831f4d27b6 | ||
| 
						 | 
					49bba868df | ||
| 
						 | 
					2a802aaf63 | ||
| 
						 | 
					ef18c2f54e | ||
| 
						 | 
					3048ed6aac | ||
| 
						 | 
					fa15286a75 | ||
| 
						 | 
					6ab57a6b80 | ||
| 
						 | 
					1c33ac5716 | ||
| 
						 | 
					3334e929ae | ||
| 
						 | 
					333cb18ff4 | ||
| 
						 | 
					a1d2db08d8 | ||
| 
						 | 
					99519e677b | ||
| 
						 | 
					18e588b197 | ||
| 
						 | 
					7b0140e49b | ||
| 
						 | 
					bbd8bb8e32 | ||
| 
						 | 
					de13d21614 | ||
| 
						 | 
					66ad0893f0 | ||
| 
						 | 
					79afc36d91 | ||
| 
						 | 
					bcb2b582f3 | ||
| 
						 | 
					6449a41a4d | ||
| 
						 | 
					a2689242b1 | ||
| 
						 | 
					4cb88c3c37 | ||
| 
						 | 
					08da527fd0 | ||
| 
						 | 
					f068d320de | ||
| 
						 | 
					471f7e30a4 | ||
| 
						 | 
					ae9b65e873 | ||
| 
						 | 
					fd25c0e6dd | ||
| 
						 | 
					2a0c46da96 | ||
| 
						 | 
					86946a2d83 | ||
| 
						 | 
					7721a30442 | ||
| 
						 | 
					14ac573392 | ||
| 
						 | 
					3b1a413812 | ||
| 
						 | 
					d3afacc726 | ||
| 
						 | 
					f6fe04d566 | ||
| 
						 | 
					be56f04eea | ||
| 
						 | 
					5acc765c04 | ||
| 
						 | 
					aa633469ed | ||
| 
						 | 
					130f2e7dcb | ||
| 
						 | 
					da5141fc45 | ||
| 
						 | 
					25f748e37a | ||
| 
						 | 
					fb8ad9f2c1 | ||
| 
						 | 
					46d9dfdad6 | ||
| 
						 | 
					411bdc7837 | ||
| 
						 | 
					4e624edaeb | ||
| 
						 | 
					526d0096e5 | ||
| 
						 | 
					f1ecb913d8 | ||
| 
						 | 
					d615efac7c | ||
| 
						 | 
					8d5c773e32 | ||
| 
						 | 
					bf01601764 | ||
| 
						 | 
					61e9924149 | ||
| 
						 | 
					4a331bb33b | ||
| 
						 | 
					a35d9be622 | ||
| 
						 | 
					5b808275f3 | ||
| 
						 | 
					82432638eb | ||
| 
						 | 
					80ff35cd3f | ||
| 
						 | 
					26896cbf35 | ||
| 
						 | 
					7efea76377 | ||
| 
						 | 
					b167383ffb | ||
| 
						 | 
					8597f2e19e | ||
| 
						 | 
					b44672849a | ||
| 
						 | 
					40e76f736d | ||
| 
						 | 
					5dfc05cb1d | ||
| 
						 | 
					959e41473f | ||
| 
						 | 
					37654d9e6a | ||
| 
						 | 
					08397c4b29 | ||
| 
						 | 
					a373cdb5ce | ||
| 
						 | 
					aa0f607f61 | ||
| 
						 | 
					95faaa73df | ||
| 
						 | 
					e8198f6ea0 | ||
| 
						 | 
					8c6d96728d | ||
| 
						 | 
					04bb4d86f1 | ||
| 
						 | 
					2e95fa1719 | ||
| 
						 | 
					1ad166b612 | ||
| 
						 | 
					5db15096d0 | ||
| 
						 | 
					d34bda716a | ||
| 
						 | 
					5d039baba4 | ||
| 
						 | 
					b544c1aba8 | ||
| 
						 | 
					405a27640b | ||
| 
						 | 
					50809c8b92 | ||
| 
						 | 
					4e627aeef8 | ||
| 
						 | 
					26edf8cc08 | ||
| 
						 | 
					31e25e3e57 | ||
| 
						 | 
					ae74bbe7c5 | ||
| 
						 | 
					f38b161203 | ||
| 
						 | 
					fd7fbc8ff7 | ||
| 
						 | 
					ea9a6606b1 | ||
| 
						 | 
					01b91ac2be | ||
| 
						 | 
					d4ad9dec14 | ||
| 
						 | 
					366d4f7e00 | ||
| 
						 | 
					e09c49f40d | ||
| 
						 | 
					9d48d3f01c | ||
| 
						 | 
					9f0355b590 | ||
| 
						 | 
					d4f005db9b | ||
| 
						 | 
					711e2f1e9e | ||
| 
						 | 
					9f9260a3be | ||
| 
						 | 
					16b96f82cd | ||
| 
						 | 
					b09481de91 | ||
| 
						 | 
					de431a655a | ||
| 
						 | 
					eaad03e472 | ||
| 
						 | 
					e2a32ebbfe | ||
| 
						 | 
					e7e898a76a | ||
| 
						 | 
					e8f6d00c30 | ||
| 
						 | 
					b728464ae8 | ||
| 
						 | 
					c1eb2fa3fd | ||
| 
						 | 
					77549a7809 | ||
| 
						 | 
					b052e4509b | ||
| 
						 | 
					870a706735 | ||
| 
						 | 
					7c82256006 | ||
| 
						 | 
					487cad8853 | ||
| 
						 | 
					00cc3e1d70 | ||
| 
						 | 
					843408b3cf | ||
| 
						 | 
					f57584dc87 | ||
| 
						 | 
					8a201bd47e | ||
| 
						 | 
					81cf8d8adc | ||
| 
						 | 
					43773ed369 | ||
| 
						 | 
					c773828aa9 | ||
| 
						 | 
					f08b617018 | ||
| 
						 | 
					1d854765df | ||
| 
						 | 
					58ed270df9 | ||
| 
						 | 
					0f590e749f | ||
| 
						 | 
					d94f0a8ecb | ||
| 
						 | 
					93e22326d6 | ||
| 
						 | 
					ca0aa40816 | ||
| 
						 | 
					a6c9eac0d5 | ||
| 
						 | 
					859d76120b | ||
| 
						 | 
					0983979b3a | ||
| 
						 | 
					fddbd80cc9 | ||
| 
						 | 
					7e4e88656c | ||
| 
						 | 
					e3eb9806c7 | ||
| 
						 | 
					3d1b2ff62c | ||
| 
						 | 
					76782fab1c | ||
| 
						 | 
					0b91966730 | ||
| 
						 | 
					d6635c4dbb | ||
| 
						 | 
					1ac362cdbd | ||
| 
						 | 
					b15446fdbf | ||
| 
						 | 
					22524f7262 | ||
| 
						 | 
					13af91ebf0 | ||
| 
						 | 
					c9f87b20b9 | ||
| 
						 | 
					5a05cbeeaa | ||
| 
						 | 
					6d7e73d62f | ||
| 
						 | 
					db519cba87 | ||
| 
						 | 
					76ef2cf549 | ||
| 
						 | 
					8d242f0ed5 | ||
| 
						 | 
					0d6ecec252 | ||
| 
						 | 
					580b6b2aa2 | ||
| 
						 | 
					c75f3bdf46 | ||
| 
						 | 
					2af0b20056 | ||
| 
						 | 
					84390bed59 | ||
| 
						 | 
					ea80019149 | ||
| 
						 | 
					85ebd381fd | ||
| 
						 | 
					99cc598924 | ||
| 
						 | 
					abd269b7cf | ||
| 
						 | 
					c2f3426c9b | ||
| 
						 | 
					e3625d3d6a | ||
| 
						 | 
					a8c868c386 | ||
| 
						 | 
					471799d135 | ||
| 
						 | 
					69447cd8f3 | ||
| 
						 | 
					80cf625766 | ||
| 
						 | 
					6ee50af24b | ||
| 
						 | 
					63f0f45f2e | ||
| 
						 | 
					9d94020bc6 | ||
| 
						 | 
					7e1efdf0a3 | ||
| 
						 | 
					dcd042282d | ||
| 
						 | 
					9b536adcbe | ||
| 
						 | 
					ed78cda3de | ||
| 
						 | 
					2572b37a47 | ||
| 
						 | 
					924fe1293c | ||
| 
						 | 
					79b6f2f651 | ||
| 
						 | 
					374044f08f | ||
| 
						 | 
					9b1786829a | ||
| 
						 | 
					f522d2acc5 | ||
| 
						 | 
					0e1dac6c41 | ||
| 
						 | 
					eb386aaccc | ||
| 
						 | 
					501f28ca9d | ||
| 
						 | 
					38dbd48b24 | ||
| 
						 | 
					28fb26f19f | ||
| 
						 | 
					7125c937c9 | ||
| 
						 | 
					d3b5491897 | ||
| 
						 | 
					b98dbc9095 | ||
| 
						 | 
					87446327cc | ||
| 
						 | 
					b763adf1a6 | ||
| 
						 | 
					7c8b724826 | ||
| 
						 | 
					0d73394ad9 | ||
| 
						 | 
					84351843eb | ||
| 
						 | 
					fb5be2e833 | ||
| 
						 | 
					13cc2c3e86 | ||
| 
						 | 
					a096b3a673 | 
@@ -66,16 +66,16 @@ matrix:
 | 
			
		||||
      compiler: gcc
 | 
			
		||||
    # All the trace backends (apart from dtrace)
 | 
			
		||||
    - env: TARGETS=i386-softmmu,x86_64-softmmu
 | 
			
		||||
           EXTRA_CONFIG="--enable-trace-backend=stderr"
 | 
			
		||||
           EXTRA_CONFIG="--enable-trace-backends=stderr"
 | 
			
		||||
      compiler: gcc
 | 
			
		||||
    - env: TARGETS=i386-softmmu,x86_64-softmmu
 | 
			
		||||
           EXTRA_CONFIG="--enable-trace-backend=simple"
 | 
			
		||||
           EXTRA_CONFIG="--enable-trace-backends=simple"
 | 
			
		||||
      compiler: gcc
 | 
			
		||||
    - env: TARGETS=i386-softmmu,x86_64-softmmu
 | 
			
		||||
           EXTRA_CONFIG="--enable-trace-backend=ftrace"
 | 
			
		||||
           EXTRA_CONFIG="--enable-trace-backends=ftrace"
 | 
			
		||||
           TEST_CMD=""
 | 
			
		||||
      compiler: gcc
 | 
			
		||||
    - env: TARGETS=i386-softmmu,x86_64-softmmu
 | 
			
		||||
          EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
 | 
			
		||||
          EXTRA_CONFIG="--enable-trace-backend=ust"
 | 
			
		||||
          EXTRA_CONFIG="--enable-trace-backends=ust"
 | 
			
		||||
      compiler: gcc
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							@@ -52,12 +52,12 @@ GENERATED_HEADERS += trace/generated-events.h
 | 
			
		||||
GENERATED_SOURCES += trace/generated-events.c
 | 
			
		||||
 | 
			
		||||
GENERATED_HEADERS += trace/generated-tracers.h
 | 
			
		||||
ifeq ($(TRACE_BACKEND),dtrace)
 | 
			
		||||
ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
 | 
			
		||||
GENERATED_HEADERS += trace/generated-tracers-dtrace.h
 | 
			
		||||
endif
 | 
			
		||||
GENERATED_SOURCES += trace/generated-tracers.c
 | 
			
		||||
 | 
			
		||||
ifeq ($(TRACE_BACKEND),ust)
 | 
			
		||||
ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
 | 
			
		||||
GENERATED_HEADERS += trace/generated-ust-provider.h
 | 
			
		||||
GENERATED_SOURCES += trace/generated-ust.c
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ endif
 | 
			
		||||
$(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
 | 
			
		||||
	$(call quiet-command,$(TRACETOOL) \
 | 
			
		||||
		--format=stap \
 | 
			
		||||
		--backend=$(TRACE_BACKEND) \
 | 
			
		||||
		--backends=$(TRACE_BACKENDS) \
 | 
			
		||||
		--binary=$(bindir)/$(QEMU_PROG) \
 | 
			
		||||
		--target-name=$(TARGET_NAME) \
 | 
			
		||||
		--target-type=$(TARGET_TYPE) \
 | 
			
		||||
@@ -58,7 +58,7 @@ $(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
 | 
			
		||||
$(QEMU_PROG).stp: $(SRC_PATH)/trace-events
 | 
			
		||||
	$(call quiet-command,$(TRACETOOL) \
 | 
			
		||||
		--format=stap \
 | 
			
		||||
		--backend=$(TRACE_BACKEND) \
 | 
			
		||||
		--backends=$(TRACE_BACKENDS) \
 | 
			
		||||
		--binary=$(realpath .)/$(QEMU_PROG) \
 | 
			
		||||
		--target-name=$(TARGET_NAME) \
 | 
			
		||||
		--target-type=$(TARGET_TYPE) \
 | 
			
		||||
@@ -102,7 +102,8 @@ endif #CONFIG_LINUX_USER
 | 
			
		||||
 | 
			
		||||
ifdef CONFIG_BSD_USER
 | 
			
		||||
 | 
			
		||||
QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR)
 | 
			
		||||
QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR) \
 | 
			
		||||
			 -I$(SRC_PATH)/bsd-user/$(HOST_VARIANT_DIR)
 | 
			
		||||
 | 
			
		||||
obj-y += bsd-user/
 | 
			
		||||
obj-y += gdbstub.o user-exec.o
 | 
			
		||||
 
 | 
			
		||||
@@ -739,7 +739,6 @@ static void migration_end(void)
 | 
			
		||||
    XBZRLE_cache_lock();
 | 
			
		||||
    if (XBZRLE.cache) {
 | 
			
		||||
        cache_fini(XBZRLE.cache);
 | 
			
		||||
        g_free(XBZRLE.cache);
 | 
			
		||||
        g_free(XBZRLE.encoded_buf);
 | 
			
		||||
        g_free(XBZRLE.current_buf);
 | 
			
		||||
        XBZRLE.cache = NULL;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								async.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								async.c
									
									
									
									
									
								
							@@ -117,15 +117,21 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
 | 
			
		||||
 | 
			
		||||
void qemu_bh_schedule(QEMUBH *bh)
 | 
			
		||||
{
 | 
			
		||||
    AioContext *ctx;
 | 
			
		||||
 | 
			
		||||
    if (bh->scheduled)
 | 
			
		||||
        return;
 | 
			
		||||
    ctx = bh->ctx;
 | 
			
		||||
    bh->idle = 0;
 | 
			
		||||
    /* Make sure that idle & any writes needed by the callback are done
 | 
			
		||||
     * before the locations are read in the aio_bh_poll.
 | 
			
		||||
    /* Make sure that:
 | 
			
		||||
     * 1. idle & any writes needed by the callback are done before the
 | 
			
		||||
     *    locations are read in the aio_bh_poll.
 | 
			
		||||
     * 2. ctx is loaded before scheduled is set and the callback has a chance
 | 
			
		||||
     *    to execute.
 | 
			
		||||
     */
 | 
			
		||||
    smp_wmb();
 | 
			
		||||
    smp_mb();
 | 
			
		||||
    bh->scheduled = 1;
 | 
			
		||||
    aio_notify(bh->ctx);
 | 
			
		||||
    aio_notify(ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -629,6 +629,7 @@ static int block_save_setup(QEMUFile *f, void *opaque)
 | 
			
		||||
            block_mig_state.submitted, block_mig_state.transferred);
 | 
			
		||||
 | 
			
		||||
    qemu_mutex_lock_iothread();
 | 
			
		||||
    init_blk_migration(f);
 | 
			
		||||
 | 
			
		||||
    /* start track dirty blocks */
 | 
			
		||||
    ret = set_dirty_tracking();
 | 
			
		||||
@@ -638,8 +639,6 @@ static int block_save_setup(QEMUFile *f, void *opaque)
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    init_blk_migration(f);
 | 
			
		||||
 | 
			
		||||
    qemu_mutex_unlock_iothread();
 | 
			
		||||
 | 
			
		||||
    ret = flush_blks(f);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										144
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								block.c
									
									
									
									
									
								
							@@ -179,6 +179,7 @@ void bdrv_io_limits_enable(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    assert(!bs->io_limits_enabled);
 | 
			
		||||
    throttle_init(&bs->throttle_state,
 | 
			
		||||
                  bdrv_get_aio_context(bs),
 | 
			
		||||
                  QEMU_CLOCK_VIRTUAL,
 | 
			
		||||
                  bdrv_throttle_read_timer_cb,
 | 
			
		||||
                  bdrv_throttle_write_timer_cb,
 | 
			
		||||
@@ -363,6 +364,7 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
 | 
			
		||||
    qemu_co_queue_init(&bs->throttled_reqs[0]);
 | 
			
		||||
    qemu_co_queue_init(&bs->throttled_reqs[1]);
 | 
			
		||||
    bs->refcnt = 1;
 | 
			
		||||
    bs->aio_context = qemu_get_aio_context();
 | 
			
		||||
 | 
			
		||||
    return bs;
 | 
			
		||||
}
 | 
			
		||||
@@ -1856,7 +1858,11 @@ void bdrv_close_all(void)
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
        aio_context_acquire(aio_context);
 | 
			
		||||
        bdrv_close(bs);
 | 
			
		||||
        aio_context_release(aio_context);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1881,17 +1887,6 @@ static bool bdrv_requests_pending(BlockDriverState *bs)
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool bdrv_requests_pending_all(void)
 | 
			
		||||
{
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
 | 
			
		||||
        if (bdrv_requests_pending(bs)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Wait for pending requests to complete across all BlockDriverStates
 | 
			
		||||
 *
 | 
			
		||||
@@ -1911,12 +1906,20 @@ void bdrv_drain_all(void)
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
 | 
			
		||||
    while (busy) {
 | 
			
		||||
        QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
 | 
			
		||||
            bdrv_start_throttled_reqs(bs);
 | 
			
		||||
        }
 | 
			
		||||
        busy = false;
 | 
			
		||||
 | 
			
		||||
        busy = bdrv_requests_pending_all();
 | 
			
		||||
        busy |= aio_poll(qemu_get_aio_context(), busy);
 | 
			
		||||
        QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
 | 
			
		||||
            AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
            bool bs_busy;
 | 
			
		||||
 | 
			
		||||
            aio_context_acquire(aio_context);
 | 
			
		||||
            bdrv_start_throttled_reqs(bs);
 | 
			
		||||
            bs_busy = bdrv_requests_pending(bs);
 | 
			
		||||
            bs_busy |= aio_poll(aio_context, bs_busy);
 | 
			
		||||
            aio_context_release(aio_context);
 | 
			
		||||
 | 
			
		||||
            busy |= bs_busy;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2352,12 +2355,17 @@ int bdrv_commit_all(void)
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
        aio_context_acquire(aio_context);
 | 
			
		||||
        if (bs->drv && bs->backing_hd) {
 | 
			
		||||
            int ret = bdrv_commit(bs);
 | 
			
		||||
            if (ret < 0) {
 | 
			
		||||
                aio_context_release(aio_context);
 | 
			
		||||
                return ret;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        aio_context_release(aio_context);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -2775,10 +2783,12 @@ static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset,
 | 
			
		||||
        /* Fast-path if already in coroutine context */
 | 
			
		||||
        bdrv_rw_co_entry(&rwco);
 | 
			
		||||
    } else {
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
        co = qemu_coroutine_create(bdrv_rw_co_entry);
 | 
			
		||||
        qemu_coroutine_enter(co, &rwco);
 | 
			
		||||
        while (rwco.ret == NOT_DONE) {
 | 
			
		||||
            qemu_aio_wait();
 | 
			
		||||
            aio_poll(aio_context, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return rwco.ret;
 | 
			
		||||
@@ -3831,10 +3841,15 @@ int bdrv_flush_all(void)
 | 
			
		||||
    int result = 0;
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
 | 
			
		||||
        int ret = bdrv_flush(bs);
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
        int ret;
 | 
			
		||||
 | 
			
		||||
        aio_context_acquire(aio_context);
 | 
			
		||||
        ret = bdrv_flush(bs);
 | 
			
		||||
        if (ret < 0 && !result) {
 | 
			
		||||
            result = ret;
 | 
			
		||||
        }
 | 
			
		||||
        aio_context_release(aio_context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
@@ -4025,10 +4040,12 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
 | 
			
		||||
        /* Fast-path if already in coroutine context */
 | 
			
		||||
        bdrv_get_block_status_co_entry(&data);
 | 
			
		||||
    } else {
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
        co = qemu_coroutine_create(bdrv_get_block_status_co_entry);
 | 
			
		||||
        qemu_coroutine_enter(co, &data);
 | 
			
		||||
        while (!data.done) {
 | 
			
		||||
            qemu_aio_wait();
 | 
			
		||||
            aio_poll(aio_context, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return data.ret;
 | 
			
		||||
@@ -4621,7 +4638,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
 | 
			
		||||
    acb->is_write = is_write;
 | 
			
		||||
    acb->qiov = qiov;
 | 
			
		||||
    acb->bounce = qemu_blockalign(bs, qiov->size);
 | 
			
		||||
    acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
 | 
			
		||||
    acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_aio_bh_cb, acb);
 | 
			
		||||
 | 
			
		||||
    if (is_write) {
 | 
			
		||||
        qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
 | 
			
		||||
@@ -4660,13 +4677,14 @@ typedef struct BlockDriverAIOCBCoroutine {
 | 
			
		||||
 | 
			
		||||
static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
 | 
			
		||||
{
 | 
			
		||||
    AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
 | 
			
		||||
    BlockDriverAIOCBCoroutine *acb =
 | 
			
		||||
        container_of(blockacb, BlockDriverAIOCBCoroutine, common);
 | 
			
		||||
    bool done = false;
 | 
			
		||||
 | 
			
		||||
    acb->done = &done;
 | 
			
		||||
    while (!done) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(aio_context, true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -4703,7 +4721,7 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)
 | 
			
		||||
            acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
 | 
			
		||||
    acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
 | 
			
		||||
    qemu_bh_schedule(acb->bh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -4739,7 +4757,7 @@ static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
 | 
			
		||||
    BlockDriverState *bs = acb->common.bs;
 | 
			
		||||
 | 
			
		||||
    acb->req.error = bdrv_co_flush(bs);
 | 
			
		||||
    acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
 | 
			
		||||
    acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
 | 
			
		||||
    qemu_bh_schedule(acb->bh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -4766,7 +4784,7 @@ static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
 | 
			
		||||
    BlockDriverState *bs = acb->common.bs;
 | 
			
		||||
 | 
			
		||||
    acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors);
 | 
			
		||||
    acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
 | 
			
		||||
    acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
 | 
			
		||||
    qemu_bh_schedule(acb->bh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -4977,7 +4995,11 @@ void bdrv_invalidate_cache_all(Error **errp)
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
        aio_context_acquire(aio_context);
 | 
			
		||||
        bdrv_invalidate_cache(bs, &local_err);
 | 
			
		||||
        aio_context_release(aio_context);
 | 
			
		||||
        if (local_err) {
 | 
			
		||||
            error_propagate(errp, local_err);
 | 
			
		||||
            return;
 | 
			
		||||
@@ -4990,7 +5012,11 @@ void bdrv_clear_incoming_migration_all(void)
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
        aio_context_acquire(aio_context);
 | 
			
		||||
        bs->open_flags = bs->open_flags & ~(BDRV_O_INCOMING);
 | 
			
		||||
        aio_context_release(aio_context);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -5006,10 +5032,12 @@ int bdrv_flush(BlockDriverState *bs)
 | 
			
		||||
        /* Fast-path if already in coroutine context */
 | 
			
		||||
        bdrv_flush_co_entry(&rwco);
 | 
			
		||||
    } else {
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
        co = qemu_coroutine_create(bdrv_flush_co_entry);
 | 
			
		||||
        qemu_coroutine_enter(co, &rwco);
 | 
			
		||||
        while (rwco.ret == NOT_DONE) {
 | 
			
		||||
            qemu_aio_wait();
 | 
			
		||||
            aio_poll(aio_context, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -5119,10 +5147,12 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
 | 
			
		||||
        /* Fast-path if already in coroutine context */
 | 
			
		||||
        bdrv_discard_co_entry(&rwco);
 | 
			
		||||
    } else {
 | 
			
		||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
        co = qemu_coroutine_create(bdrv_discard_co_entry);
 | 
			
		||||
        qemu_coroutine_enter(co, &rwco);
 | 
			
		||||
        while (rwco.ret == NOT_DONE) {
 | 
			
		||||
            qemu_aio_wait();
 | 
			
		||||
            aio_poll(aio_context, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -5633,8 +5663,66 @@ out:
 | 
			
		||||
 | 
			
		||||
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    /* Currently BlockDriverState always uses the main loop AioContext */
 | 
			
		||||
    return qemu_get_aio_context();
 | 
			
		||||
    return bs->aio_context;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bdrv_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    if (!bs->drv) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (bs->io_limits_enabled) {
 | 
			
		||||
        throttle_detach_aio_context(&bs->throttle_state);
 | 
			
		||||
    }
 | 
			
		||||
    if (bs->drv->bdrv_detach_aio_context) {
 | 
			
		||||
        bs->drv->bdrv_detach_aio_context(bs);
 | 
			
		||||
    }
 | 
			
		||||
    if (bs->file) {
 | 
			
		||||
        bdrv_detach_aio_context(bs->file);
 | 
			
		||||
    }
 | 
			
		||||
    if (bs->backing_hd) {
 | 
			
		||||
        bdrv_detach_aio_context(bs->backing_hd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bs->aio_context = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bdrv_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                             AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    if (!bs->drv) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bs->aio_context = new_context;
 | 
			
		||||
 | 
			
		||||
    if (bs->backing_hd) {
 | 
			
		||||
        bdrv_attach_aio_context(bs->backing_hd, new_context);
 | 
			
		||||
    }
 | 
			
		||||
    if (bs->file) {
 | 
			
		||||
        bdrv_attach_aio_context(bs->file, new_context);
 | 
			
		||||
    }
 | 
			
		||||
    if (bs->drv->bdrv_attach_aio_context) {
 | 
			
		||||
        bs->drv->bdrv_attach_aio_context(bs, new_context);
 | 
			
		||||
    }
 | 
			
		||||
    if (bs->io_limits_enabled) {
 | 
			
		||||
        throttle_attach_aio_context(&bs->throttle_state, new_context);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    bdrv_drain_all(); /* ensure there are no in-flight requests */
 | 
			
		||||
 | 
			
		||||
    bdrv_detach_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    /* This function executes in the old AioContext so acquire the new one in
 | 
			
		||||
     * case it runs in a different thread.
 | 
			
		||||
     */
 | 
			
		||||
    aio_context_acquire(new_context);
 | 
			
		||||
    bdrv_attach_aio_context(bs, new_context);
 | 
			
		||||
    aio_context_release(new_context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bdrv_add_before_write_notifier(BlockDriverState *bs,
 | 
			
		||||
 
 | 
			
		||||
@@ -471,7 +471,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
 | 
			
		||||
    acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque);
 | 
			
		||||
    acb->ret = -error;
 | 
			
		||||
 | 
			
		||||
    bh = qemu_bh_new(error_callback_bh, acb);
 | 
			
		||||
    bh = aio_bh_new(bdrv_get_aio_context(bs), error_callback_bh, acb);
 | 
			
		||||
    acb->bh = bh;
 | 
			
		||||
    qemu_bh_schedule(bh);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,12 +39,13 @@ struct BlkverifyAIOCB {
 | 
			
		||||
static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
			
		||||
{
 | 
			
		||||
    BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb;
 | 
			
		||||
    AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
 | 
			
		||||
    bool finished = false;
 | 
			
		||||
 | 
			
		||||
    /* Wait until request completes, invokes its callback, and frees itself */
 | 
			
		||||
    acb->finished = &finished;
 | 
			
		||||
    while (!finished) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(aio_context, true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -228,7 +229,8 @@ static void blkverify_aio_cb(void *opaque, int ret)
 | 
			
		||||
            acb->verify(acb);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        acb->bh = qemu_bh_new(blkverify_aio_bh, acb);
 | 
			
		||||
        acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
 | 
			
		||||
                             blkverify_aio_bh, acb);
 | 
			
		||||
        qemu_bh_schedule(acb->bh);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -302,21 +304,40 @@ static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs,
 | 
			
		||||
    return bdrv_recurse_is_first_non_filter(s->test_file, candidate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Propagate AioContext changes to ->test_file */
 | 
			
		||||
static void blkverify_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVBlkverifyState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    bdrv_detach_aio_context(s->test_file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void blkverify_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                         AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    BDRVBlkverifyState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    bdrv_attach_aio_context(s->test_file, new_context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_blkverify = {
 | 
			
		||||
    .format_name            = "blkverify",
 | 
			
		||||
    .protocol_name          = "blkverify",
 | 
			
		||||
    .instance_size          = sizeof(BDRVBlkverifyState),
 | 
			
		||||
    .format_name                      = "blkverify",
 | 
			
		||||
    .protocol_name                    = "blkverify",
 | 
			
		||||
    .instance_size                    = sizeof(BDRVBlkverifyState),
 | 
			
		||||
 | 
			
		||||
    .bdrv_parse_filename    = blkverify_parse_filename,
 | 
			
		||||
    .bdrv_file_open         = blkverify_open,
 | 
			
		||||
    .bdrv_close             = blkverify_close,
 | 
			
		||||
    .bdrv_getlength         = blkverify_getlength,
 | 
			
		||||
    .bdrv_parse_filename              = blkverify_parse_filename,
 | 
			
		||||
    .bdrv_file_open                   = blkverify_open,
 | 
			
		||||
    .bdrv_close                       = blkverify_close,
 | 
			
		||||
    .bdrv_getlength                   = blkverify_getlength,
 | 
			
		||||
 | 
			
		||||
    .bdrv_aio_readv         = blkverify_aio_readv,
 | 
			
		||||
    .bdrv_aio_writev        = blkverify_aio_writev,
 | 
			
		||||
    .bdrv_aio_flush         = blkverify_aio_flush,
 | 
			
		||||
    .bdrv_aio_readv                   = blkverify_aio_readv,
 | 
			
		||||
    .bdrv_aio_writev                  = blkverify_aio_writev,
 | 
			
		||||
    .bdrv_aio_flush                   = blkverify_aio_flush,
 | 
			
		||||
 | 
			
		||||
    .is_filter              = true,
 | 
			
		||||
    .bdrv_attach_aio_context          = blkverify_attach_aio_context,
 | 
			
		||||
    .bdrv_detach_aio_context          = blkverify_detach_aio_context,
 | 
			
		||||
 | 
			
		||||
    .is_filter                        = true,
 | 
			
		||||
    .bdrv_recurse_is_first_non_filter = blkverify_recurse_is_first_non_filter,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										192
									
								
								block/curl.c
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								block/curl.c
									
									
									
									
									
								
							@@ -110,6 +110,7 @@ typedef struct BDRVCURLState {
 | 
			
		||||
    size_t readahead_size;
 | 
			
		||||
    bool sslverify;
 | 
			
		||||
    bool accept_range;
 | 
			
		||||
    AioContext *aio_context;
 | 
			
		||||
} BDRVCURLState;
 | 
			
		||||
 | 
			
		||||
static void curl_clean_state(CURLState *s);
 | 
			
		||||
@@ -134,25 +135,29 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
 | 
			
		||||
                        void *s, void *sp)
 | 
			
		||||
                        void *userp, void *sp)
 | 
			
		||||
{
 | 
			
		||||
    BDRVCURLState *s;
 | 
			
		||||
    CURLState *state = NULL;
 | 
			
		||||
    curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
 | 
			
		||||
    state->sock_fd = fd;
 | 
			
		||||
    s = state->s;
 | 
			
		||||
 | 
			
		||||
    DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
 | 
			
		||||
    switch (action) {
 | 
			
		||||
        case CURL_POLL_IN:
 | 
			
		||||
            qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, state);
 | 
			
		||||
            aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
 | 
			
		||||
                               NULL, state);
 | 
			
		||||
            break;
 | 
			
		||||
        case CURL_POLL_OUT:
 | 
			
		||||
            qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, state);
 | 
			
		||||
            aio_set_fd_handler(s->aio_context, fd, NULL, curl_multi_do, state);
 | 
			
		||||
            break;
 | 
			
		||||
        case CURL_POLL_INOUT:
 | 
			
		||||
            qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, state);
 | 
			
		||||
            aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
 | 
			
		||||
                               curl_multi_do, state);
 | 
			
		||||
            break;
 | 
			
		||||
        case CURL_POLL_REMOVE:
 | 
			
		||||
            qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
 | 
			
		||||
            aio_set_fd_handler(s->aio_context, fd, NULL, NULL, NULL);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -365,7 +370,7 @@ static CURLState *curl_init_state(BDRVCURLState *s)
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (!state) {
 | 
			
		||||
            qemu_aio_wait();
 | 
			
		||||
            aio_poll(state->s->aio_context, true);
 | 
			
		||||
        }
 | 
			
		||||
    } while(!state);
 | 
			
		||||
 | 
			
		||||
@@ -422,6 +427,51 @@ static void curl_parse_filename(const char *filename, QDict *options,
 | 
			
		||||
    qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void curl_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVCURLState *s = bs->opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < CURL_NUM_STATES; i++) {
 | 
			
		||||
        if (s->states[i].in_use) {
 | 
			
		||||
            curl_clean_state(&s->states[i]);
 | 
			
		||||
        }
 | 
			
		||||
        if (s->states[i].curl) {
 | 
			
		||||
            curl_easy_cleanup(s->states[i].curl);
 | 
			
		||||
            s->states[i].curl = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        if (s->states[i].orig_buf) {
 | 
			
		||||
            g_free(s->states[i].orig_buf);
 | 
			
		||||
            s->states[i].orig_buf = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (s->multi) {
 | 
			
		||||
        curl_multi_cleanup(s->multi);
 | 
			
		||||
        s->multi = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    timer_del(&s->timer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void curl_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                    AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    BDRVCURLState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    aio_timer_init(new_context, &s->timer,
 | 
			
		||||
                   QEMU_CLOCK_REALTIME, SCALE_NS,
 | 
			
		||||
                   curl_multi_timeout_do, s);
 | 
			
		||||
 | 
			
		||||
    assert(!s->multi);
 | 
			
		||||
    s->multi = curl_multi_init();
 | 
			
		||||
    s->aio_context = new_context;
 | 
			
		||||
    curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
 | 
			
		||||
#ifdef NEED_CURL_TIMER_CALLBACK
 | 
			
		||||
    curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
 | 
			
		||||
    curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QemuOptsList runtime_opts = {
 | 
			
		||||
    .name = "curl",
 | 
			
		||||
    .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
 | 
			
		||||
@@ -491,6 +541,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DPRINTF("CURL: Opening %s\n", file);
 | 
			
		||||
    s->aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
    s->url = g_strdup(file);
 | 
			
		||||
    state = curl_init_state(s);
 | 
			
		||||
    if (!state)
 | 
			
		||||
@@ -523,19 +574,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    curl_easy_cleanup(state->curl);
 | 
			
		||||
    state->curl = NULL;
 | 
			
		||||
 | 
			
		||||
    aio_timer_init(bdrv_get_aio_context(bs), &s->timer,
 | 
			
		||||
                   QEMU_CLOCK_REALTIME, SCALE_NS,
 | 
			
		||||
                   curl_multi_timeout_do, s);
 | 
			
		||||
 | 
			
		||||
    // Now we know the file exists and its size, so let's
 | 
			
		||||
    // initialize the multi interface!
 | 
			
		||||
 | 
			
		||||
    s->multi = curl_multi_init();
 | 
			
		||||
    curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
 | 
			
		||||
#ifdef NEED_CURL_TIMER_CALLBACK
 | 
			
		||||
    curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
 | 
			
		||||
    curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
 | 
			
		||||
#endif
 | 
			
		||||
    curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
 | 
			
		||||
 | 
			
		||||
    qemu_opts_del(opts);
 | 
			
		||||
    return 0;
 | 
			
		||||
@@ -630,7 +669,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
 | 
			
		||||
    acb->sector_num = sector_num;
 | 
			
		||||
    acb->nb_sectors = nb_sectors;
 | 
			
		||||
 | 
			
		||||
    acb->bh = qemu_bh_new(curl_readv_bh_cb, acb);
 | 
			
		||||
    acb->bh = aio_bh_new(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
 | 
			
		||||
    qemu_bh_schedule(acb->bh);
 | 
			
		||||
    return &acb->common;
 | 
			
		||||
}
 | 
			
		||||
@@ -638,25 +677,9 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
 | 
			
		||||
static void curl_close(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVCURLState *s = bs->opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    DPRINTF("CURL: Close\n");
 | 
			
		||||
    for (i=0; i<CURL_NUM_STATES; i++) {
 | 
			
		||||
        if (s->states[i].in_use)
 | 
			
		||||
            curl_clean_state(&s->states[i]);
 | 
			
		||||
        if (s->states[i].curl) {
 | 
			
		||||
            curl_easy_cleanup(s->states[i].curl);
 | 
			
		||||
            s->states[i].curl = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        if (s->states[i].orig_buf) {
 | 
			
		||||
            g_free(s->states[i].orig_buf);
 | 
			
		||||
            s->states[i].orig_buf = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (s->multi)
 | 
			
		||||
        curl_multi_cleanup(s->multi);
 | 
			
		||||
 | 
			
		||||
    timer_del(&s->timer);
 | 
			
		||||
    curl_detach_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    g_free(s->url);
 | 
			
		||||
}
 | 
			
		||||
@@ -668,68 +691,83 @@ static int64_t curl_getlength(BlockDriverState *bs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_http = {
 | 
			
		||||
    .format_name            = "http",
 | 
			
		||||
    .protocol_name          = "http",
 | 
			
		||||
    .format_name                = "http",
 | 
			
		||||
    .protocol_name              = "http",
 | 
			
		||||
 | 
			
		||||
    .instance_size          = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename    = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open         = curl_open,
 | 
			
		||||
    .bdrv_close             = curl_close,
 | 
			
		||||
    .bdrv_getlength         = curl_getlength,
 | 
			
		||||
    .instance_size              = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename        = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open             = curl_open,
 | 
			
		||||
    .bdrv_close                 = curl_close,
 | 
			
		||||
    .bdrv_getlength             = curl_getlength,
 | 
			
		||||
 | 
			
		||||
    .bdrv_aio_readv         = curl_aio_readv,
 | 
			
		||||
    .bdrv_aio_readv             = curl_aio_readv,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context    = curl_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context    = curl_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_https = {
 | 
			
		||||
    .format_name            = "https",
 | 
			
		||||
    .protocol_name          = "https",
 | 
			
		||||
    .format_name                = "https",
 | 
			
		||||
    .protocol_name              = "https",
 | 
			
		||||
 | 
			
		||||
    .instance_size          = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename    = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open         = curl_open,
 | 
			
		||||
    .bdrv_close             = curl_close,
 | 
			
		||||
    .bdrv_getlength         = curl_getlength,
 | 
			
		||||
    .instance_size              = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename        = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open             = curl_open,
 | 
			
		||||
    .bdrv_close                 = curl_close,
 | 
			
		||||
    .bdrv_getlength             = curl_getlength,
 | 
			
		||||
 | 
			
		||||
    .bdrv_aio_readv         = curl_aio_readv,
 | 
			
		||||
    .bdrv_aio_readv             = curl_aio_readv,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context    = curl_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context    = curl_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_ftp = {
 | 
			
		||||
    .format_name            = "ftp",
 | 
			
		||||
    .protocol_name          = "ftp",
 | 
			
		||||
    .format_name                = "ftp",
 | 
			
		||||
    .protocol_name              = "ftp",
 | 
			
		||||
 | 
			
		||||
    .instance_size          = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename    = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open         = curl_open,
 | 
			
		||||
    .bdrv_close             = curl_close,
 | 
			
		||||
    .bdrv_getlength         = curl_getlength,
 | 
			
		||||
    .instance_size              = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename        = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open             = curl_open,
 | 
			
		||||
    .bdrv_close                 = curl_close,
 | 
			
		||||
    .bdrv_getlength             = curl_getlength,
 | 
			
		||||
 | 
			
		||||
    .bdrv_aio_readv         = curl_aio_readv,
 | 
			
		||||
    .bdrv_aio_readv             = curl_aio_readv,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context    = curl_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context    = curl_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_ftps = {
 | 
			
		||||
    .format_name            = "ftps",
 | 
			
		||||
    .protocol_name          = "ftps",
 | 
			
		||||
    .format_name                = "ftps",
 | 
			
		||||
    .protocol_name              = "ftps",
 | 
			
		||||
 | 
			
		||||
    .instance_size          = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename    = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open         = curl_open,
 | 
			
		||||
    .bdrv_close             = curl_close,
 | 
			
		||||
    .bdrv_getlength         = curl_getlength,
 | 
			
		||||
    .instance_size              = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename        = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open             = curl_open,
 | 
			
		||||
    .bdrv_close                 = curl_close,
 | 
			
		||||
    .bdrv_getlength             = curl_getlength,
 | 
			
		||||
 | 
			
		||||
    .bdrv_aio_readv         = curl_aio_readv,
 | 
			
		||||
    .bdrv_aio_readv             = curl_aio_readv,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context    = curl_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context    = curl_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_tftp = {
 | 
			
		||||
    .format_name            = "tftp",
 | 
			
		||||
    .protocol_name          = "tftp",
 | 
			
		||||
    .format_name                = "tftp",
 | 
			
		||||
    .protocol_name              = "tftp",
 | 
			
		||||
 | 
			
		||||
    .instance_size          = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename    = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open         = curl_open,
 | 
			
		||||
    .bdrv_close             = curl_close,
 | 
			
		||||
    .bdrv_getlength         = curl_getlength,
 | 
			
		||||
    .instance_size              = sizeof(BDRVCURLState),
 | 
			
		||||
    .bdrv_parse_filename        = curl_parse_filename,
 | 
			
		||||
    .bdrv_file_open             = curl_open,
 | 
			
		||||
    .bdrv_close                 = curl_close,
 | 
			
		||||
    .bdrv_getlength             = curl_getlength,
 | 
			
		||||
 | 
			
		||||
    .bdrv_aio_readv         = curl_aio_readv,
 | 
			
		||||
    .bdrv_aio_readv             = curl_aio_readv,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context    = curl_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context    = curl_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void curl_block_init(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ typedef struct GlusterAIOCB {
 | 
			
		||||
    int ret;
 | 
			
		||||
    QEMUBH *bh;
 | 
			
		||||
    Coroutine *coroutine;
 | 
			
		||||
    AioContext *aio_context;
 | 
			
		||||
} GlusterAIOCB;
 | 
			
		||||
 | 
			
		||||
typedef struct BDRVGlusterState {
 | 
			
		||||
@@ -249,7 +250,7 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
 | 
			
		||||
        acb->ret = -EIO; /* Partial read/write - fail it */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    acb->bh = qemu_bh_new(qemu_gluster_complete_aio, acb);
 | 
			
		||||
    acb->bh = aio_bh_new(acb->aio_context, qemu_gluster_complete_aio, acb);
 | 
			
		||||
    qemu_bh_schedule(acb->bh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -436,6 +437,7 @@ static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs,
 | 
			
		||||
    acb->size = size;
 | 
			
		||||
    acb->ret = 0;
 | 
			
		||||
    acb->coroutine = qemu_coroutine_self();
 | 
			
		||||
    acb->aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    ret = glfs_zerofill_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
@@ -549,6 +551,7 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
 | 
			
		||||
    acb->size = size;
 | 
			
		||||
    acb->ret = 0;
 | 
			
		||||
    acb->coroutine = qemu_coroutine_self();
 | 
			
		||||
    acb->aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    if (write) {
 | 
			
		||||
        ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
 | 
			
		||||
@@ -605,6 +608,7 @@ static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
 | 
			
		||||
    acb->size = 0;
 | 
			
		||||
    acb->ret = 0;
 | 
			
		||||
    acb->coroutine = qemu_coroutine_self();
 | 
			
		||||
    acb->aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
@@ -633,6 +637,7 @@ static coroutine_fn int qemu_gluster_co_discard(BlockDriverState *bs,
 | 
			
		||||
    acb->size = 0;
 | 
			
		||||
    acb->ret = 0;
 | 
			
		||||
    acb->coroutine = qemu_coroutine_self();
 | 
			
		||||
    acb->aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    ret = glfs_discard_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,7 @@
 | 
			
		||||
 | 
			
		||||
typedef struct IscsiLun {
 | 
			
		||||
    struct iscsi_context *iscsi;
 | 
			
		||||
    AioContext *aio_context;
 | 
			
		||||
    int lun;
 | 
			
		||||
    enum scsi_inquiry_peripheral_device_type type;
 | 
			
		||||
    int block_size;
 | 
			
		||||
@@ -73,6 +74,7 @@ typedef struct IscsiTask {
 | 
			
		||||
    struct scsi_task *task;
 | 
			
		||||
    Coroutine *co;
 | 
			
		||||
    QEMUBH *bh;
 | 
			
		||||
    IscsiLun *iscsilun;
 | 
			
		||||
} IscsiTask;
 | 
			
		||||
 | 
			
		||||
typedef struct IscsiAIOCB {
 | 
			
		||||
@@ -133,7 +135,7 @@ iscsi_schedule_bh(IscsiAIOCB *acb)
 | 
			
		||||
    if (acb->bh) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
 | 
			
		||||
    acb->bh = aio_bh_new(acb->iscsilun->aio_context, iscsi_bh_cb, acb);
 | 
			
		||||
    qemu_bh_schedule(acb->bh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -169,7 +171,8 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
    if (iTask->co) {
 | 
			
		||||
        iTask->bh = qemu_bh_new(iscsi_co_generic_bh_cb, iTask);
 | 
			
		||||
        iTask->bh = aio_bh_new(iTask->iscsilun->aio_context,
 | 
			
		||||
                               iscsi_co_generic_bh_cb, iTask);
 | 
			
		||||
        qemu_bh_schedule(iTask->bh);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -177,8 +180,9 @@ out:
 | 
			
		||||
static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
 | 
			
		||||
{
 | 
			
		||||
    *iTask = (struct IscsiTask) {
 | 
			
		||||
        .co         = qemu_coroutine_self(),
 | 
			
		||||
        .retries    = ISCSI_CMD_RETRIES,
 | 
			
		||||
        .co             = qemu_coroutine_self(),
 | 
			
		||||
        .retries        = ISCSI_CMD_RETRIES,
 | 
			
		||||
        .iscsilun       = iscsilun,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -209,7 +213,7 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
			
		||||
                                     iscsi_abort_task_cb, acb);
 | 
			
		||||
 | 
			
		||||
    while (acb->status == -EINPROGRESS) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(iscsilun->aio_context, true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -232,10 +236,11 @@ iscsi_set_events(IscsiLun *iscsilun)
 | 
			
		||||
    ev = POLLIN;
 | 
			
		||||
    ev |= iscsi_which_events(iscsi);
 | 
			
		||||
    if (ev != iscsilun->events) {
 | 
			
		||||
        qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
 | 
			
		||||
                      iscsi_process_read,
 | 
			
		||||
                      (ev & POLLOUT) ? iscsi_process_write : NULL,
 | 
			
		||||
                      iscsilun);
 | 
			
		||||
        aio_set_fd_handler(iscsilun->aio_context,
 | 
			
		||||
                           iscsi_get_fd(iscsi),
 | 
			
		||||
                           iscsi_process_read,
 | 
			
		||||
                           (ev & POLLOUT) ? iscsi_process_write : NULL,
 | 
			
		||||
                           iscsilun);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -791,7 +796,7 @@ static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
 | 
			
		||||
        iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);
 | 
			
		||||
 | 
			
		||||
        while (status == -EINPROGRESS) {
 | 
			
		||||
            qemu_aio_wait();
 | 
			
		||||
            aio_poll(iscsilun->aio_context, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
@@ -1195,6 +1200,40 @@ fail_with_err:
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void iscsi_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    IscsiLun *iscsilun = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    aio_set_fd_handler(iscsilun->aio_context,
 | 
			
		||||
                       iscsi_get_fd(iscsilun->iscsi),
 | 
			
		||||
                       NULL, NULL, NULL);
 | 
			
		||||
    iscsilun->events = 0;
 | 
			
		||||
 | 
			
		||||
    if (iscsilun->nop_timer) {
 | 
			
		||||
        timer_del(iscsilun->nop_timer);
 | 
			
		||||
        timer_free(iscsilun->nop_timer);
 | 
			
		||||
        iscsilun->nop_timer = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void iscsi_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                     AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    IscsiLun *iscsilun = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    iscsilun->aio_context = new_context;
 | 
			
		||||
    iscsi_set_events(iscsilun);
 | 
			
		||||
 | 
			
		||||
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
 | 
			
		||||
    /* Set up a timer for sending out iSCSI NOPs */
 | 
			
		||||
    iscsilun->nop_timer = aio_timer_new(iscsilun->aio_context,
 | 
			
		||||
                                        QEMU_CLOCK_REALTIME, SCALE_MS,
 | 
			
		||||
                                        iscsi_nop_timed_event, iscsilun);
 | 
			
		||||
    timer_mod(iscsilun->nop_timer,
 | 
			
		||||
              qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * We support iscsi url's on the form
 | 
			
		||||
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
 | 
			
		||||
@@ -1301,6 +1340,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    iscsilun->iscsi = iscsi;
 | 
			
		||||
    iscsilun->aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
    iscsilun->lun   = iscsi_url->lun;
 | 
			
		||||
    iscsilun->has_write_same = true;
 | 
			
		||||
 | 
			
		||||
@@ -1374,11 +1414,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    scsi_free_scsi_task(task);
 | 
			
		||||
    task = NULL;
 | 
			
		||||
 | 
			
		||||
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
 | 
			
		||||
    /* Set up a timer for sending out iSCSI NOPs */
 | 
			
		||||
    iscsilun->nop_timer = timer_new_ms(QEMU_CLOCK_REALTIME, iscsi_nop_timed_event, iscsilun);
 | 
			
		||||
    timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
 | 
			
		||||
#endif
 | 
			
		||||
    iscsi_attach_aio_context(bs, iscsilun->aio_context);
 | 
			
		||||
 | 
			
		||||
    /* Guess the internal cluster (page) size of the iscsi target by the means
 | 
			
		||||
     * of opt_unmap_gran. Transfer the unmap granularity only if it has a
 | 
			
		||||
@@ -1422,11 +1458,7 @@ static void iscsi_close(BlockDriverState *bs)
 | 
			
		||||
    IscsiLun *iscsilun = bs->opaque;
 | 
			
		||||
    struct iscsi_context *iscsi = iscsilun->iscsi;
 | 
			
		||||
 | 
			
		||||
    if (iscsilun->nop_timer) {
 | 
			
		||||
        timer_del(iscsilun->nop_timer);
 | 
			
		||||
        timer_free(iscsilun->nop_timer);
 | 
			
		||||
    }
 | 
			
		||||
    qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
 | 
			
		||||
    iscsi_detach_aio_context(bs);
 | 
			
		||||
    iscsi_destroy_context(iscsi);
 | 
			
		||||
    g_free(iscsilun->zeroblock);
 | 
			
		||||
    g_free(iscsilun->allocationmap);
 | 
			
		||||
@@ -1530,10 +1562,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    if (iscsilun->nop_timer) {
 | 
			
		||||
        timer_del(iscsilun->nop_timer);
 | 
			
		||||
        timer_free(iscsilun->nop_timer);
 | 
			
		||||
    }
 | 
			
		||||
    iscsi_detach_aio_context(bs);
 | 
			
		||||
    if (iscsilun->type != TYPE_DISK) {
 | 
			
		||||
        ret = -ENODEV;
 | 
			
		||||
        goto out;
 | 
			
		||||
@@ -1604,6 +1633,9 @@ static BlockDriver bdrv_iscsi = {
 | 
			
		||||
    .bdrv_ioctl       = iscsi_ioctl,
 | 
			
		||||
    .bdrv_aio_ioctl   = iscsi_aio_ioctl,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = iscsi_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = iscsi_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static QemuOptsList qemu_iscsi_opts = {
 | 
			
		||||
 
 | 
			
		||||
@@ -177,6 +177,20 @@ out_free_aiocb:
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void laio_detach_aio_context(void *s_, AioContext *old_context)
 | 
			
		||||
{
 | 
			
		||||
    struct qemu_laio_state *s = s_;
 | 
			
		||||
 | 
			
		||||
    aio_set_event_notifier(old_context, &s->e, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void laio_attach_aio_context(void *s_, AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    struct qemu_laio_state *s = s_;
 | 
			
		||||
 | 
			
		||||
    aio_set_event_notifier(new_context, &s->e, qemu_laio_completion_cb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *laio_init(void)
 | 
			
		||||
{
 | 
			
		||||
    struct qemu_laio_state *s;
 | 
			
		||||
@@ -190,8 +204,6 @@ void *laio_init(void)
 | 
			
		||||
        goto out_close_efd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb);
 | 
			
		||||
 | 
			
		||||
    return s;
 | 
			
		||||
 | 
			
		||||
out_close_efd:
 | 
			
		||||
@@ -200,3 +212,11 @@ out_free_state:
 | 
			
		||||
    g_free(s);
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void laio_cleanup(void *s_)
 | 
			
		||||
{
 | 
			
		||||
    struct qemu_laio_state *s = s_;
 | 
			
		||||
 | 
			
		||||
    event_notifier_cleanup(&s->e);
 | 
			
		||||
    g_free(s);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ static void nbd_teardown_connection(NbdClientSession *client)
 | 
			
		||||
    shutdown(client->sock, 2);
 | 
			
		||||
    nbd_recv_coroutines_enter_all(client);
 | 
			
		||||
 | 
			
		||||
    qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
 | 
			
		||||
    nbd_client_session_detach_aio_context(client);
 | 
			
		||||
    closesocket(client->sock);
 | 
			
		||||
    client->sock = -1;
 | 
			
		||||
}
 | 
			
		||||
@@ -103,11 +103,14 @@ static int nbd_co_send_request(NbdClientSession *s,
 | 
			
		||||
    struct nbd_request *request,
 | 
			
		||||
    QEMUIOVector *qiov, int offset)
 | 
			
		||||
{
 | 
			
		||||
    AioContext *aio_context;
 | 
			
		||||
    int rc, ret;
 | 
			
		||||
 | 
			
		||||
    qemu_co_mutex_lock(&s->send_mutex);
 | 
			
		||||
    s->send_coroutine = qemu_coroutine_self();
 | 
			
		||||
    qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, s);
 | 
			
		||||
    aio_context = bdrv_get_aio_context(s->bs);
 | 
			
		||||
    aio_set_fd_handler(aio_context, s->sock,
 | 
			
		||||
                       nbd_reply_ready, nbd_restart_write, s);
 | 
			
		||||
    if (qiov) {
 | 
			
		||||
        if (!s->is_unix) {
 | 
			
		||||
            socket_set_cork(s->sock, 1);
 | 
			
		||||
@@ -126,7 +129,7 @@ static int nbd_co_send_request(NbdClientSession *s,
 | 
			
		||||
    } else {
 | 
			
		||||
        rc = nbd_send_request(s->sock, request);
 | 
			
		||||
    }
 | 
			
		||||
    qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, s);
 | 
			
		||||
    aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, s);
 | 
			
		||||
    s->send_coroutine = NULL;
 | 
			
		||||
    qemu_co_mutex_unlock(&s->send_mutex);
 | 
			
		||||
    return rc;
 | 
			
		||||
@@ -335,6 +338,19 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nbd_client_session_detach_aio_context(NbdClientSession *client)
 | 
			
		||||
{
 | 
			
		||||
    aio_set_fd_handler(bdrv_get_aio_context(client->bs), client->sock,
 | 
			
		||||
                       NULL, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nbd_client_session_attach_aio_context(NbdClientSession *client,
 | 
			
		||||
                                           AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    aio_set_fd_handler(new_context, client->sock,
 | 
			
		||||
                       nbd_reply_ready, NULL, client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nbd_client_session_close(NbdClientSession *client)
 | 
			
		||||
{
 | 
			
		||||
    struct nbd_request request = {
 | 
			
		||||
@@ -381,7 +397,7 @@ int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs,
 | 
			
		||||
    /* Now that we're connected, set the socket to be non-blocking and
 | 
			
		||||
     * kick the reply mechanism.  */
 | 
			
		||||
    qemu_set_nonblock(sock);
 | 
			
		||||
    qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, client);
 | 
			
		||||
    nbd_client_session_attach_aio_context(client, bdrv_get_aio_context(bs));
 | 
			
		||||
 | 
			
		||||
    logout("Established connection with NBD server\n");
 | 
			
		||||
    return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -47,4 +47,8 @@ int nbd_client_session_co_writev(NbdClientSession *client, int64_t sector_num,
 | 
			
		||||
int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num,
 | 
			
		||||
                                int nb_sectors, QEMUIOVector *qiov);
 | 
			
		||||
 | 
			
		||||
void nbd_client_session_detach_aio_context(NbdClientSession *client);
 | 
			
		||||
void nbd_client_session_attach_aio_context(NbdClientSession *client,
 | 
			
		||||
                                           AioContext *new_context);
 | 
			
		||||
 | 
			
		||||
#endif /* NBD_CLIENT_H */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										87
									
								
								block/nbd.c
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								block/nbd.c
									
									
									
									
									
								
							@@ -323,46 +323,67 @@ static int64_t nbd_getlength(BlockDriverState *bs)
 | 
			
		||||
    return s->client.size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nbd_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVNBDState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    nbd_client_session_detach_aio_context(&s->client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nbd_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                   AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    BDRVNBDState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    nbd_client_session_attach_aio_context(&s->client, new_context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_nbd = {
 | 
			
		||||
    .format_name         = "nbd",
 | 
			
		||||
    .protocol_name       = "nbd",
 | 
			
		||||
    .instance_size       = sizeof(BDRVNBDState),
 | 
			
		||||
    .bdrv_parse_filename = nbd_parse_filename,
 | 
			
		||||
    .bdrv_file_open      = nbd_open,
 | 
			
		||||
    .bdrv_co_readv       = nbd_co_readv,
 | 
			
		||||
    .bdrv_co_writev      = nbd_co_writev,
 | 
			
		||||
    .bdrv_close          = nbd_close,
 | 
			
		||||
    .bdrv_co_flush_to_os = nbd_co_flush,
 | 
			
		||||
    .bdrv_co_discard     = nbd_co_discard,
 | 
			
		||||
    .bdrv_getlength      = nbd_getlength,
 | 
			
		||||
    .format_name                = "nbd",
 | 
			
		||||
    .protocol_name              = "nbd",
 | 
			
		||||
    .instance_size              = sizeof(BDRVNBDState),
 | 
			
		||||
    .bdrv_parse_filename        = nbd_parse_filename,
 | 
			
		||||
    .bdrv_file_open             = nbd_open,
 | 
			
		||||
    .bdrv_co_readv              = nbd_co_readv,
 | 
			
		||||
    .bdrv_co_writev             = nbd_co_writev,
 | 
			
		||||
    .bdrv_close                 = nbd_close,
 | 
			
		||||
    .bdrv_co_flush_to_os        = nbd_co_flush,
 | 
			
		||||
    .bdrv_co_discard            = nbd_co_discard,
 | 
			
		||||
    .bdrv_getlength             = nbd_getlength,
 | 
			
		||||
    .bdrv_detach_aio_context    = nbd_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context    = nbd_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_nbd_tcp = {
 | 
			
		||||
    .format_name         = "nbd",
 | 
			
		||||
    .protocol_name       = "nbd+tcp",
 | 
			
		||||
    .instance_size       = sizeof(BDRVNBDState),
 | 
			
		||||
    .bdrv_parse_filename = nbd_parse_filename,
 | 
			
		||||
    .bdrv_file_open      = nbd_open,
 | 
			
		||||
    .bdrv_co_readv       = nbd_co_readv,
 | 
			
		||||
    .bdrv_co_writev      = nbd_co_writev,
 | 
			
		||||
    .bdrv_close          = nbd_close,
 | 
			
		||||
    .bdrv_co_flush_to_os = nbd_co_flush,
 | 
			
		||||
    .bdrv_co_discard     = nbd_co_discard,
 | 
			
		||||
    .bdrv_getlength      = nbd_getlength,
 | 
			
		||||
    .format_name                = "nbd",
 | 
			
		||||
    .protocol_name              = "nbd+tcp",
 | 
			
		||||
    .instance_size              = sizeof(BDRVNBDState),
 | 
			
		||||
    .bdrv_parse_filename        = nbd_parse_filename,
 | 
			
		||||
    .bdrv_file_open             = nbd_open,
 | 
			
		||||
    .bdrv_co_readv              = nbd_co_readv,
 | 
			
		||||
    .bdrv_co_writev             = nbd_co_writev,
 | 
			
		||||
    .bdrv_close                 = nbd_close,
 | 
			
		||||
    .bdrv_co_flush_to_os        = nbd_co_flush,
 | 
			
		||||
    .bdrv_co_discard            = nbd_co_discard,
 | 
			
		||||
    .bdrv_getlength             = nbd_getlength,
 | 
			
		||||
    .bdrv_detach_aio_context    = nbd_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context    = nbd_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_nbd_unix = {
 | 
			
		||||
    .format_name         = "nbd",
 | 
			
		||||
    .protocol_name       = "nbd+unix",
 | 
			
		||||
    .instance_size       = sizeof(BDRVNBDState),
 | 
			
		||||
    .bdrv_parse_filename = nbd_parse_filename,
 | 
			
		||||
    .bdrv_file_open      = nbd_open,
 | 
			
		||||
    .bdrv_co_readv       = nbd_co_readv,
 | 
			
		||||
    .bdrv_co_writev      = nbd_co_writev,
 | 
			
		||||
    .bdrv_close          = nbd_close,
 | 
			
		||||
    .bdrv_co_flush_to_os = nbd_co_flush,
 | 
			
		||||
    .bdrv_co_discard     = nbd_co_discard,
 | 
			
		||||
    .bdrv_getlength      = nbd_getlength,
 | 
			
		||||
    .format_name                = "nbd",
 | 
			
		||||
    .protocol_name              = "nbd+unix",
 | 
			
		||||
    .instance_size              = sizeof(BDRVNBDState),
 | 
			
		||||
    .bdrv_parse_filename        = nbd_parse_filename,
 | 
			
		||||
    .bdrv_file_open             = nbd_open,
 | 
			
		||||
    .bdrv_co_readv              = nbd_co_readv,
 | 
			
		||||
    .bdrv_co_writev             = nbd_co_writev,
 | 
			
		||||
    .bdrv_close                 = nbd_close,
 | 
			
		||||
    .bdrv_co_flush_to_os        = nbd_co_flush,
 | 
			
		||||
    .bdrv_co_discard            = nbd_co_discard,
 | 
			
		||||
    .bdrv_getlength             = nbd_getlength,
 | 
			
		||||
    .bdrv_detach_aio_context    = nbd_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context    = nbd_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void bdrv_nbd_init(void)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										75
									
								
								block/nfs.c
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								block/nfs.c
									
									
									
									
									
								
							@@ -40,6 +40,7 @@ typedef struct NFSClient {
 | 
			
		||||
    struct nfsfh *fh;
 | 
			
		||||
    int events;
 | 
			
		||||
    bool has_zero_init;
 | 
			
		||||
    AioContext *aio_context;
 | 
			
		||||
} NFSClient;
 | 
			
		||||
 | 
			
		||||
typedef struct NFSRPC {
 | 
			
		||||
@@ -49,6 +50,7 @@ typedef struct NFSRPC {
 | 
			
		||||
    struct stat *st;
 | 
			
		||||
    Coroutine *co;
 | 
			
		||||
    QEMUBH *bh;
 | 
			
		||||
    NFSClient *client;
 | 
			
		||||
} NFSRPC;
 | 
			
		||||
 | 
			
		||||
static void nfs_process_read(void *arg);
 | 
			
		||||
@@ -58,10 +60,11 @@ static void nfs_set_events(NFSClient *client)
 | 
			
		||||
{
 | 
			
		||||
    int ev = nfs_which_events(client->context);
 | 
			
		||||
    if (ev != client->events) {
 | 
			
		||||
        qemu_aio_set_fd_handler(nfs_get_fd(client->context),
 | 
			
		||||
                      (ev & POLLIN) ? nfs_process_read : NULL,
 | 
			
		||||
                      (ev & POLLOUT) ? nfs_process_write : NULL,
 | 
			
		||||
                      client);
 | 
			
		||||
        aio_set_fd_handler(client->aio_context,
 | 
			
		||||
                           nfs_get_fd(client->context),
 | 
			
		||||
                           (ev & POLLIN) ? nfs_process_read : NULL,
 | 
			
		||||
                           (ev & POLLOUT) ? nfs_process_write : NULL,
 | 
			
		||||
                           client);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    client->events = ev;
 | 
			
		||||
@@ -84,7 +87,8 @@ static void nfs_process_write(void *arg)
 | 
			
		||||
static void nfs_co_init_task(NFSClient *client, NFSRPC *task)
 | 
			
		||||
{
 | 
			
		||||
    *task = (NFSRPC) {
 | 
			
		||||
        .co         = qemu_coroutine_self(),
 | 
			
		||||
        .co             = qemu_coroutine_self(),
 | 
			
		||||
        .client         = client,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -116,7 +120,8 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
 | 
			
		||||
        error_report("NFS Error: %s", nfs_get_error(nfs));
 | 
			
		||||
    }
 | 
			
		||||
    if (task->co) {
 | 
			
		||||
        task->bh = qemu_bh_new(nfs_co_generic_bh_cb, task);
 | 
			
		||||
        task->bh = aio_bh_new(task->client->aio_context,
 | 
			
		||||
                              nfs_co_generic_bh_cb, task);
 | 
			
		||||
        qemu_bh_schedule(task->bh);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -224,13 +229,34 @@ static QemuOptsList runtime_opts = {
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void nfs_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    NFSClient *client = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    aio_set_fd_handler(client->aio_context,
 | 
			
		||||
                       nfs_get_fd(client->context),
 | 
			
		||||
                       NULL, NULL, NULL);
 | 
			
		||||
    client->events = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nfs_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                   AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    NFSClient *client = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    client->aio_context = new_context;
 | 
			
		||||
    nfs_set_events(client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nfs_client_close(NFSClient *client)
 | 
			
		||||
{
 | 
			
		||||
    if (client->context) {
 | 
			
		||||
        if (client->fh) {
 | 
			
		||||
            nfs_close(client->context, client->fh);
 | 
			
		||||
        }
 | 
			
		||||
        qemu_aio_set_fd_handler(nfs_get_fd(client->context), NULL, NULL, NULL);
 | 
			
		||||
        aio_set_fd_handler(client->aio_context,
 | 
			
		||||
                           nfs_get_fd(client->context),
 | 
			
		||||
                           NULL, NULL, NULL);
 | 
			
		||||
        nfs_destroy_context(client->context);
 | 
			
		||||
    }
 | 
			
		||||
    memset(client, 0, sizeof(NFSClient));
 | 
			
		||||
@@ -345,6 +371,8 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    QemuOpts *opts;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
 | 
			
		||||
    client->aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
 | 
			
		||||
    qemu_opts_absorb_qdict(opts, options, &local_err);
 | 
			
		||||
    if (local_err) {
 | 
			
		||||
@@ -368,6 +396,8 @@ static int nfs_file_create(const char *url, QEMUOptionParameter *options,
 | 
			
		||||
    int64_t total_size = 0;
 | 
			
		||||
    NFSClient *client = g_malloc0(sizeof(NFSClient));
 | 
			
		||||
 | 
			
		||||
    client->aio_context = qemu_get_aio_context();
 | 
			
		||||
 | 
			
		||||
    /* Read out options */
 | 
			
		||||
    while (options && options->name) {
 | 
			
		||||
        if (!strcmp(options->name, "size")) {
 | 
			
		||||
@@ -407,7 +437,7 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
 | 
			
		||||
 | 
			
		||||
    while (!task.complete) {
 | 
			
		||||
        nfs_set_events(client);
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(client->aio_context, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (task.ret < 0 ? task.ret : st.st_blocks * st.st_blksize);
 | 
			
		||||
@@ -420,22 +450,25 @@ static int nfs_file_truncate(BlockDriverState *bs, int64_t offset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_nfs = {
 | 
			
		||||
    .format_name     = "nfs",
 | 
			
		||||
    .protocol_name   = "nfs",
 | 
			
		||||
    .format_name                    = "nfs",
 | 
			
		||||
    .protocol_name                  = "nfs",
 | 
			
		||||
 | 
			
		||||
    .instance_size   = sizeof(NFSClient),
 | 
			
		||||
    .bdrv_needs_filename = true,
 | 
			
		||||
    .bdrv_has_zero_init = nfs_has_zero_init,
 | 
			
		||||
    .bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
 | 
			
		||||
    .bdrv_truncate = nfs_file_truncate,
 | 
			
		||||
    .instance_size                  = sizeof(NFSClient),
 | 
			
		||||
    .bdrv_needs_filename            = true,
 | 
			
		||||
    .bdrv_has_zero_init             = nfs_has_zero_init,
 | 
			
		||||
    .bdrv_get_allocated_file_size   = nfs_get_allocated_file_size,
 | 
			
		||||
    .bdrv_truncate                  = nfs_file_truncate,
 | 
			
		||||
 | 
			
		||||
    .bdrv_file_open  = nfs_file_open,
 | 
			
		||||
    .bdrv_close      = nfs_file_close,
 | 
			
		||||
    .bdrv_create     = nfs_file_create,
 | 
			
		||||
    .bdrv_file_open                 = nfs_file_open,
 | 
			
		||||
    .bdrv_close                     = nfs_file_close,
 | 
			
		||||
    .bdrv_create                    = nfs_file_create,
 | 
			
		||||
 | 
			
		||||
    .bdrv_co_readv         = nfs_co_readv,
 | 
			
		||||
    .bdrv_co_writev        = nfs_co_writev,
 | 
			
		||||
    .bdrv_co_flush_to_disk = nfs_co_flush,
 | 
			
		||||
    .bdrv_co_readv                  = nfs_co_readv,
 | 
			
		||||
    .bdrv_co_writev                 = nfs_co_writev,
 | 
			
		||||
    .bdrv_co_flush_to_disk          = nfs_co_flush,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context        = nfs_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context        = nfs_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void nfs_block_init(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -173,7 +173,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
 | 
			
		||||
    qed_read_table(s, s->header.l1_table_offset,
 | 
			
		||||
                   s->l1_table, qed_sync_cb, &ret);
 | 
			
		||||
    while (ret == -EINPROGRESS) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(bdrv_get_aio_context(s->bs), true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
@@ -194,7 +194,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
 | 
			
		||||
 | 
			
		||||
    qed_write_l1_table(s, index, n, qed_sync_cb, &ret);
 | 
			
		||||
    while (ret == -EINPROGRESS) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(bdrv_get_aio_context(s->bs), true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
@@ -267,7 +267,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
 | 
			
		||||
 | 
			
		||||
    qed_read_l2_table(s, request, offset, qed_sync_cb, &ret);
 | 
			
		||||
    while (ret == -EINPROGRESS) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(bdrv_get_aio_context(s->bs), true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
@@ -289,7 +289,7 @@ int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
 | 
			
		||||
 | 
			
		||||
    qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret);
 | 
			
		||||
    while (ret == -EINPROGRESS) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(bdrv_get_aio_context(s->bs), true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								block/qed.c
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								block/qed.c
									
									
									
									
									
								
							@@ -21,12 +21,13 @@
 | 
			
		||||
static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
			
		||||
{
 | 
			
		||||
    QEDAIOCB *acb = (QEDAIOCB *)blockacb;
 | 
			
		||||
    AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
 | 
			
		||||
    bool finished = false;
 | 
			
		||||
 | 
			
		||||
    /* Wait for the request to finish */
 | 
			
		||||
    acb->finished = &finished;
 | 
			
		||||
    while (!finished) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(aio_context, true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -373,6 +374,27 @@ static void bdrv_qed_rebind(BlockDriverState *bs)
 | 
			
		||||
    s->bs = bs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bdrv_qed_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVQEDState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    qed_cancel_need_check_timer(s);
 | 
			
		||||
    timer_free(s->need_check_timer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                        AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    BDRVQEDState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    s->need_check_timer = aio_timer_new(new_context,
 | 
			
		||||
                                        QEMU_CLOCK_VIRTUAL, SCALE_NS,
 | 
			
		||||
                                        qed_need_check_timer_cb, s);
 | 
			
		||||
    if (s->header.features & QED_F_NEED_CHECK) {
 | 
			
		||||
        qed_start_need_check_timer(s);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
                         Error **errp)
 | 
			
		||||
{
 | 
			
		||||
@@ -496,8 +518,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->need_check_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
 | 
			
		||||
                                            qed_need_check_timer_cb, s);
 | 
			
		||||
    bdrv_qed_attach_aio_context(bs, bdrv_get_aio_context(bs));
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
    if (ret) {
 | 
			
		||||
@@ -528,8 +549,7 @@ static void bdrv_qed_close(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVQEDState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    qed_cancel_need_check_timer(s);
 | 
			
		||||
    timer_free(s->need_check_timer);
 | 
			
		||||
    bdrv_qed_detach_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    /* Ensure writes reach stable storage */
 | 
			
		||||
    bdrv_flush(bs->file);
 | 
			
		||||
@@ -919,7 +939,8 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
 | 
			
		||||
 | 
			
		||||
    /* Arrange for a bh to invoke the completion function */
 | 
			
		||||
    acb->bh_ret = ret;
 | 
			
		||||
    acb->bh = qemu_bh_new(qed_aio_complete_bh, acb);
 | 
			
		||||
    acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
 | 
			
		||||
                         qed_aio_complete_bh, acb);
 | 
			
		||||
    qemu_bh_schedule(acb->bh);
 | 
			
		||||
 | 
			
		||||
    /* Start next allocating write request waiting behind this one.  Note that
 | 
			
		||||
@@ -1644,6 +1665,8 @@ static BlockDriver bdrv_qed = {
 | 
			
		||||
    .bdrv_change_backing_file = bdrv_qed_change_backing_file,
 | 
			
		||||
    .bdrv_invalidate_cache    = bdrv_qed_invalidate_cache,
 | 
			
		||||
    .bdrv_check               = bdrv_qed_check,
 | 
			
		||||
    .bdrv_detach_aio_context  = bdrv_qed_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context  = bdrv_qed_attach_aio_context,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void bdrv_qed_init(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -848,25 +848,49 @@ static void quorum_close(BlockDriverState *bs)
 | 
			
		||||
    g_free(s->bs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void quorum_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVQuorumState *s = bs->opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_children; i++) {
 | 
			
		||||
        bdrv_detach_aio_context(s->bs[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void quorum_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                      AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    BDRVQuorumState *s = bs->opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_children; i++) {
 | 
			
		||||
        bdrv_attach_aio_context(s->bs[i], new_context);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BlockDriver bdrv_quorum = {
 | 
			
		||||
    .format_name        = "quorum",
 | 
			
		||||
    .protocol_name      = "quorum",
 | 
			
		||||
    .format_name                        = "quorum",
 | 
			
		||||
    .protocol_name                      = "quorum",
 | 
			
		||||
 | 
			
		||||
    .instance_size      = sizeof(BDRVQuorumState),
 | 
			
		||||
    .instance_size                      = sizeof(BDRVQuorumState),
 | 
			
		||||
 | 
			
		||||
    .bdrv_file_open     = quorum_open,
 | 
			
		||||
    .bdrv_close         = quorum_close,
 | 
			
		||||
    .bdrv_file_open                     = quorum_open,
 | 
			
		||||
    .bdrv_close                         = quorum_close,
 | 
			
		||||
 | 
			
		||||
    .bdrv_co_flush_to_disk = quorum_co_flush,
 | 
			
		||||
    .bdrv_co_flush_to_disk              = quorum_co_flush,
 | 
			
		||||
 | 
			
		||||
    .bdrv_getlength     = quorum_getlength,
 | 
			
		||||
    .bdrv_getlength                     = quorum_getlength,
 | 
			
		||||
 | 
			
		||||
    .bdrv_aio_readv     = quorum_aio_readv,
 | 
			
		||||
    .bdrv_aio_writev    = quorum_aio_writev,
 | 
			
		||||
    .bdrv_invalidate_cache = quorum_invalidate_cache,
 | 
			
		||||
    .bdrv_aio_readv                     = quorum_aio_readv,
 | 
			
		||||
    .bdrv_aio_writev                    = quorum_aio_writev,
 | 
			
		||||
    .bdrv_invalidate_cache              = quorum_invalidate_cache,
 | 
			
		||||
 | 
			
		||||
    .is_filter           = true,
 | 
			
		||||
    .bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
 | 
			
		||||
    .bdrv_detach_aio_context            = quorum_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context            = quorum_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    .is_filter                          = true,
 | 
			
		||||
    .bdrv_recurse_is_first_non_filter   = quorum_recurse_is_first_non_filter,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void bdrv_quorum_init(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -34,19 +34,27 @@
 | 
			
		||||
/* linux-aio.c - Linux native implementation */
 | 
			
		||||
#ifdef CONFIG_LINUX_AIO
 | 
			
		||||
void *laio_init(void);
 | 
			
		||||
void laio_cleanup(void *s);
 | 
			
		||||
BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
 | 
			
		||||
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
 | 
			
		||||
        BlockDriverCompletionFunc *cb, void *opaque, int type);
 | 
			
		||||
void laio_detach_aio_context(void *s, AioContext *old_context);
 | 
			
		||||
void laio_attach_aio_context(void *s, AioContext *new_context);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
typedef struct QEMUWin32AIOState QEMUWin32AIOState;
 | 
			
		||||
QEMUWin32AIOState *win32_aio_init(void);
 | 
			
		||||
void win32_aio_cleanup(QEMUWin32AIOState *aio);
 | 
			
		||||
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
 | 
			
		||||
BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
 | 
			
		||||
        QEMUWin32AIOState *aio, HANDLE hfile,
 | 
			
		||||
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
 | 
			
		||||
        BlockDriverCompletionFunc *cb, void *opaque, int type);
 | 
			
		||||
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
 | 
			
		||||
                                  AioContext *old_context);
 | 
			
		||||
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
 | 
			
		||||
                                  AioContext *new_context);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* QEMU_RAW_AIO_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -307,6 +307,29 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void raw_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
#ifdef CONFIG_LINUX_AIO
 | 
			
		||||
    BDRVRawState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    if (s->use_aio) {
 | 
			
		||||
        laio_detach_aio_context(s->aio_ctx, bdrv_get_aio_context(bs));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void raw_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                   AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
#ifdef CONFIG_LINUX_AIO
 | 
			
		||||
    BDRVRawState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    if (s->use_aio) {
 | 
			
		||||
        laio_attach_aio_context(s->aio_ctx, new_context);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_LINUX_AIO
 | 
			
		||||
static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags)
 | 
			
		||||
{
 | 
			
		||||
@@ -447,6 +470,8 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    raw_attach_aio_context(bs, bdrv_get_aio_context(bs));
 | 
			
		||||
 | 
			
		||||
    ret = 0;
 | 
			
		||||
fail:
 | 
			
		||||
    if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
 | 
			
		||||
@@ -1059,6 +1084,14 @@ static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
 | 
			
		||||
static void raw_close(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVRawState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    raw_detach_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_LINUX_AIO
 | 
			
		||||
    if (s->use_aio) {
 | 
			
		||||
        laio_cleanup(s->aio_ctx);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    if (s->fd >= 0) {
 | 
			
		||||
        qemu_close(s->fd);
 | 
			
		||||
        s->fd = -1;
 | 
			
		||||
@@ -1478,6 +1511,9 @@ static BlockDriver bdrv_file = {
 | 
			
		||||
    .bdrv_get_allocated_file_size
 | 
			
		||||
                        = raw_get_allocated_file_size,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = raw_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = raw_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    .create_options = raw_create_options,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -1878,6 +1914,9 @@ static BlockDriver bdrv_host_device = {
 | 
			
		||||
    .bdrv_get_allocated_file_size
 | 
			
		||||
                        = raw_get_allocated_file_size,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = raw_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = raw_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    /* generic scsi device */
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
    .bdrv_ioctl         = hdev_ioctl,
 | 
			
		||||
@@ -2020,6 +2059,9 @@ static BlockDriver bdrv_host_floppy = {
 | 
			
		||||
    .bdrv_get_allocated_file_size
 | 
			
		||||
                        = raw_get_allocated_file_size,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = raw_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = raw_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    /* removable device support */
 | 
			
		||||
    .bdrv_is_inserted   = floppy_is_inserted,
 | 
			
		||||
    .bdrv_media_changed = floppy_media_changed,
 | 
			
		||||
@@ -2145,6 +2187,9 @@ static BlockDriver bdrv_host_cdrom = {
 | 
			
		||||
    .bdrv_get_allocated_file_size
 | 
			
		||||
                        = raw_get_allocated_file_size,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = raw_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = raw_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    /* removable device support */
 | 
			
		||||
    .bdrv_is_inserted   = cdrom_is_inserted,
 | 
			
		||||
    .bdrv_eject         = cdrom_eject,
 | 
			
		||||
@@ -2276,6 +2321,9 @@ static BlockDriver bdrv_host_cdrom = {
 | 
			
		||||
    .bdrv_get_allocated_file_size
 | 
			
		||||
                        = raw_get_allocated_file_size,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = raw_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = raw_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    /* removable device support */
 | 
			
		||||
    .bdrv_is_inserted   = cdrom_is_inserted,
 | 
			
		||||
    .bdrv_eject         = cdrom_eject,
 | 
			
		||||
@@ -2283,40 +2331,6 @@ static BlockDriver bdrv_host_cdrom = {
 | 
			
		||||
};
 | 
			
		||||
#endif /* __FreeBSD__ */
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_LINUX_AIO
 | 
			
		||||
/**
 | 
			
		||||
 * Return the file descriptor for Linux AIO
 | 
			
		||||
 *
 | 
			
		||||
 * This function is a layering violation and should be removed when it becomes
 | 
			
		||||
 * possible to call the block layer outside the global mutex.  It allows the
 | 
			
		||||
 * caller to hijack the file descriptor so I/O can be performed outside the
 | 
			
		||||
 * block layer.
 | 
			
		||||
 */
 | 
			
		||||
int raw_get_aio_fd(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVRawState *s;
 | 
			
		||||
 | 
			
		||||
    if (!bs->drv) {
 | 
			
		||||
        return -ENOMEDIUM;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (bs->drv == bdrv_find_format("raw")) {
 | 
			
		||||
        bs = bs->file;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* raw-posix has several protocols so just check for raw_aio_readv */
 | 
			
		||||
    if (bs->drv->bdrv_aio_readv != raw_aio_readv) {
 | 
			
		||||
        return -ENOTSUP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s = bs->opaque;
 | 
			
		||||
    if (!s->use_aio) {
 | 
			
		||||
        return -ENOTSUP;
 | 
			
		||||
    }
 | 
			
		||||
    return s->fd;
 | 
			
		||||
}
 | 
			
		||||
#endif /* CONFIG_LINUX_AIO */
 | 
			
		||||
 | 
			
		||||
static void bdrv_file_init(void)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
 
 | 
			
		||||
@@ -36,8 +36,6 @@
 | 
			
		||||
#define FTYPE_CD     1
 | 
			
		||||
#define FTYPE_HARDDISK 2
 | 
			
		||||
 | 
			
		||||
static QEMUWin32AIOState *aio;
 | 
			
		||||
 | 
			
		||||
typedef struct RawWin32AIOData {
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
    HANDLE hfile;
 | 
			
		||||
@@ -202,6 +200,25 @@ static int set_sparse(int fd)
 | 
			
		||||
				 NULL, 0, NULL, 0, &returned, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void raw_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVRawState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    if (s->aio) {
 | 
			
		||||
        win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void raw_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                   AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    BDRVRawState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    if (s->aio) {
 | 
			
		||||
        win32_aio_attach_aio_context(s->aio, new_context);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void raw_probe_alignment(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVRawState *s = bs->opaque;
 | 
			
		||||
@@ -300,15 +317,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
 | 
			
		||||
    raw_parse_flags(flags, &access_flags, &overlapped);
 | 
			
		||||
 | 
			
		||||
    if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
 | 
			
		||||
        aio = win32_aio_init();
 | 
			
		||||
        if (aio == NULL) {
 | 
			
		||||
            error_setg(errp, "Could not initialize AIO");
 | 
			
		||||
            ret = -EINVAL;
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (filename[0] && filename[1] == ':') {
 | 
			
		||||
        snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]);
 | 
			
		||||
    } else if (filename[0] == '\\' && filename[1] == '\\') {
 | 
			
		||||
@@ -335,13 +343,23 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (flags & BDRV_O_NATIVE_AIO) {
 | 
			
		||||
        ret = win32_aio_attach(aio, s->hfile);
 | 
			
		||||
        s->aio = win32_aio_init();
 | 
			
		||||
        if (s->aio == NULL) {
 | 
			
		||||
            CloseHandle(s->hfile);
 | 
			
		||||
            error_setg(errp, "Could not initialize AIO");
 | 
			
		||||
            ret = -EINVAL;
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = win32_aio_attach(s->aio, s->hfile);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            win32_aio_cleanup(s->aio);
 | 
			
		||||
            CloseHandle(s->hfile);
 | 
			
		||||
            error_setg_errno(errp, -ret, "Could not enable AIO");
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
        s->aio = aio;
 | 
			
		||||
 | 
			
		||||
        win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    raw_probe_alignment(bs);
 | 
			
		||||
@@ -389,6 +407,13 @@ static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
 | 
			
		||||
static void raw_close(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVRawState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    if (s->aio) {
 | 
			
		||||
        win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
 | 
			
		||||
        win32_aio_cleanup(s->aio);
 | 
			
		||||
        s->aio = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CloseHandle(s->hfile);
 | 
			
		||||
    if (bs->open_flags & BDRV_O_TEMPORARY) {
 | 
			
		||||
        unlink(bs->filename);
 | 
			
		||||
@@ -684,6 +709,9 @@ static BlockDriver bdrv_host_device = {
 | 
			
		||||
    .bdrv_aio_writev    = raw_aio_writev,
 | 
			
		||||
    .bdrv_aio_flush     = raw_aio_flush,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = raw_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = raw_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    .bdrv_getlength      = raw_getlength,
 | 
			
		||||
    .has_variable_length = true,
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								block/rbd.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								block/rbd.c
									
									
									
									
									
								
							@@ -555,7 +555,7 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
			
		||||
    acb->cancelled = 1;
 | 
			
		||||
 | 
			
		||||
    while (acb->status == -EINPROGRESS) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(bdrv_get_aio_context(acb->common.bs), true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_aio_release(acb);
 | 
			
		||||
@@ -588,7 +588,8 @@ static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb)
 | 
			
		||||
    rcb->ret = rbd_aio_get_return_value(c);
 | 
			
		||||
    rbd_aio_release(c);
 | 
			
		||||
 | 
			
		||||
    acb->bh = qemu_bh_new(rbd_finish_bh, rcb);
 | 
			
		||||
    acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
 | 
			
		||||
                         rbd_finish_bh, rcb);
 | 
			
		||||
    qemu_bh_schedule(acb->bh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -684,13 +685,16 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        goto failed;
 | 
			
		||||
        goto failed_completion;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return &acb->common;
 | 
			
		||||
 | 
			
		||||
failed_completion:
 | 
			
		||||
    rbd_aio_release(c);
 | 
			
		||||
failed:
 | 
			
		||||
    g_free(rcb);
 | 
			
		||||
    qemu_vfree(acb->bounce);
 | 
			
		||||
    qemu_aio_release(acb);
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										167
									
								
								block/sheepdog.c
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								block/sheepdog.c
									
									
									
									
									
								
							@@ -200,6 +200,8 @@ typedef struct SheepdogInode {
 | 
			
		||||
    uint32_t data_vdi_id[MAX_DATA_OBJS];
 | 
			
		||||
} SheepdogInode;
 | 
			
		||||
 | 
			
		||||
#define SD_INODE_HEADER_SIZE offsetof(SheepdogInode, data_vdi_id)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 64 bit FNV-1a non-zero initial basis
 | 
			
		||||
 */
 | 
			
		||||
@@ -282,6 +284,7 @@ typedef struct AIOReq {
 | 
			
		||||
    unsigned int data_len;
 | 
			
		||||
    uint8_t flags;
 | 
			
		||||
    uint32_t id;
 | 
			
		||||
    bool create;
 | 
			
		||||
 | 
			
		||||
    QLIST_ENTRY(AIOReq) aio_siblings;
 | 
			
		||||
} AIOReq;
 | 
			
		||||
@@ -314,6 +317,7 @@ struct SheepdogAIOCB {
 | 
			
		||||
 | 
			
		||||
typedef struct BDRVSheepdogState {
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
    AioContext *aio_context;
 | 
			
		||||
 | 
			
		||||
    SheepdogInode inode;
 | 
			
		||||
 | 
			
		||||
@@ -404,7 +408,7 @@ static const char * sd_strerror(int err)
 | 
			
		||||
 | 
			
		||||
static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
 | 
			
		||||
                                    uint64_t oid, unsigned int data_len,
 | 
			
		||||
                                    uint64_t offset, uint8_t flags,
 | 
			
		||||
                                    uint64_t offset, uint8_t flags, bool create,
 | 
			
		||||
                                    uint64_t base_oid, unsigned int iov_offset)
 | 
			
		||||
{
 | 
			
		||||
    AIOReq *aio_req;
 | 
			
		||||
@@ -418,6 +422,7 @@ static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
 | 
			
		||||
    aio_req->data_len = data_len;
 | 
			
		||||
    aio_req->flags = flags;
 | 
			
		||||
    aio_req->id = s->aioreq_seq_num++;
 | 
			
		||||
    aio_req->create = create;
 | 
			
		||||
 | 
			
		||||
    acb->nr_pending++;
 | 
			
		||||
    return aio_req;
 | 
			
		||||
@@ -496,7 +501,7 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
			
		||||
            sd_finish_aiocb(acb);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(s->aio_context, true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -578,6 +583,7 @@ static void restart_co_req(void *opaque)
 | 
			
		||||
 | 
			
		||||
typedef struct SheepdogReqCo {
 | 
			
		||||
    int sockfd;
 | 
			
		||||
    AioContext *aio_context;
 | 
			
		||||
    SheepdogReq *hdr;
 | 
			
		||||
    void *data;
 | 
			
		||||
    unsigned int *wlen;
 | 
			
		||||
@@ -598,14 +604,14 @@ static coroutine_fn void do_co_req(void *opaque)
 | 
			
		||||
    unsigned int *rlen = srco->rlen;
 | 
			
		||||
 | 
			
		||||
    co = qemu_coroutine_self();
 | 
			
		||||
    qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, co);
 | 
			
		||||
    aio_set_fd_handler(srco->aio_context, sockfd, NULL, restart_co_req, co);
 | 
			
		||||
 | 
			
		||||
    ret = send_co_req(sockfd, hdr, data, wlen);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_aio_set_fd_handler(sockfd, restart_co_req, NULL, co);
 | 
			
		||||
    aio_set_fd_handler(srco->aio_context, sockfd, restart_co_req, NULL, co);
 | 
			
		||||
 | 
			
		||||
    ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
 | 
			
		||||
    if (ret != sizeof(*hdr)) {
 | 
			
		||||
@@ -630,18 +636,19 @@ static coroutine_fn void do_co_req(void *opaque)
 | 
			
		||||
out:
 | 
			
		||||
    /* there is at most one request for this sockfd, so it is safe to
 | 
			
		||||
     * set each handler to NULL. */
 | 
			
		||||
    qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL);
 | 
			
		||||
    aio_set_fd_handler(srco->aio_context, sockfd, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    srco->ret = ret;
 | 
			
		||||
    srco->finished = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_req(int sockfd, SheepdogReq *hdr, void *data,
 | 
			
		||||
                  unsigned int *wlen, unsigned int *rlen)
 | 
			
		||||
static int do_req(int sockfd, AioContext *aio_context, SheepdogReq *hdr,
 | 
			
		||||
                  void *data, unsigned int *wlen, unsigned int *rlen)
 | 
			
		||||
{
 | 
			
		||||
    Coroutine *co;
 | 
			
		||||
    SheepdogReqCo srco = {
 | 
			
		||||
        .sockfd = sockfd,
 | 
			
		||||
        .aio_context = aio_context,
 | 
			
		||||
        .hdr = hdr,
 | 
			
		||||
        .data = data,
 | 
			
		||||
        .wlen = wlen,
 | 
			
		||||
@@ -656,7 +663,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
 | 
			
		||||
        co = qemu_coroutine_create(do_co_req);
 | 
			
		||||
        qemu_coroutine_enter(co, &srco);
 | 
			
		||||
        while (!srco.finished) {
 | 
			
		||||
            qemu_aio_wait();
 | 
			
		||||
            aio_poll(aio_context, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -664,8 +671,8 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
 | 
			
		||||
                           struct iovec *iov, int niov, bool create,
 | 
			
		||||
                           enum AIOCBState aiocb_type);
 | 
			
		||||
                                         struct iovec *iov, int niov,
 | 
			
		||||
                                         enum AIOCBState aiocb_type);
 | 
			
		||||
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req);
 | 
			
		||||
static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag);
 | 
			
		||||
static int get_sheep_fd(BDRVSheepdogState *s, Error **errp);
 | 
			
		||||
@@ -698,7 +705,7 @@ static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid)
 | 
			
		||||
        /* move aio_req from pending list to inflight one */
 | 
			
		||||
        QLIST_REMOVE(aio_req, aio_siblings);
 | 
			
		||||
        QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
 | 
			
		||||
        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, false,
 | 
			
		||||
        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
 | 
			
		||||
                        acb->aiocb_type);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -709,7 +716,7 @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
 | 
			
		||||
    BDRVSheepdogState *s = opaque;
 | 
			
		||||
    AIOReq *aio_req, *next;
 | 
			
		||||
 | 
			
		||||
    qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
 | 
			
		||||
    aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
 | 
			
		||||
    close(s->fd);
 | 
			
		||||
    s->fd = -1;
 | 
			
		||||
 | 
			
		||||
@@ -797,7 +804,7 @@ static void coroutine_fn aio_read_response(void *opaque)
 | 
			
		||||
        }
 | 
			
		||||
        idx = data_oid_to_idx(aio_req->oid);
 | 
			
		||||
 | 
			
		||||
        if (s->inode.data_vdi_id[idx] != s->inode.vdi_id) {
 | 
			
		||||
        if (aio_req->create) {
 | 
			
		||||
            /*
 | 
			
		||||
             * If the object is newly created one, we need to update
 | 
			
		||||
             * the vdi object (metadata object).  min_dirty_data_idx
 | 
			
		||||
@@ -922,7 +929,7 @@ static int get_sheep_fd(BDRVSheepdogState *s, Error **errp)
 | 
			
		||||
        return fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_aio_set_fd_handler(fd, co_read_response, NULL, s);
 | 
			
		||||
    aio_set_fd_handler(s->aio_context, fd, co_read_response, NULL, s);
 | 
			
		||||
    return fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1092,7 +1099,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
 | 
			
		||||
    hdr.snapid = snapid;
 | 
			
		||||
    hdr.flags = SD_FLAG_CMD_WRITE;
 | 
			
		||||
 | 
			
		||||
    ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
 | 
			
		||||
    ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        error_setg_errno(errp, -ret, "cannot get vdi info");
 | 
			
		||||
        goto out;
 | 
			
		||||
@@ -1117,8 +1124,8 @@ out:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
 | 
			
		||||
                           struct iovec *iov, int niov, bool create,
 | 
			
		||||
                           enum AIOCBState aiocb_type)
 | 
			
		||||
                                         struct iovec *iov, int niov,
 | 
			
		||||
                                         enum AIOCBState aiocb_type)
 | 
			
		||||
{
 | 
			
		||||
    int nr_copies = s->inode.nr_copies;
 | 
			
		||||
    SheepdogObjReq hdr;
 | 
			
		||||
@@ -1129,6 +1136,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
 | 
			
		||||
    uint64_t offset = aio_req->offset;
 | 
			
		||||
    uint8_t flags = aio_req->flags;
 | 
			
		||||
    uint64_t old_oid = aio_req->base_oid;
 | 
			
		||||
    bool create = aio_req->create;
 | 
			
		||||
 | 
			
		||||
    if (!nr_copies) {
 | 
			
		||||
        error_report("bug");
 | 
			
		||||
@@ -1173,7 +1181,8 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
 | 
			
		||||
 | 
			
		||||
    qemu_co_mutex_lock(&s->lock);
 | 
			
		||||
    s->co_send = qemu_coroutine_self();
 | 
			
		||||
    qemu_aio_set_fd_handler(s->fd, co_read_response, co_write_request, s);
 | 
			
		||||
    aio_set_fd_handler(s->aio_context, s->fd,
 | 
			
		||||
                       co_read_response, co_write_request, s);
 | 
			
		||||
    socket_set_cork(s->fd, 1);
 | 
			
		||||
 | 
			
		||||
    /* send a header */
 | 
			
		||||
@@ -1191,12 +1200,13 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
 | 
			
		||||
    }
 | 
			
		||||
out:
 | 
			
		||||
    socket_set_cork(s->fd, 0);
 | 
			
		||||
    qemu_aio_set_fd_handler(s->fd, co_read_response, NULL, s);
 | 
			
		||||
    aio_set_fd_handler(s->aio_context, s->fd, co_read_response, NULL, s);
 | 
			
		||||
    s->co_send = NULL;
 | 
			
		||||
    qemu_co_mutex_unlock(&s->lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
 | 
			
		||||
static int read_write_object(int fd, AioContext *aio_context, char *buf,
 | 
			
		||||
                             uint64_t oid, uint8_t copies,
 | 
			
		||||
                             unsigned int datalen, uint64_t offset,
 | 
			
		||||
                             bool write, bool create, uint32_t cache_flags)
 | 
			
		||||
{
 | 
			
		||||
@@ -1229,7 +1239,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
 | 
			
		||||
    hdr.offset = offset;
 | 
			
		||||
    hdr.copies = copies;
 | 
			
		||||
 | 
			
		||||
    ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
 | 
			
		||||
    ret = do_req(fd, aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        error_report("failed to send a request to the sheep");
 | 
			
		||||
        return ret;
 | 
			
		||||
@@ -1244,19 +1254,23 @@ static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int read_object(int fd, char *buf, uint64_t oid, uint8_t copies,
 | 
			
		||||
static int read_object(int fd, AioContext *aio_context, char *buf,
 | 
			
		||||
                       uint64_t oid, uint8_t copies,
 | 
			
		||||
                       unsigned int datalen, uint64_t offset,
 | 
			
		||||
                       uint32_t cache_flags)
 | 
			
		||||
{
 | 
			
		||||
    return read_write_object(fd, buf, oid, copies, datalen, offset, false,
 | 
			
		||||
    return read_write_object(fd, aio_context, buf, oid, copies,
 | 
			
		||||
                             datalen, offset, false,
 | 
			
		||||
                             false, cache_flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
 | 
			
		||||
static int write_object(int fd, AioContext *aio_context, char *buf,
 | 
			
		||||
                        uint64_t oid, uint8_t copies,
 | 
			
		||||
                        unsigned int datalen, uint64_t offset, bool create,
 | 
			
		||||
                        uint32_t cache_flags)
 | 
			
		||||
{
 | 
			
		||||
    return read_write_object(fd, buf, oid, copies, datalen, offset, true,
 | 
			
		||||
    return read_write_object(fd, aio_context, buf, oid, copies,
 | 
			
		||||
                             datalen, offset, true,
 | 
			
		||||
                             create, cache_flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1275,7 +1289,7 @@ static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag)
 | 
			
		||||
        return -EIO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inode = g_malloc(sizeof(s->inode));
 | 
			
		||||
    inode = g_malloc(SD_INODE_HEADER_SIZE);
 | 
			
		||||
 | 
			
		||||
    ret = find_vdi_name(s, s->name, snapid, tag, &vid, false, &local_err);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
@@ -1284,14 +1298,15 @@ static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag)
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = read_object(fd, (char *)inode, vid_to_vdi_oid(vid),
 | 
			
		||||
                      s->inode.nr_copies, sizeof(*inode), 0, s->cache_flags);
 | 
			
		||||
    ret = read_object(fd, s->aio_context, (char *)inode, vid_to_vdi_oid(vid),
 | 
			
		||||
                      s->inode.nr_copies, SD_INODE_HEADER_SIZE, 0,
 | 
			
		||||
                      s->cache_flags);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (inode->vdi_id != s->inode.vdi_id) {
 | 
			
		||||
        memcpy(&s->inode, inode, sizeof(s->inode));
 | 
			
		||||
        memcpy(&s->inode, inode, SD_INODE_HEADER_SIZE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
@@ -1315,6 +1330,7 @@ static bool check_simultaneous_create(BDRVSheepdogState *s, AIOReq *aio_req)
 | 
			
		||||
            DPRINTF("simultaneous create to %" PRIx64 "\n", aio_req->oid);
 | 
			
		||||
            aio_req->flags = 0;
 | 
			
		||||
            aio_req->base_oid = 0;
 | 
			
		||||
            aio_req->create = false;
 | 
			
		||||
            QLIST_REMOVE(aio_req, aio_siblings);
 | 
			
		||||
            QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req, aio_siblings);
 | 
			
		||||
            return true;
 | 
			
		||||
@@ -1327,7 +1343,8 @@ static bool check_simultaneous_create(BDRVSheepdogState *s, AIOReq *aio_req)
 | 
			
		||||
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
 | 
			
		||||
{
 | 
			
		||||
    SheepdogAIOCB *acb = aio_req->aiocb;
 | 
			
		||||
    bool create = false;
 | 
			
		||||
 | 
			
		||||
    aio_req->create = false;
 | 
			
		||||
 | 
			
		||||
    /* check whether this request becomes a CoW one */
 | 
			
		||||
    if (acb->aiocb_type == AIOCB_WRITE_UDATA && is_data_obj(aio_req->oid)) {
 | 
			
		||||
@@ -1345,20 +1362,36 @@ static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
 | 
			
		||||
            aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);
 | 
			
		||||
            aio_req->flags |= SD_FLAG_CMD_COW;
 | 
			
		||||
        }
 | 
			
		||||
        create = true;
 | 
			
		||||
        aio_req->create = true;
 | 
			
		||||
    }
 | 
			
		||||
out:
 | 
			
		||||
    if (is_data_obj(aio_req->oid)) {
 | 
			
		||||
        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,
 | 
			
		||||
        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
 | 
			
		||||
                        acb->aiocb_type);
 | 
			
		||||
    } else {
 | 
			
		||||
        struct iovec iov;
 | 
			
		||||
        iov.iov_base = &s->inode;
 | 
			
		||||
        iov.iov_len = sizeof(s->inode);
 | 
			
		||||
        add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
 | 
			
		||||
        add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sd_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVSheepdogState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sd_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                  AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    BDRVSheepdogState *s = bs->opaque;
 | 
			
		||||
 | 
			
		||||
    s->aio_context = new_context;
 | 
			
		||||
    aio_set_fd_handler(new_context, s->fd, co_read_response, NULL, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* TODO Convert to fine grained options */
 | 
			
		||||
static QemuOptsList runtime_opts = {
 | 
			
		||||
    .name = "sheepdog",
 | 
			
		||||
@@ -1387,6 +1420,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    const char *filename;
 | 
			
		||||
 | 
			
		||||
    s->bs = bs;
 | 
			
		||||
    s->aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
 | 
			
		||||
    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
 | 
			
		||||
    qemu_opts_absorb_qdict(opts, options, &local_err);
 | 
			
		||||
@@ -1448,8 +1482,8 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buf = g_malloc(SD_INODE_SIZE);
 | 
			
		||||
    ret = read_object(fd, buf, vid_to_vdi_oid(vid), 0, SD_INODE_SIZE, 0,
 | 
			
		||||
                      s->cache_flags);
 | 
			
		||||
    ret = read_object(fd, s->aio_context, buf, vid_to_vdi_oid(vid),
 | 
			
		||||
                      0, SD_INODE_SIZE, 0, s->cache_flags);
 | 
			
		||||
 | 
			
		||||
    closesocket(fd);
 | 
			
		||||
 | 
			
		||||
@@ -1469,7 +1503,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
 | 
			
		||||
    g_free(buf);
 | 
			
		||||
    return 0;
 | 
			
		||||
out:
 | 
			
		||||
    qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
 | 
			
		||||
    aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL);
 | 
			
		||||
    if (s->fd >= 0) {
 | 
			
		||||
        closesocket(s->fd);
 | 
			
		||||
    }
 | 
			
		||||
@@ -1512,7 +1546,7 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot,
 | 
			
		||||
    hdr.copy_policy = s->inode.copy_policy;
 | 
			
		||||
    hdr.copies = s->inode.nr_copies;
 | 
			
		||||
 | 
			
		||||
    ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
 | 
			
		||||
    ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
 | 
			
		||||
 | 
			
		||||
    closesocket(fd);
 | 
			
		||||
 | 
			
		||||
@@ -1766,7 +1800,8 @@ static void sd_close(BlockDriverState *bs)
 | 
			
		||||
    hdr.data_length = wlen;
 | 
			
		||||
    hdr.flags = SD_FLAG_CMD_WRITE;
 | 
			
		||||
 | 
			
		||||
    ret = do_req(fd, (SheepdogReq *)&hdr, s->name, &wlen, &rlen);
 | 
			
		||||
    ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr,
 | 
			
		||||
                 s->name, &wlen, &rlen);
 | 
			
		||||
 | 
			
		||||
    closesocket(fd);
 | 
			
		||||
 | 
			
		||||
@@ -1775,7 +1810,7 @@ static void sd_close(BlockDriverState *bs)
 | 
			
		||||
        error_report("%s, %s", sd_strerror(rsp->result), s->name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
 | 
			
		||||
    aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL);
 | 
			
		||||
    closesocket(s->fd);
 | 
			
		||||
    g_free(s->host_spec);
 | 
			
		||||
}
 | 
			
		||||
@@ -1812,8 +1847,9 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
 | 
			
		||||
    /* we don't need to update entire object */
 | 
			
		||||
    datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
 | 
			
		||||
    s->inode.vdi_size = offset;
 | 
			
		||||
    ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
 | 
			
		||||
                       s->inode.nr_copies, datalen, 0, false, s->cache_flags);
 | 
			
		||||
    ret = write_object(fd, s->aio_context, (char *)&s->inode,
 | 
			
		||||
                       vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies,
 | 
			
		||||
                       datalen, 0, false, s->cache_flags);
 | 
			
		||||
    close(fd);
 | 
			
		||||
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
@@ -1849,9 +1885,9 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
 | 
			
		||||
        iov.iov_base = &s->inode;
 | 
			
		||||
        iov.iov_len = sizeof(s->inode);
 | 
			
		||||
        aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
 | 
			
		||||
                                data_len, offset, 0, 0, offset);
 | 
			
		||||
                                data_len, offset, 0, false, 0, offset);
 | 
			
		||||
        QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
 | 
			
		||||
        add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
 | 
			
		||||
        add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
 | 
			
		||||
 | 
			
		||||
        acb->aio_done_func = sd_finish_aiocb;
 | 
			
		||||
        acb->aiocb_type = AIOCB_WRITE_UDATA;
 | 
			
		||||
@@ -1882,7 +1918,8 @@ static bool sd_delete(BDRVSheepdogState *s)
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = do_req(fd, (SheepdogReq *)&hdr, s->name, &wlen, &rlen);
 | 
			
		||||
    ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr,
 | 
			
		||||
                 s->name, &wlen, &rlen);
 | 
			
		||||
    closesocket(fd);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -1939,8 +1976,8 @@ static int sd_create_branch(BDRVSheepdogState *s)
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = read_object(fd, buf, vid_to_vdi_oid(vid), s->inode.nr_copies,
 | 
			
		||||
                      SD_INODE_SIZE, 0, s->cache_flags);
 | 
			
		||||
    ret = read_object(fd, s->aio_context, buf, vid_to_vdi_oid(vid),
 | 
			
		||||
                      s->inode.nr_copies, SD_INODE_SIZE, 0, s->cache_flags);
 | 
			
		||||
 | 
			
		||||
    closesocket(fd);
 | 
			
		||||
 | 
			
		||||
@@ -2049,7 +2086,8 @@ static int coroutine_fn sd_co_rw_vector(void *p)
 | 
			
		||||
            DPRINTF("new oid %" PRIx64 "\n", oid);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, old_oid, done);
 | 
			
		||||
        aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, create,
 | 
			
		||||
                                old_oid, done);
 | 
			
		||||
        QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
 | 
			
		||||
 | 
			
		||||
        if (create) {
 | 
			
		||||
@@ -2058,7 +2096,7 @@ static int coroutine_fn sd_co_rw_vector(void *p)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,
 | 
			
		||||
        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
 | 
			
		||||
                        acb->aiocb_type);
 | 
			
		||||
    done:
 | 
			
		||||
        offset = 0;
 | 
			
		||||
@@ -2138,9 +2176,9 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
 | 
			
		||||
    acb->aio_done_func = sd_finish_aiocb;
 | 
			
		||||
 | 
			
		||||
    aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
 | 
			
		||||
                            0, 0, 0, 0, 0);
 | 
			
		||||
                            0, 0, 0, false, 0, 0);
 | 
			
		||||
    QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
 | 
			
		||||
    add_aio_request(s, aio_req, NULL, 0, false, acb->aiocb_type);
 | 
			
		||||
    add_aio_request(s, aio_req, NULL, 0, acb->aiocb_type);
 | 
			
		||||
 | 
			
		||||
    qemu_coroutine_yield();
 | 
			
		||||
    return acb->ret;
 | 
			
		||||
@@ -2187,8 +2225,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
 | 
			
		||||
                       s->inode.nr_copies, datalen, 0, false, s->cache_flags);
 | 
			
		||||
    ret = write_object(fd, s->aio_context, (char *)&s->inode,
 | 
			
		||||
                       vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies,
 | 
			
		||||
                       datalen, 0, false, s->cache_flags);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        error_report("failed to write snapshot's inode.");
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
@@ -2203,8 +2242,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
 | 
			
		||||
                      s->inode.nr_copies, datalen, 0, s->cache_flags);
 | 
			
		||||
    ret = read_object(fd, s->aio_context, (char *)inode,
 | 
			
		||||
                      vid_to_vdi_oid(new_vid), s->inode.nr_copies, datalen, 0,
 | 
			
		||||
                      s->cache_flags);
 | 
			
		||||
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        error_report("failed to read new inode info. %s", strerror(errno));
 | 
			
		||||
@@ -2311,7 +2351,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
 | 
			
		||||
    req.opcode = SD_OP_READ_VDIS;
 | 
			
		||||
    req.data_length = max;
 | 
			
		||||
 | 
			
		||||
    ret = do_req(fd, (SheepdogReq *)&req, vdi_inuse, &wlen, &rlen);
 | 
			
		||||
    ret = do_req(fd, s->aio_context, (SheepdogReq *)&req,
 | 
			
		||||
                 vdi_inuse, &wlen, &rlen);
 | 
			
		||||
 | 
			
		||||
    closesocket(fd);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
@@ -2338,7 +2379,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* we don't need to read entire object */
 | 
			
		||||
        ret = read_object(fd, (char *)&inode, vid_to_vdi_oid(vid),
 | 
			
		||||
        ret = read_object(fd, s->aio_context, (char *)&inode,
 | 
			
		||||
                          vid_to_vdi_oid(vid),
 | 
			
		||||
                          0, SD_INODE_SIZE - sizeof(inode.data_vdi_id), 0,
 | 
			
		||||
                          s->cache_flags);
 | 
			
		||||
 | 
			
		||||
@@ -2403,11 +2445,11 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
 | 
			
		||||
 | 
			
		||||
        create = (offset == 0);
 | 
			
		||||
        if (load) {
 | 
			
		||||
            ret = read_object(fd, (char *)data, vmstate_oid,
 | 
			
		||||
            ret = read_object(fd, s->aio_context, (char *)data, vmstate_oid,
 | 
			
		||||
                              s->inode.nr_copies, data_len, offset,
 | 
			
		||||
                              s->cache_flags);
 | 
			
		||||
        } else {
 | 
			
		||||
            ret = write_object(fd, (char *)data, vmstate_oid,
 | 
			
		||||
            ret = write_object(fd, s->aio_context, (char *)data, vmstate_oid,
 | 
			
		||||
                               s->inode.nr_copies, data_len, offset, create,
 | 
			
		||||
                               s->cache_flags);
 | 
			
		||||
        }
 | 
			
		||||
@@ -2580,6 +2622,9 @@ static BlockDriver bdrv_sheepdog = {
 | 
			
		||||
    .bdrv_save_vmstate  = sd_save_vmstate,
 | 
			
		||||
    .bdrv_load_vmstate  = sd_load_vmstate,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = sd_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = sd_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    .create_options = sd_create_options,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -2610,6 +2655,9 @@ static BlockDriver bdrv_sheepdog_tcp = {
 | 
			
		||||
    .bdrv_save_vmstate  = sd_save_vmstate,
 | 
			
		||||
    .bdrv_load_vmstate  = sd_load_vmstate,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = sd_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = sd_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    .create_options = sd_create_options,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -2640,6 +2688,9 @@ static BlockDriver bdrv_sheepdog_unix = {
 | 
			
		||||
    .bdrv_save_vmstate  = sd_save_vmstate,
 | 
			
		||||
    .bdrv_load_vmstate  = sd_load_vmstate,
 | 
			
		||||
 | 
			
		||||
    .bdrv_detach_aio_context = sd_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context = sd_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    .create_options = sd_create_options,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								block/ssh.c
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								block/ssh.c
									
									
									
									
									
								
							@@ -773,7 +773,7 @@ static void restart_coroutine(void *opaque)
 | 
			
		||||
    qemu_coroutine_enter(co, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static coroutine_fn void set_fd_handler(BDRVSSHState *s)
 | 
			
		||||
static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    int r;
 | 
			
		||||
    IOHandler *rd_handler = NULL, *wr_handler = NULL;
 | 
			
		||||
@@ -791,24 +791,26 @@ static coroutine_fn void set_fd_handler(BDRVSSHState *s)
 | 
			
		||||
    DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock,
 | 
			
		||||
            rd_handler, wr_handler);
 | 
			
		||||
 | 
			
		||||
    qemu_aio_set_fd_handler(s->sock, rd_handler, wr_handler, co);
 | 
			
		||||
    aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
 | 
			
		||||
                       rd_handler, wr_handler, co);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static coroutine_fn void clear_fd_handler(BDRVSSHState *s)
 | 
			
		||||
static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
 | 
			
		||||
                                          BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    DPRINTF("s->sock=%d", s->sock);
 | 
			
		||||
    qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL);
 | 
			
		||||
    aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, NULL, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* A non-blocking call returned EAGAIN, so yield, ensuring the
 | 
			
		||||
 * handlers are set up so that we'll be rescheduled when there is an
 | 
			
		||||
 * interesting event on the socket.
 | 
			
		||||
 */
 | 
			
		||||
static coroutine_fn void co_yield(BDRVSSHState *s)
 | 
			
		||||
static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    set_fd_handler(s);
 | 
			
		||||
    set_fd_handler(s, bs);
 | 
			
		||||
    qemu_coroutine_yield();
 | 
			
		||||
    clear_fd_handler(s);
 | 
			
		||||
    clear_fd_handler(s, bs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position
 | 
			
		||||
@@ -838,7 +840,7 @@ static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static coroutine_fn int ssh_read(BDRVSSHState *s,
 | 
			
		||||
static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs,
 | 
			
		||||
                                 int64_t offset, size_t size,
 | 
			
		||||
                                 QEMUIOVector *qiov)
 | 
			
		||||
{
 | 
			
		||||
@@ -871,7 +873,7 @@ static coroutine_fn int ssh_read(BDRVSSHState *s,
 | 
			
		||||
        DPRINTF("sftp_read returned %zd", r);
 | 
			
		||||
 | 
			
		||||
        if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
 | 
			
		||||
            co_yield(s);
 | 
			
		||||
            co_yield(s, bs);
 | 
			
		||||
            goto again;
 | 
			
		||||
        }
 | 
			
		||||
        if (r < 0) {
 | 
			
		||||
@@ -906,14 +908,14 @@ static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    qemu_co_mutex_lock(&s->lock);
 | 
			
		||||
    ret = ssh_read(s, sector_num * BDRV_SECTOR_SIZE,
 | 
			
		||||
    ret = ssh_read(s, bs, sector_num * BDRV_SECTOR_SIZE,
 | 
			
		||||
                   nb_sectors * BDRV_SECTOR_SIZE, qiov);
 | 
			
		||||
    qemu_co_mutex_unlock(&s->lock);
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ssh_write(BDRVSSHState *s,
 | 
			
		||||
static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
 | 
			
		||||
                     int64_t offset, size_t size,
 | 
			
		||||
                     QEMUIOVector *qiov)
 | 
			
		||||
{
 | 
			
		||||
@@ -941,7 +943,7 @@ static int ssh_write(BDRVSSHState *s,
 | 
			
		||||
        DPRINTF("sftp_write returned %zd", r);
 | 
			
		||||
 | 
			
		||||
        if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
 | 
			
		||||
            co_yield(s);
 | 
			
		||||
            co_yield(s, bs);
 | 
			
		||||
            goto again;
 | 
			
		||||
        }
 | 
			
		||||
        if (r < 0) {
 | 
			
		||||
@@ -960,7 +962,7 @@ static int ssh_write(BDRVSSHState *s,
 | 
			
		||||
         */
 | 
			
		||||
        if (r == 0) {
 | 
			
		||||
            ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE);
 | 
			
		||||
            co_yield(s);
 | 
			
		||||
            co_yield(s, bs);
 | 
			
		||||
            goto again;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -988,7 +990,7 @@ static coroutine_fn int ssh_co_writev(BlockDriverState *bs,
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    qemu_co_mutex_lock(&s->lock);
 | 
			
		||||
    ret = ssh_write(s, sector_num * BDRV_SECTOR_SIZE,
 | 
			
		||||
    ret = ssh_write(s, bs, sector_num * BDRV_SECTOR_SIZE,
 | 
			
		||||
                    nb_sectors * BDRV_SECTOR_SIZE, qiov);
 | 
			
		||||
    qemu_co_mutex_unlock(&s->lock);
 | 
			
		||||
 | 
			
		||||
@@ -1009,7 +1011,7 @@ static void unsafe_flush_warning(BDRVSSHState *s, const char *what)
 | 
			
		||||
 | 
			
		||||
#ifdef HAS_LIBSSH2_SFTP_FSYNC
 | 
			
		||||
 | 
			
		||||
static coroutine_fn int ssh_flush(BDRVSSHState *s)
 | 
			
		||||
static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
@@ -1017,7 +1019,7 @@ static coroutine_fn int ssh_flush(BDRVSSHState *s)
 | 
			
		||||
 again:
 | 
			
		||||
    r = libssh2_sftp_fsync(s->sftp_handle);
 | 
			
		||||
    if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
 | 
			
		||||
        co_yield(s);
 | 
			
		||||
        co_yield(s, bs);
 | 
			
		||||
        goto again;
 | 
			
		||||
    }
 | 
			
		||||
    if (r == LIBSSH2_ERROR_SFTP_PROTOCOL &&
 | 
			
		||||
@@ -1039,7 +1041,7 @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    qemu_co_mutex_lock(&s->lock);
 | 
			
		||||
    ret = ssh_flush(s);
 | 
			
		||||
    ret = ssh_flush(s, bs);
 | 
			
		||||
    qemu_co_mutex_unlock(&s->lock);
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -239,7 +239,6 @@ static void vdi_header_to_le(VdiHeader *header)
 | 
			
		||||
    cpu_to_le32s(&header->block_extra);
 | 
			
		||||
    cpu_to_le32s(&header->blocks_in_image);
 | 
			
		||||
    cpu_to_le32s(&header->blocks_allocated);
 | 
			
		||||
    cpu_to_le32s(&header->blocks_allocated);
 | 
			
		||||
    uuid_convert(header->uuid_image);
 | 
			
		||||
    uuid_convert(header->uuid_last_snap);
 | 
			
		||||
    uuid_convert(header->uuid_link);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								block/vmdk.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								block/vmdk.c
									
									
									
									
									
								
							@@ -2096,6 +2096,27 @@ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vmdk_detach_aio_context(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    BDRVVmdkState *s = bs->opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_extents; i++) {
 | 
			
		||||
        bdrv_detach_aio_context(s->extents[i].file);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vmdk_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                                    AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    BDRVVmdkState *s = bs->opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->num_extents; i++) {
 | 
			
		||||
        bdrv_attach_aio_context(s->extents[i].file, new_context);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QEMUOptionParameter vmdk_create_options[] = {
 | 
			
		||||
    {
 | 
			
		||||
        .name = BLOCK_OPT_SIZE,
 | 
			
		||||
@@ -2153,6 +2174,8 @@ static BlockDriver bdrv_vmdk = {
 | 
			
		||||
    .bdrv_get_specific_info       = vmdk_get_specific_info,
 | 
			
		||||
    .bdrv_refresh_limits          = vmdk_refresh_limits,
 | 
			
		||||
    .bdrv_get_info                = vmdk_get_info,
 | 
			
		||||
    .bdrv_detach_aio_context      = vmdk_detach_aio_context,
 | 
			
		||||
    .bdrv_attach_aio_context      = vmdk_attach_aio_context,
 | 
			
		||||
 | 
			
		||||
    .create_options               = vmdk_create_options,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ struct QEMUWin32AIOState {
 | 
			
		||||
    HANDLE hIOCP;
 | 
			
		||||
    EventNotifier e;
 | 
			
		||||
    int count;
 | 
			
		||||
    bool is_aio_context_attached;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct QEMUWin32AIOCB {
 | 
			
		||||
@@ -114,7 +115,7 @@ static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
 | 
			
		||||
     * wait for completion.
 | 
			
		||||
     */
 | 
			
		||||
    while (!HasOverlappedIoCompleted(&waiocb->ov)) {
 | 
			
		||||
        qemu_aio_wait();
 | 
			
		||||
        aio_poll(bdrv_get_aio_context(blockacb->bs), true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -180,6 +181,20 @@ int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
 | 
			
		||||
                                  AioContext *old_context)
 | 
			
		||||
{
 | 
			
		||||
    aio_set_event_notifier(old_context, &aio->e, NULL);
 | 
			
		||||
    aio->is_aio_context_attached = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
 | 
			
		||||
                                  AioContext *new_context)
 | 
			
		||||
{
 | 
			
		||||
    aio->is_aio_context_attached = true;
 | 
			
		||||
    aio_set_event_notifier(new_context, &aio->e, win32_aio_completion_cb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QEMUWin32AIOState *win32_aio_init(void)
 | 
			
		||||
{
 | 
			
		||||
    QEMUWin32AIOState *s;
 | 
			
		||||
@@ -194,8 +209,6 @@ QEMUWin32AIOState *win32_aio_init(void)
 | 
			
		||||
        goto out_close_efd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb);
 | 
			
		||||
 | 
			
		||||
    return s;
 | 
			
		||||
 | 
			
		||||
out_close_efd:
 | 
			
		||||
@@ -204,3 +217,11 @@ out_free_state:
 | 
			
		||||
    g_free(s);
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void win32_aio_cleanup(QEMUWin32AIOState *aio)
 | 
			
		||||
{
 | 
			
		||||
    assert(!aio->is_aio_context_attached);
 | 
			
		||||
    CloseHandle(aio->hIOCP);
 | 
			
		||||
    event_notifier_cleanup(&aio->e);
 | 
			
		||||
    g_free(aio);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1703,6 +1703,7 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
 | 
			
		||||
{
 | 
			
		||||
    ThrottleConfig cfg;
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
    AioContext *aio_context;
 | 
			
		||||
 | 
			
		||||
    bs = bdrv_find(device);
 | 
			
		||||
    if (!bs) {
 | 
			
		||||
@@ -1746,6 +1747,9 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    aio_context = bdrv_get_aio_context(bs);
 | 
			
		||||
    aio_context_acquire(aio_context);
 | 
			
		||||
 | 
			
		||||
    if (!bs->io_limits_enabled && throttle_enabled(&cfg)) {
 | 
			
		||||
        bdrv_io_limits_enable(bs);
 | 
			
		||||
    } else if (bs->io_limits_enabled && !throttle_enabled(&cfg)) {
 | 
			
		||||
@@ -1755,6 +1759,8 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
 | 
			
		||||
    if (bs->io_limits_enabled) {
 | 
			
		||||
        bdrv_set_io_limits(bs, &cfg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    aio_context_release(aio_context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,37 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR___getcwd, "__getcwd", NULL, NULL, NULL },
 | 
			
		||||
/*
 | 
			
		||||
 *  FreeBSD strace list
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 *  (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_aclcheck_fd, "__acl_aclcheck_fd", "%s(%d, %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_aclcheck_file, "__acl_aclcheck_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_aclcheck_link, "__acl_aclcheck_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_delete_fd, "__acl_delete_fd", "%s(%d, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_delete_file, "__acl_delete_file", "%s(\"%s\", %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_delete_link, "__acl_delete_link", "%s(\"%s\", %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_get_fd, "__acl_get_fd", "%s(%d, %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_get_file, "__acl_get_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_get_link, "__acl_get_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_set_fd, "__acl_set_fd", "%s(%d, %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_set_file, "__acl_set_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___acl_set_link, "__acl_set_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___semctl, "__semctl", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___syscall, "__syscall", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, print_sysctl, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR__umtx_op, "_umtx_op", "%s(%#x, %d, %d, %#x, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_accept, "accept", "%s(%d,%#x,%#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_access, "access", "%s(\"%s\",%#o)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_acct, "acct", NULL, NULL, NULL },
 | 
			
		||||
@@ -20,24 +50,41 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR_connect, "connect", "%s(%d,%#x,%d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_dup, "dup", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_dup2, "dup2", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_eaccess, "eaccess", "%s(\"%s\",%#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_execve, "execve", NULL, print_execve, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_exit, "exit", "%s(%d)\n", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattrctl, "extattrctl", "%s(\"%s\", %d, \"%s\", %d, \"%s\"", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_delete_fd, "extattr_delete_fd", "%s(%d, %d, \"%s\")", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_delete_file, "extattr_delete_file", "%s(\"%s\", %d, \"%s\")", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_delete_link, "extattr_delete_link", "%s(\"%s\", %d, \"%s\")", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_get_fd, "extattr_get_fd", "%s(%d, %d, \"%s\", %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_get_file, "extattr_get_file", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_get_file, "extattr_get_link", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_list_fd, "extattr_list_fd", "%s(%d, %d, %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_list_file, "extattr_list_file", "%s(\"%s\", %d, %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_list_link, "extattr_list_link", "%s(\"%s\", %d, %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_set_fd, "extattr_set_fd", "%s(%d, %d, \"%s\", %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_set_file, "extattr_set_file", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_extattr_set_link, "extattr_set_link", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fchdir, "fchdir", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fchflags, "fchflags", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fchmod, "fchmod", "%s(%d,%#o)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(\"%s\",%d,%d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(%d,%d,%d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fcntl, "fcntl", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fexecve, "fexecve", NULL, print_execve, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fhopen, "fhopen", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fhstat, "fhstat", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fhstatfs, "fhstatfs", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_flock, "flock", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fork, "fork", "%s()", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fpathconf, "fpathconf", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fstat, "fstat", "%s(%d,%p)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fstatfs, "fstatfs", "%s(%d,%p)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fstat, "fstat", "%s(%d,%#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fstatat, "fstatat", "%s(%d,\"%s\", %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fstatfs, "fstatfs", "%s(%d,%#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_fsync, "fsync", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_getcontext, "getcontext", "%s(%#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_getdirentries, "getdirentries", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_freebsd6_mmap, "freebsd6_mmap", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_getegid, "getegid", "%s()", NULL, NULL },
 | 
			
		||||
@@ -63,7 +110,7 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR_getsockopt, "getsockopt", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_gettimeofday, "gettimeofday", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_getuid, "getuid", "%s()", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_ioctl, "ioctl", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_ioctl, "ioctl", NULL, print_ioctl, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_issetugid, "issetugid", "%s()", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_kevent, "kevent", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_kill, "kill", NULL, NULL, NULL },
 | 
			
		||||
@@ -72,6 +119,7 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR_lchown, "lchown", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_link, "link", "%s(\"%s\",\"%s\")", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_listen, "listen", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_lpathconf, "lpathconf", "%s(\"%s\", %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_lseek, "lseek", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_lstat, "lstat", "%s(\"%s\",%p)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_madvise, "madvise", NULL, NULL, NULL },
 | 
			
		||||
@@ -96,7 +144,8 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR_nanosleep, "nanosleep", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_nfssvc, "nfssvc", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_open, "open", "%s(\"%s\",%#x,%#o)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_pathconf, "pathconf", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_openat, "openat", "%s(%d, \"%s\",%#x,%#o)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_pathconf, "pathconf", "%s(\"%s\", %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_pipe, "pipe", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_poll, "poll", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_pread, "pread", NULL, NULL, NULL },
 | 
			
		||||
@@ -116,6 +165,7 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR_revoke, "revoke", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_rfork, "rfork", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_rmdir, "rmdir", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_rtprio_thread, "rtprio_thread", "%s(%d, %d, %p)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_sbrk, "sbrk", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_sched_yield, "sched_yield", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_select, "select", NULL, NULL, NULL },
 | 
			
		||||
@@ -123,6 +173,7 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR_semop, "semop", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_sendmsg, "sendmsg", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_sendto, "sendto", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_setcontext, "setcontext", "%s(%#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_setegid, "setegid", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_seteuid, "seteuid", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_setgid, "setgid", NULL, NULL, NULL },
 | 
			
		||||
@@ -151,7 +202,7 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR_sigprocmask, "sigprocmask", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_sigreturn, "sigreturn", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_sigsuspend, "sigsuspend", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_socket, "socket", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_socket, "socket", "%s(%d,%d,%d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_socketpair, "socketpair", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_sstk, "sstk", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_stat, "stat", "%s(\"%s\",%p)", NULL, NULL },
 | 
			
		||||
@@ -160,6 +211,15 @@
 | 
			
		||||
{ TARGET_FREEBSD_NR_sync, "sync", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_sysarch, "sysarch", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_syscall, "syscall", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_create, "thr_create", "%s(%#x, %#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_exit, "thr_exit", "%s(%#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_kill, "thr_kill", "%s(%d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_kill2, "thr_kill2", "%s(%d, %d, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_new, "thr_new", "%s(%#x, %d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_self, "thr_self", "%s(%#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_set_name, "thr_set_name", "%s(%d, \"%s\")", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_suspend, "thr_suspend", "%s(%d, %#x)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_thr_wake, "thr_wake", "%s(%d)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_truncate, "truncate", NULL, NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_umask, "umask", "%s(%#o)", NULL, NULL },
 | 
			
		||||
{ TARGET_FREEBSD_NR_unlink, "unlink", "%s(\"%s\")", NULL, NULL },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,373 +1,450 @@
 | 
			
		||||
/*
 | 
			
		||||
 * System call numbers.
 | 
			
		||||
 *
 | 
			
		||||
 * $FreeBSD: src/sys/sys/syscall.h,v 1.224 2008/08/24 21:23:08 rwatson Exp $
 | 
			
		||||
 * created from FreeBSD: head/sys/kern/syscalls.master 182123 2008-08-24 21:20:35Z rwatson
 | 
			
		||||
 * created from FreeBSD: releng/9.1/sys/kern/syscalls.master 229723
 | 
			
		||||
 * 2012-01-06 19:29:16Z jhb
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define TARGET_FREEBSD_NR_syscall     0
 | 
			
		||||
#define TARGET_FREEBSD_NR_exit        1
 | 
			
		||||
#define TARGET_FREEBSD_NR_fork        2
 | 
			
		||||
#define TARGET_FREEBSD_NR_read        3
 | 
			
		||||
#define TARGET_FREEBSD_NR_write       4
 | 
			
		||||
#define TARGET_FREEBSD_NR_open        5
 | 
			
		||||
#define TARGET_FREEBSD_NR_close       6
 | 
			
		||||
#define TARGET_FREEBSD_NR_wait4       7
 | 
			
		||||
#define TARGET_FREEBSD_NR_link        9
 | 
			
		||||
#define TARGET_FREEBSD_NR_unlink      10
 | 
			
		||||
#define TARGET_FREEBSD_NR_chdir       12
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchdir      13
 | 
			
		||||
#define TARGET_FREEBSD_NR_mknod       14
 | 
			
		||||
#define TARGET_FREEBSD_NR_chmod       15
 | 
			
		||||
#define TARGET_FREEBSD_NR_chown       16
 | 
			
		||||
#define TARGET_FREEBSD_NR_break       17
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_getfsstat  18
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpid      20
 | 
			
		||||
#define TARGET_FREEBSD_NR_mount       21
 | 
			
		||||
#define TARGET_FREEBSD_NR_unmount     22
 | 
			
		||||
#define TARGET_FREEBSD_NR_setuid      23
 | 
			
		||||
#define TARGET_FREEBSD_NR_getuid      24
 | 
			
		||||
#define TARGET_FREEBSD_NR_geteuid     25
 | 
			
		||||
#define TARGET_FREEBSD_NR_ptrace      26
 | 
			
		||||
#define TARGET_FREEBSD_NR_recvmsg     27
 | 
			
		||||
#define TARGET_FREEBSD_NR_sendmsg     28
 | 
			
		||||
#define TARGET_FREEBSD_NR_recvfrom    29
 | 
			
		||||
#define TARGET_FREEBSD_NR_accept      30
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpeername 31
 | 
			
		||||
#define TARGET_FREEBSD_NR_getsockname 32
 | 
			
		||||
#define TARGET_FREEBSD_NR_access      33
 | 
			
		||||
#define TARGET_FREEBSD_NR_chflags     34
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchflags    35
 | 
			
		||||
#define TARGET_FREEBSD_NR_sync        36
 | 
			
		||||
#define TARGET_FREEBSD_NR_kill        37
 | 
			
		||||
#define TARGET_FREEBSD_NR_getppid     39
 | 
			
		||||
#define TARGET_FREEBSD_NR_dup 41
 | 
			
		||||
#define TARGET_FREEBSD_NR_pipe        42
 | 
			
		||||
#define TARGET_FREEBSD_NR_getegid     43
 | 
			
		||||
#define TARGET_FREEBSD_NR_profil      44
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktrace      45
 | 
			
		||||
#define TARGET_FREEBSD_NR_getgid      47
 | 
			
		||||
#define TARGET_FREEBSD_NR_getlogin    49
 | 
			
		||||
#define TARGET_FREEBSD_NR_setlogin    50
 | 
			
		||||
#define TARGET_FREEBSD_NR_acct        51
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigaltstack 53
 | 
			
		||||
#define TARGET_FREEBSD_NR_ioctl       54
 | 
			
		||||
#define TARGET_FREEBSD_NR_reboot      55
 | 
			
		||||
#define TARGET_FREEBSD_NR_revoke      56
 | 
			
		||||
#define TARGET_FREEBSD_NR_symlink     57
 | 
			
		||||
#define TARGET_FREEBSD_NR_readlink    58
 | 
			
		||||
#define TARGET_FREEBSD_NR_execve      59
 | 
			
		||||
#define TARGET_FREEBSD_NR_umask       60
 | 
			
		||||
#define TARGET_FREEBSD_NR_chroot      61
 | 
			
		||||
#define TARGET_FREEBSD_NR_msync       65
 | 
			
		||||
#define TARGET_FREEBSD_NR_vfork       66
 | 
			
		||||
#define TARGET_FREEBSD_NR_sbrk        69
 | 
			
		||||
#define TARGET_FREEBSD_NR_sstk        70
 | 
			
		||||
#define TARGET_FREEBSD_NR_vadvise     72
 | 
			
		||||
#define TARGET_FREEBSD_NR_munmap      73
 | 
			
		||||
#define TARGET_FREEBSD_NR_mprotect    74
 | 
			
		||||
#define TARGET_FREEBSD_NR_madvise     75
 | 
			
		||||
#define TARGET_FREEBSD_NR_mincore     78
 | 
			
		||||
#define TARGET_FREEBSD_NR_getgroups   79
 | 
			
		||||
#define TARGET_FREEBSD_NR_setgroups   80
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpgrp     81
 | 
			
		||||
#define TARGET_FREEBSD_NR_setpgid     82
 | 
			
		||||
#define TARGET_FREEBSD_NR_setitimer   83
 | 
			
		||||
#define TARGET_FREEBSD_NR_swapon      85
 | 
			
		||||
#define TARGET_FREEBSD_NR_getitimer   86
 | 
			
		||||
#define TARGET_FREEBSD_NR_getdtablesize       89
 | 
			
		||||
#define TARGET_FREEBSD_NR_dup2        90
 | 
			
		||||
#define TARGET_FREEBSD_NR_fcntl       92
 | 
			
		||||
#define TARGET_FREEBSD_NR_select      93
 | 
			
		||||
#define TARGET_FREEBSD_NR_fsync       95
 | 
			
		||||
#define TARGET_FREEBSD_NR_setpriority 96
 | 
			
		||||
#define TARGET_FREEBSD_NR_socket      97
 | 
			
		||||
#define TARGET_FREEBSD_NR_connect     98
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpriority 100
 | 
			
		||||
#define TARGET_FREEBSD_NR_bind        104
 | 
			
		||||
#define TARGET_FREEBSD_NR_setsockopt  105
 | 
			
		||||
#define TARGET_FREEBSD_NR_listen      106
 | 
			
		||||
#define TARGET_FREEBSD_NR_gettimeofday        116
 | 
			
		||||
#define TARGET_FREEBSD_NR_getrusage   117
 | 
			
		||||
#define TARGET_FREEBSD_NR_getsockopt  118
 | 
			
		||||
#define TARGET_FREEBSD_NR_readv       120
 | 
			
		||||
#define TARGET_FREEBSD_NR_writev      121
 | 
			
		||||
#define TARGET_FREEBSD_NR_settimeofday        122
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchown      123
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchmod      124
 | 
			
		||||
#define TARGET_FREEBSD_NR_setreuid    126
 | 
			
		||||
#define TARGET_FREEBSD_NR_setregid    127
 | 
			
		||||
#define TARGET_FREEBSD_NR_rename      128
 | 
			
		||||
#define TARGET_FREEBSD_NR_flock       131
 | 
			
		||||
#define TARGET_FREEBSD_NR_mkfifo      132
 | 
			
		||||
#define TARGET_FREEBSD_NR_sendto      133
 | 
			
		||||
#define TARGET_FREEBSD_NR_shutdown    134
 | 
			
		||||
#define TARGET_FREEBSD_NR_socketpair  135
 | 
			
		||||
#define TARGET_FREEBSD_NR_mkdir       136
 | 
			
		||||
#define TARGET_FREEBSD_NR_rmdir       137
 | 
			
		||||
#define TARGET_FREEBSD_NR_utimes      138
 | 
			
		||||
#define TARGET_FREEBSD_NR_adjtime     140
 | 
			
		||||
#define TARGET_FREEBSD_NR_setsid      147
 | 
			
		||||
#define TARGET_FREEBSD_NR_quotactl    148
 | 
			
		||||
#define TARGET_FREEBSD_NR_nlm_syscall 154
 | 
			
		||||
#define TARGET_FREEBSD_NR_nfssvc      155
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_statfs     157
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_fstatfs    158
 | 
			
		||||
#define TARGET_FREEBSD_NR_lgetfh      160
 | 
			
		||||
#define TARGET_FREEBSD_NR_getfh       161
 | 
			
		||||
#define TARGET_FREEBSD_NR_getdomainname       162
 | 
			
		||||
#define TARGET_FREEBSD_NR_setdomainname       163
 | 
			
		||||
#define TARGET_FREEBSD_NR_uname       164
 | 
			
		||||
#define TARGET_FREEBSD_NR_sysarch     165
 | 
			
		||||
#define TARGET_FREEBSD_NR_rtprio      166
 | 
			
		||||
#define TARGET_FREEBSD_NR_semsys      169
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgsys      170
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmsys      171
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_pread      173
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_pwrite     174
 | 
			
		||||
#define TARGET_FREEBSD_NR_setfib      175
 | 
			
		||||
#define TARGET_FREEBSD_NR_ntp_adjtime 176
 | 
			
		||||
#define TARGET_FREEBSD_NR_setgid      181
 | 
			
		||||
#define TARGET_FREEBSD_NR_setegid     182
 | 
			
		||||
#define TARGET_FREEBSD_NR_seteuid     183
 | 
			
		||||
#define TARGET_FREEBSD_NR_stat        188
 | 
			
		||||
#define TARGET_FREEBSD_NR_fstat       189
 | 
			
		||||
#define TARGET_FREEBSD_NR_lstat       190
 | 
			
		||||
#define TARGET_FREEBSD_NR_pathconf    191
 | 
			
		||||
#define TARGET_FREEBSD_NR_fpathconf   192
 | 
			
		||||
#define TARGET_FREEBSD_NR_getrlimit   194
 | 
			
		||||
#define TARGET_FREEBSD_NR_setrlimit   195
 | 
			
		||||
#define TARGET_FREEBSD_NR_getdirentries       196
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_mmap       197
 | 
			
		||||
#define TARGET_FREEBSD_NR___syscall   198
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_lseek      199
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_truncate   200
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_ftruncate  201
 | 
			
		||||
#define TARGET_FREEBSD_NR___sysctl    202
 | 
			
		||||
#define TARGET_FREEBSD_NR_mlock       203
 | 
			
		||||
#define TARGET_FREEBSD_NR_munlock     204
 | 
			
		||||
#define TARGET_FREEBSD_NR_undelete    205
 | 
			
		||||
#define TARGET_FREEBSD_NR_futimes     206
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpgid     207
 | 
			
		||||
#define TARGET_FREEBSD_NR_poll        209
 | 
			
		||||
#define TARGET_FREEBSD_NR___semctl    220
 | 
			
		||||
#define TARGET_FREEBSD_NR_semget      221
 | 
			
		||||
#define TARGET_FREEBSD_NR_semop       222
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgctl      224
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgget      225
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgsnd      226
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgrcv      227
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmat       228
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmctl      229
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmdt       230
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmget      231
 | 
			
		||||
#define TARGET_FREEBSD_NR_clock_gettime       232
 | 
			
		||||
#define TARGET_FREEBSD_NR_clock_settime       233
 | 
			
		||||
#define TARGET_FREEBSD_NR_clock_getres        234
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_create       235
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_delete       236
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_settime      237
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_gettime      238
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_getoverrun   239
 | 
			
		||||
#define TARGET_FREEBSD_NR_nanosleep   240
 | 
			
		||||
#define TARGET_FREEBSD_NR_ntp_gettime 248
 | 
			
		||||
#define TARGET_FREEBSD_NR_minherit    250
 | 
			
		||||
#define TARGET_FREEBSD_NR_rfork       251
 | 
			
		||||
#define TARGET_FREEBSD_NR_openbsd_poll        252
 | 
			
		||||
#define TARGET_FREEBSD_NR_issetugid   253
 | 
			
		||||
#define TARGET_FREEBSD_NR_lchown      254
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_read    255
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_write   256
 | 
			
		||||
#define TARGET_FREEBSD_NR_lio_listio  257
 | 
			
		||||
#define TARGET_FREEBSD_NR_getdents    272
 | 
			
		||||
#define TARGET_FREEBSD_NR_lchmod      274
 | 
			
		||||
#define TARGET_FREEBSD_NR_netbsd_lchown       275
 | 
			
		||||
#define TARGET_FREEBSD_NR_lutimes     276
 | 
			
		||||
#define TARGET_FREEBSD_NR_netbsd_msync        277
 | 
			
		||||
#define TARGET_FREEBSD_NR_nstat       278
 | 
			
		||||
#define TARGET_FREEBSD_NR_nfstat      279
 | 
			
		||||
#define TARGET_FREEBSD_NR_nlstat      280
 | 
			
		||||
#define TARGET_FREEBSD_NR_preadv      289
 | 
			
		||||
#define TARGET_FREEBSD_NR_pwritev     290
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_fhstatfs   297
 | 
			
		||||
#define TARGET_FREEBSD_NR_fhopen      298
 | 
			
		||||
#define TARGET_FREEBSD_NR_fhstat      299
 | 
			
		||||
#define TARGET_FREEBSD_NR_modnext     300
 | 
			
		||||
#define TARGET_FREEBSD_NR_modstat     301
 | 
			
		||||
#define TARGET_FREEBSD_NR_modfnext    302
 | 
			
		||||
#define TARGET_FREEBSD_NR_modfind     303
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldload     304
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldunload   305
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldfind     306
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldnext     307
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldstat     308
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldfirstmod 309
 | 
			
		||||
#define TARGET_FREEBSD_NR_getsid      310
 | 
			
		||||
#define TARGET_FREEBSD_NR_setresuid   311
 | 
			
		||||
#define TARGET_FREEBSD_NR_setresgid   312
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_return  314
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_suspend 315
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_cancel  316
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_error   317
 | 
			
		||||
#define TARGET_FREEBSD_NR_oaio_read   318
 | 
			
		||||
#define TARGET_FREEBSD_NR_oaio_write  319
 | 
			
		||||
#define TARGET_FREEBSD_NR_olio_listio 320
 | 
			
		||||
#define TARGET_FREEBSD_NR_yield       321
 | 
			
		||||
#define TARGET_FREEBSD_NR_mlockall    324
 | 
			
		||||
#define TARGET_FREEBSD_NR_munlockall  325
 | 
			
		||||
#define TARGET_FREEBSD_NR___getcwd    326
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_setparam      327
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_getparam      328
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_setscheduler  329
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_getscheduler  330
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_yield 331
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_get_priority_max      332
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_get_priority_min      333
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_rr_get_interval       334
 | 
			
		||||
#define TARGET_FREEBSD_NR_utrace      335
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_sendfile   336
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldsym      337
 | 
			
		||||
#define TARGET_FREEBSD_NR_jail        338
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigprocmask 340
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigsuspend  341
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_sigaction  342
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigpending  343
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_sigreturn  344
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigtimedwait        345
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigwaitinfo 346
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_get_file      347
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_set_file      348
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_get_fd        349
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_set_fd        350
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_delete_file   351
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_delete_fd     352
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_aclcheck_file 353
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_aclcheck_fd   354
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattrctl  355
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_set_file    356
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_get_file    357
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_delete_file 358
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_waitcomplete    359
 | 
			
		||||
#define TARGET_FREEBSD_NR_getresuid   360
 | 
			
		||||
#define TARGET_FREEBSD_NR_getresgid   361
 | 
			
		||||
#define TARGET_FREEBSD_NR_kqueue      362
 | 
			
		||||
#define TARGET_FREEBSD_NR_kevent      363
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_set_fd      371
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_get_fd      372
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_delete_fd   373
 | 
			
		||||
#define TARGET_FREEBSD_NR___setugid   374
 | 
			
		||||
#define TARGET_FREEBSD_NR_nfsclnt     375
 | 
			
		||||
#define TARGET_FREEBSD_NR_eaccess     376
 | 
			
		||||
#define TARGET_FREEBSD_NR_nmount      378
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_proc      384
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_set_proc      385
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_fd        386
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_file      387
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_set_fd        388
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_set_file      389
 | 
			
		||||
#define TARGET_FREEBSD_NR_kenv        390
 | 
			
		||||
#define TARGET_FREEBSD_NR_lchflags    391
 | 
			
		||||
#define TARGET_FREEBSD_NR_uuidgen     392
 | 
			
		||||
#define TARGET_FREEBSD_NR_sendfile    393
 | 
			
		||||
#define TARGET_FREEBSD_NR_mac_syscall 394
 | 
			
		||||
#define TARGET_FREEBSD_NR_getfsstat   395
 | 
			
		||||
#define TARGET_FREEBSD_NR_statfs      396
 | 
			
		||||
#define TARGET_FREEBSD_NR_fstatfs     397
 | 
			
		||||
#define TARGET_FREEBSD_NR_fhstatfs    398
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_close  400
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_post   401
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_wait   402
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_trywait        403
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_init   404
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_open   405
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_unlink 406
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_getvalue       407
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_destroy        408
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_pid       409
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_link      410
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_set_link      411
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_set_link    412
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_get_link    413
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_delete_link 414
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_execve        415
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigaction   416
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigreturn   417
 | 
			
		||||
#define TARGET_FREEBSD_NR_getcontext  421
 | 
			
		||||
#define TARGET_FREEBSD_NR_setcontext  422
 | 
			
		||||
#define TARGET_FREEBSD_NR_swapcontext 423
 | 
			
		||||
#define TARGET_FREEBSD_NR_swapoff     424
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_get_link      425
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_set_link      426
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_delete_link   427
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_aclcheck_link 428
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigwait     429
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_create  430
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_exit    431
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_self    432
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_kill    433
 | 
			
		||||
#define TARGET_FREEBSD_NR__umtx_lock  434
 | 
			
		||||
#define TARGET_FREEBSD_NR__umtx_unlock        435
 | 
			
		||||
#define TARGET_FREEBSD_NR_jail_attach 436
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_list_fd     437
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_list_file   438
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_list_link   439
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_timedwait      441
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_suspend 442
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_wake    443
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldunloadf  444
 | 
			
		||||
#define TARGET_FREEBSD_NR_audit       445
 | 
			
		||||
#define TARGET_FREEBSD_NR_auditon     446
 | 
			
		||||
#define TARGET_FREEBSD_NR_getauid     447
 | 
			
		||||
#define TARGET_FREEBSD_NR_setauid     448
 | 
			
		||||
#define TARGET_FREEBSD_NR_getaudit    449
 | 
			
		||||
#define TARGET_FREEBSD_NR_setaudit    450
 | 
			
		||||
#define TARGET_FREEBSD_NR_getaudit_addr       451
 | 
			
		||||
#define TARGET_FREEBSD_NR_setaudit_addr       452
 | 
			
		||||
#define TARGET_FREEBSD_NR_auditctl    453
 | 
			
		||||
#define TARGET_FREEBSD_NR__umtx_op    454
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_new     455
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigqueue    456
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_open    457
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_setattr 458
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_timedreceive    459
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_timedsend       460
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_notify  461
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_unlink  462
 | 
			
		||||
#define TARGET_FREEBSD_NR_abort2      463
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_set_name        464
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_fsync   465
 | 
			
		||||
#define TARGET_FREEBSD_NR_rtprio_thread       466
 | 
			
		||||
#define TARGET_FREEBSD_NR_sctp_peeloff        471
 | 
			
		||||
#define TARGET_FREEBSD_NR_sctp_generic_sendmsg        472
 | 
			
		||||
#define TARGET_FREEBSD_NR_sctp_generic_sendmsg_iov    473
 | 
			
		||||
#define TARGET_FREEBSD_NR_sctp_generic_recvmsg        474
 | 
			
		||||
#define TARGET_FREEBSD_NR_pread       475
 | 
			
		||||
#define TARGET_FREEBSD_NR_pwrite      476
 | 
			
		||||
#define TARGET_FREEBSD_NR_mmap        477
 | 
			
		||||
#define TARGET_FREEBSD_NR_lseek       478
 | 
			
		||||
#define TARGET_FREEBSD_NR_truncate    479
 | 
			
		||||
#define TARGET_FREEBSD_NR_ftruncate   480
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_kill2   481
 | 
			
		||||
#define TARGET_FREEBSD_NR_shm_open    482
 | 
			
		||||
#define TARGET_FREEBSD_NR_shm_unlink  483
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset      484
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset_setid        485
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset_getid        486
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset_getaffinity  487
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset_setaffinity  488
 | 
			
		||||
#define TARGET_FREEBSD_NR_faccessat   489
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchmodat    490
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchownat    491
 | 
			
		||||
#define TARGET_FREEBSD_NR_fexecve     492
 | 
			
		||||
#define TARGET_FREEBSD_NR_fstatat     493
 | 
			
		||||
#define TARGET_FREEBSD_NR_futimesat   494
 | 
			
		||||
#define TARGET_FREEBSD_NR_linkat      495
 | 
			
		||||
#define TARGET_FREEBSD_NR_mkdirat     496
 | 
			
		||||
#define TARGET_FREEBSD_NR_mkfifoat    497
 | 
			
		||||
#define TARGET_FREEBSD_NR_mknodat     498
 | 
			
		||||
#define TARGET_FREEBSD_NR_openat      499
 | 
			
		||||
#define TARGET_FREEBSD_NR_readlinkat  500
 | 
			
		||||
#define TARGET_FREEBSD_NR_renameat    501
 | 
			
		||||
#define TARGET_FREEBSD_NR_symlinkat   502
 | 
			
		||||
#define TARGET_FREEBSD_NR_unlinkat    503
 | 
			
		||||
#define TARGET_FREEBSD_NR_posix_openpt        504
 | 
			
		||||
#define TARGET_FREEBSD_NR_syscall   0
 | 
			
		||||
#define TARGET_FREEBSD_NR_exit  1
 | 
			
		||||
#define TARGET_FREEBSD_NR_fork  2
 | 
			
		||||
#define TARGET_FREEBSD_NR_read  3
 | 
			
		||||
#define TARGET_FREEBSD_NR_write 4
 | 
			
		||||
#define TARGET_FREEBSD_NR_open  5
 | 
			
		||||
#define TARGET_FREEBSD_NR_close 6
 | 
			
		||||
#define TARGET_FREEBSD_NR_wait4 7
 | 
			
		||||
                /* 8 is old creat */
 | 
			
		||||
#define TARGET_FREEBSD_NR_link  9
 | 
			
		||||
#define TARGET_FREEBSD_NR_unlink    10
 | 
			
		||||
                /* 11 is obsolete execv */
 | 
			
		||||
#define TARGET_FREEBSD_NR_chdir 12
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchdir    13
 | 
			
		||||
#define TARGET_FREEBSD_NR_mknod 14
 | 
			
		||||
#define TARGET_FREEBSD_NR_chmod 15
 | 
			
		||||
#define TARGET_FREEBSD_NR_chown 16
 | 
			
		||||
#define TARGET_FREEBSD_NR_break 17
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_getfsstat    18
 | 
			
		||||
                /* 19 is old lseek */
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpid    20
 | 
			
		||||
#define TARGET_FREEBSD_NR_mount 21
 | 
			
		||||
#define TARGET_FREEBSD_NR_unmount   22
 | 
			
		||||
#define TARGET_FREEBSD_NR_setuid    23
 | 
			
		||||
#define TARGET_FREEBSD_NR_getuid    24
 | 
			
		||||
#define TARGET_FREEBSD_NR_geteuid   25
 | 
			
		||||
#define TARGET_FREEBSD_NR_ptrace    26
 | 
			
		||||
#define TARGET_FREEBSD_NR_recvmsg   27
 | 
			
		||||
#define TARGET_FREEBSD_NR_sendmsg   28
 | 
			
		||||
#define TARGET_FREEBSD_NR_recvfrom  29
 | 
			
		||||
#define TARGET_FREEBSD_NR_accept    30
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpeername   31
 | 
			
		||||
#define TARGET_FREEBSD_NR_getsockname   32
 | 
			
		||||
#define TARGET_FREEBSD_NR_access    33
 | 
			
		||||
#define TARGET_FREEBSD_NR_chflags   34
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchflags  35
 | 
			
		||||
#define TARGET_FREEBSD_NR_sync  36
 | 
			
		||||
#define TARGET_FREEBSD_NR_kill  37
 | 
			
		||||
                /* 38 is old stat */
 | 
			
		||||
#define TARGET_FREEBSD_NR_getppid   39
 | 
			
		||||
                /* 40 is old lstat */
 | 
			
		||||
#define TARGET_FREEBSD_NR_dup   41
 | 
			
		||||
#define TARGET_FREEBSD_NR_pipe  42
 | 
			
		||||
#define TARGET_FREEBSD_NR_getegid   43
 | 
			
		||||
#define TARGET_FREEBSD_NR_profil    44
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktrace    45
 | 
			
		||||
                /* 46 is old sigaction */
 | 
			
		||||
#define TARGET_FREEBSD_NR_getgid    47
 | 
			
		||||
                /* 48 is old sigprocmask */
 | 
			
		||||
#define TARGET_FREEBSD_NR_getlogin  49
 | 
			
		||||
#define TARGET_FREEBSD_NR_setlogin  50
 | 
			
		||||
#define TARGET_FREEBSD_NR_acct  51
 | 
			
		||||
                /* 52 is old sigpending */
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigaltstack   53
 | 
			
		||||
#define TARGET_FREEBSD_NR_ioctl 54
 | 
			
		||||
#define TARGET_FREEBSD_NR_reboot    55
 | 
			
		||||
#define TARGET_FREEBSD_NR_revoke    56
 | 
			
		||||
#define TARGET_FREEBSD_NR_symlink   57
 | 
			
		||||
#define TARGET_FREEBSD_NR_readlink  58
 | 
			
		||||
#define TARGET_FREEBSD_NR_execve    59
 | 
			
		||||
#define TARGET_FREEBSD_NR_umask 60
 | 
			
		||||
#define TARGET_FREEBSD_NR_chroot    61
 | 
			
		||||
                /* 62 is old fstat */
 | 
			
		||||
                /* 63 is old getkerninfo */
 | 
			
		||||
                /* 64 is old getpagesize */
 | 
			
		||||
#define TARGET_FREEBSD_NR_msync 65
 | 
			
		||||
#define TARGET_FREEBSD_NR_vfork 66
 | 
			
		||||
                /* 67 is obsolete vread */
 | 
			
		||||
                /* 68 is obsolete vwrite */
 | 
			
		||||
#define TARGET_FREEBSD_NR_sbrk  69
 | 
			
		||||
#define TARGET_FREEBSD_NR_sstk  70
 | 
			
		||||
                /* 71 is old mmap */
 | 
			
		||||
#define TARGET_FREEBSD_NR_vadvise   72
 | 
			
		||||
#define TARGET_FREEBSD_NR_munmap    73
 | 
			
		||||
#define TARGET_FREEBSD_NR_mprotect  74
 | 
			
		||||
#define TARGET_FREEBSD_NR_madvise   75
 | 
			
		||||
                /* 76 is obsolete vhangup */
 | 
			
		||||
                /* 77 is obsolete vlimit */
 | 
			
		||||
#define TARGET_FREEBSD_NR_mincore   78
 | 
			
		||||
#define TARGET_FREEBSD_NR_getgroups 79
 | 
			
		||||
#define TARGET_FREEBSD_NR_setgroups 80
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpgrp   81
 | 
			
		||||
#define TARGET_FREEBSD_NR_setpgid   82
 | 
			
		||||
#define TARGET_FREEBSD_NR_setitimer 83
 | 
			
		||||
                /* 84 is old wait */
 | 
			
		||||
#define TARGET_FREEBSD_NR_swapon    85
 | 
			
		||||
#define TARGET_FREEBSD_NR_getitimer 86
 | 
			
		||||
                /* 87 is old gethostname */
 | 
			
		||||
                /* 88 is old sethostname */
 | 
			
		||||
#define TARGET_FREEBSD_NR_getdtablesize 89
 | 
			
		||||
#define TARGET_FREEBSD_NR_dup2  90
 | 
			
		||||
#define TARGET_FREEBSD_NR_fcntl 92
 | 
			
		||||
#define TARGET_FREEBSD_NR_select    93
 | 
			
		||||
#define TARGET_FREEBSD_NR_fsync 95
 | 
			
		||||
#define TARGET_FREEBSD_NR_setpriority   96
 | 
			
		||||
#define TARGET_FREEBSD_NR_socket    97
 | 
			
		||||
#define TARGET_FREEBSD_NR_connect   98
 | 
			
		||||
                /* 99 is old accept */
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpriority   100
 | 
			
		||||
                /* 101 is old send */
 | 
			
		||||
                /* 102 is old recv */
 | 
			
		||||
                /* 103 is old sigreturn */
 | 
			
		||||
#define TARGET_FREEBSD_NR_bind  104
 | 
			
		||||
#define TARGET_FREEBSD_NR_setsockopt    105
 | 
			
		||||
#define TARGET_FREEBSD_NR_listen    106
 | 
			
		||||
                /* 107 is obsolete vtimes */
 | 
			
		||||
                /* 108 is old sigvec */
 | 
			
		||||
                /* 109 is old sigblock */
 | 
			
		||||
                /* 110 is old sigsetmask */
 | 
			
		||||
                /* 111 is old sigsuspend */
 | 
			
		||||
                /* 112 is old sigstack */
 | 
			
		||||
                /* 113 is old recvmsg */
 | 
			
		||||
                /* 114 is old sendmsg */
 | 
			
		||||
                /* 115 is obsolete vtrace */
 | 
			
		||||
#define TARGET_FREEBSD_NR_gettimeofday  116
 | 
			
		||||
#define TARGET_FREEBSD_NR_getrusage 117
 | 
			
		||||
#define TARGET_FREEBSD_NR_getsockopt    118
 | 
			
		||||
#define TARGET_FREEBSD_NR_readv 120
 | 
			
		||||
#define TARGET_FREEBSD_NR_writev    121
 | 
			
		||||
#define TARGET_FREEBSD_NR_settimeofday  122
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchown    123
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchmod    124
 | 
			
		||||
                /* 125 is old recvfrom */
 | 
			
		||||
#define TARGET_FREEBSD_NR_setreuid  126
 | 
			
		||||
#define TARGET_FREEBSD_NR_setregid  127
 | 
			
		||||
#define TARGET_FREEBSD_NR_rename    128
 | 
			
		||||
                /* 129 is old truncate */
 | 
			
		||||
                /* 130 is old ftruncate */
 | 
			
		||||
#define TARGET_FREEBSD_NR_flock 131
 | 
			
		||||
#define TARGET_FREEBSD_NR_mkfifo    132
 | 
			
		||||
#define TARGET_FREEBSD_NR_sendto    133
 | 
			
		||||
#define TARGET_FREEBSD_NR_shutdown  134
 | 
			
		||||
#define TARGET_FREEBSD_NR_socketpair    135
 | 
			
		||||
#define TARGET_FREEBSD_NR_mkdir 136
 | 
			
		||||
#define TARGET_FREEBSD_NR_rmdir 137
 | 
			
		||||
#define TARGET_FREEBSD_NR_utimes    138
 | 
			
		||||
                /* 139 is obsolete 4.2 sigreturn */
 | 
			
		||||
#define TARGET_FREEBSD_NR_adjtime   140
 | 
			
		||||
                /* 141 is old getpeername */
 | 
			
		||||
                /* 142 is old gethostid */
 | 
			
		||||
                /* 143 is old sethostid */
 | 
			
		||||
                /* 144 is old getrlimit */
 | 
			
		||||
                /* 145 is old setrlimit */
 | 
			
		||||
                /* 146 is old killpg */
 | 
			
		||||
#define TARGET_FREEBSD_NR_killpg    146 /* COMPAT */
 | 
			
		||||
#define TARGET_FREEBSD_NR_setsid    147
 | 
			
		||||
#define TARGET_FREEBSD_NR_quotactl  148
 | 
			
		||||
                /* 149 is old quota */
 | 
			
		||||
                /* 150 is old getsockname */
 | 
			
		||||
#define TARGET_FREEBSD_NR_nlm_syscall   154
 | 
			
		||||
#define TARGET_FREEBSD_NR_nfssvc    155
 | 
			
		||||
                /* 156 is old getdirentries */
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_statfs   157
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_fstatfs  158
 | 
			
		||||
#define TARGET_FREEBSD_NR_lgetfh    160
 | 
			
		||||
#define TARGET_FREEBSD_NR_getfh 161
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_getdomainname    162
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_setdomainname    163
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_uname    164
 | 
			
		||||
#define TARGET_FREEBSD_NR_sysarch   165
 | 
			
		||||
#define TARGET_FREEBSD_NR_rtprio    166
 | 
			
		||||
#define TARGET_FREEBSD_NR_semsys    169
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgsys    170
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmsys    171
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_pread    173
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_pwrite   174
 | 
			
		||||
#define TARGET_FREEBSD_NR_setfib    175
 | 
			
		||||
#define TARGET_FREEBSD_NR_ntp_adjtime   176
 | 
			
		||||
#define TARGET_FREEBSD_NR_setgid    181
 | 
			
		||||
#define TARGET_FREEBSD_NR_setegid   182
 | 
			
		||||
#define TARGET_FREEBSD_NR_seteuid   183
 | 
			
		||||
#define TARGET_FREEBSD_NR_stat  188
 | 
			
		||||
#define TARGET_FREEBSD_NR_fstat 189
 | 
			
		||||
#define TARGET_FREEBSD_NR_lstat 190
 | 
			
		||||
#define TARGET_FREEBSD_NR_pathconf  191
 | 
			
		||||
#define TARGET_FREEBSD_NR_fpathconf 192
 | 
			
		||||
#define TARGET_FREEBSD_NR_getrlimit 194
 | 
			
		||||
#define TARGET_FREEBSD_NR_setrlimit 195
 | 
			
		||||
#define TARGET_FREEBSD_NR_getdirentries 196
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_mmap 197
 | 
			
		||||
#define TARGET_FREEBSD_NR___syscall 198
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_lseek    199
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_truncate 200
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd6_ftruncate    201
 | 
			
		||||
#define TARGET_FREEBSD_NR___sysctl  202
 | 
			
		||||
#define TARGET_FREEBSD_NR_mlock 203
 | 
			
		||||
#define TARGET_FREEBSD_NR_munlock   204
 | 
			
		||||
#define TARGET_FREEBSD_NR_undelete  205
 | 
			
		||||
#define TARGET_FREEBSD_NR_futimes   206
 | 
			
		||||
#define TARGET_FREEBSD_NR_getpgid   207
 | 
			
		||||
#define TARGET_FREEBSD_NR_poll  209
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd7___semctl 220
 | 
			
		||||
#define TARGET_FREEBSD_NR_semget    221
 | 
			
		||||
#define TARGET_FREEBSD_NR_semop 222
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd7_msgctl   224
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgget    225
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgsnd    226
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgrcv    227
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmat 228
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd7_shmctl   229
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmdt 230
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmget    231
 | 
			
		||||
#define TARGET_FREEBSD_NR_clock_gettime 232
 | 
			
		||||
#define TARGET_FREEBSD_NR_clock_settime 233
 | 
			
		||||
#define TARGET_FREEBSD_NR_clock_getres  234
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_create 235
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_delete 236
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_settime    237
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_gettime    238
 | 
			
		||||
#define TARGET_FREEBSD_NR_ktimer_getoverrun 239
 | 
			
		||||
#define TARGET_FREEBSD_NR_nanosleep 240
 | 
			
		||||
#define TARGET_FREEBSD_NR_ntp_gettime   248
 | 
			
		||||
#define TARGET_FREEBSD_NR_minherit  250
 | 
			
		||||
#define TARGET_FREEBSD_NR_rfork 251
 | 
			
		||||
#define TARGET_FREEBSD_NR_openbsd_poll  252
 | 
			
		||||
#define TARGET_FREEBSD_NR_issetugid 253
 | 
			
		||||
#define TARGET_FREEBSD_NR_lchown    254
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_read  255
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_write 256
 | 
			
		||||
#define TARGET_FREEBSD_NR_lio_listio    257
 | 
			
		||||
#define TARGET_FREEBSD_NR_getdents  272
 | 
			
		||||
#define TARGET_FREEBSD_NR_lchmod    274
 | 
			
		||||
#define TARGET_FREEBSD_NR_netbsd_lchown 275
 | 
			
		||||
#define TARGET_FREEBSD_NR_lutimes   276
 | 
			
		||||
#define TARGET_FREEBSD_NR_netbsd_msync  277
 | 
			
		||||
#define TARGET_FREEBSD_NR_nstat 278
 | 
			
		||||
#define TARGET_FREEBSD_NR_nfstat    279
 | 
			
		||||
#define TARGET_FREEBSD_NR_nlstat    280
 | 
			
		||||
#define TARGET_FREEBSD_NR_preadv    289
 | 
			
		||||
#define TARGET_FREEBSD_NR_pwritev   290
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_fhstatfs 297
 | 
			
		||||
#define TARGET_FREEBSD_NR_fhopen    298
 | 
			
		||||
#define TARGET_FREEBSD_NR_fhstat    299
 | 
			
		||||
#define TARGET_FREEBSD_NR_modnext   300
 | 
			
		||||
#define TARGET_FREEBSD_NR_modstat   301
 | 
			
		||||
#define TARGET_FREEBSD_NR_modfnext  302
 | 
			
		||||
#define TARGET_FREEBSD_NR_modfind   303
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldload   304
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldunload 305
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldfind   306
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldnext   307
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldstat   308
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldfirstmod   309
 | 
			
		||||
#define TARGET_FREEBSD_NR_getsid    310
 | 
			
		||||
#define TARGET_FREEBSD_NR_setresuid 311
 | 
			
		||||
#define TARGET_FREEBSD_NR_setresgid 312
 | 
			
		||||
                /* 313 is obsolete signanosleep */
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_return    314
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_suspend   315
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_cancel    316
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_error 317
 | 
			
		||||
#define TARGET_FREEBSD_NR_oaio_read 318
 | 
			
		||||
#define TARGET_FREEBSD_NR_oaio_write    319
 | 
			
		||||
#define TARGET_FREEBSD_NR_olio_listio   320
 | 
			
		||||
#define TARGET_FREEBSD_NR_yield 321
 | 
			
		||||
                /* 322 is obsolete thr_sleep */
 | 
			
		||||
                /* 323 is obsolete thr_wakeup */
 | 
			
		||||
#define TARGET_FREEBSD_NR_mlockall  324
 | 
			
		||||
#define TARGET_FREEBSD_NR_munlockall    325
 | 
			
		||||
#define TARGET_FREEBSD_NR___getcwd  326
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_setparam    327
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_getparam    328
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_setscheduler    329
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_getscheduler    330
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_yield   331
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_get_priority_max    332
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_get_priority_min    333
 | 
			
		||||
#define TARGET_FREEBSD_NR_sched_rr_get_interval 334
 | 
			
		||||
#define TARGET_FREEBSD_NR_utrace    335
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_sendfile 336
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldsym    337
 | 
			
		||||
#define TARGET_FREEBSD_NR_jail  338
 | 
			
		||||
#define TARGET_FREEBSD_NR_nnpfs_syscall 339
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigprocmask   340
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigsuspend    341
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_sigaction    342
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigpending    343
 | 
			
		||||
#define TARGET_FREEBSD_NR_freebsd4_sigreturn    344
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigtimedwait  345
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigwaitinfo   346
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_get_file    347
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_set_file    348
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_get_fd  349
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_set_fd  350
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_delete_file 351
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_delete_fd   352
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_aclcheck_file   353
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_aclcheck_fd 354
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattrctl    355
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_set_file  356
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_get_file  357
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_delete_file   358
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_waitcomplete  359
 | 
			
		||||
#define TARGET_FREEBSD_NR_getresuid 360
 | 
			
		||||
#define TARGET_FREEBSD_NR_getresgid 361
 | 
			
		||||
#define TARGET_FREEBSD_NR_kqueue    362
 | 
			
		||||
#define TARGET_FREEBSD_NR_kevent    363
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_set_fd    371
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_get_fd    372
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_delete_fd 373
 | 
			
		||||
#define TARGET_FREEBSD_NR___setugid 374
 | 
			
		||||
#define TARGET_FREEBSD_NR_eaccess   376
 | 
			
		||||
#define TARGET_FREEBSD_NR_afs3_syscall  377
 | 
			
		||||
#define TARGET_FREEBSD_NR_nmount    378
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_proc    384
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_set_proc    385
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_fd  386
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_file    387
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_set_fd  388
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_set_file    389
 | 
			
		||||
#define TARGET_FREEBSD_NR_kenv  390
 | 
			
		||||
#define TARGET_FREEBSD_NR_lchflags  391
 | 
			
		||||
#define TARGET_FREEBSD_NR_uuidgen   392
 | 
			
		||||
#define TARGET_FREEBSD_NR_sendfile  393
 | 
			
		||||
#define TARGET_FREEBSD_NR_mac_syscall   394
 | 
			
		||||
#define TARGET_FREEBSD_NR_getfsstat 395
 | 
			
		||||
#define TARGET_FREEBSD_NR_statfs    396
 | 
			
		||||
#define TARGET_FREEBSD_NR_fstatfs   397
 | 
			
		||||
#define TARGET_FREEBSD_NR_fhstatfs  398
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_close    400
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_post 401
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_wait 402
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_trywait  403
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_init 404
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_open 405
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_unlink   406
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_getvalue 407
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_destroy  408
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_pid 409
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_get_link    410
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_set_link    411
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_set_link  412
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_get_link  413
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_delete_link   414
 | 
			
		||||
#define TARGET_FREEBSD_NR___mac_execve  415
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigaction 416
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigreturn 417
 | 
			
		||||
#define TARGET_FREEBSD_NR_getcontext    421
 | 
			
		||||
#define TARGET_FREEBSD_NR_setcontext    422
 | 
			
		||||
#define TARGET_FREEBSD_NR_swapcontext   423
 | 
			
		||||
#define TARGET_FREEBSD_NR_swapoff   424
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_get_link    425
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_set_link    426
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_delete_link 427
 | 
			
		||||
#define TARGET_FREEBSD_NR___acl_aclcheck_link   428
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigwait   429
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_create    430
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_exit  431
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_self  432
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_kill  433
 | 
			
		||||
#define TARGET_FREEBSD_NR__umtx_lock    434
 | 
			
		||||
#define TARGET_FREEBSD_NR__umtx_unlock  435
 | 
			
		||||
#define TARGET_FREEBSD_NR_jail_attach   436
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_list_fd   437
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_list_file 438
 | 
			
		||||
#define TARGET_FREEBSD_NR_extattr_list_link 439
 | 
			
		||||
#define TARGET_FREEBSD_NR_ksem_timedwait    441
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_suspend   442
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_wake  443
 | 
			
		||||
#define TARGET_FREEBSD_NR_kldunloadf    444
 | 
			
		||||
#define TARGET_FREEBSD_NR_audit 445
 | 
			
		||||
#define TARGET_FREEBSD_NR_auditon   446
 | 
			
		||||
#define TARGET_FREEBSD_NR_getauid   447
 | 
			
		||||
#define TARGET_FREEBSD_NR_setauid   448
 | 
			
		||||
#define TARGET_FREEBSD_NR_getaudit  449
 | 
			
		||||
#define TARGET_FREEBSD_NR_setaudit  450
 | 
			
		||||
#define TARGET_FREEBSD_NR_getaudit_addr 451
 | 
			
		||||
#define TARGET_FREEBSD_NR_setaudit_addr 452
 | 
			
		||||
#define TARGET_FREEBSD_NR_auditctl  453
 | 
			
		||||
#define TARGET_FREEBSD_NR__umtx_op  454
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_new   455
 | 
			
		||||
#define TARGET_FREEBSD_NR_sigqueue  456
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_open  457
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_setattr   458
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_timedreceive  459
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_timedsend 460
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_notify    461
 | 
			
		||||
#define TARGET_FREEBSD_NR_kmq_unlink    462
 | 
			
		||||
#define TARGET_FREEBSD_NR_abort2    463
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_set_name  464
 | 
			
		||||
#define TARGET_FREEBSD_NR_aio_fsync 465
 | 
			
		||||
#define TARGET_FREEBSD_NR_rtprio_thread 466
 | 
			
		||||
#define TARGET_FREEBSD_NR_sctp_peeloff  471
 | 
			
		||||
#define TARGET_FREEBSD_NR_sctp_generic_sendmsg  472
 | 
			
		||||
#define TARGET_FREEBSD_NR_sctp_generic_sendmsg_iov  473
 | 
			
		||||
#define TARGET_FREEBSD_NR_sctp_generic_recvmsg  474
 | 
			
		||||
#define TARGET_FREEBSD_NR_pread 475
 | 
			
		||||
#define TARGET_FREEBSD_NR_pwrite    476
 | 
			
		||||
#define TARGET_FREEBSD_NR_mmap  477
 | 
			
		||||
#define TARGET_FREEBSD_NR_lseek 478
 | 
			
		||||
#define TARGET_FREEBSD_NR_truncate  479
 | 
			
		||||
#define TARGET_FREEBSD_NR_ftruncate 480
 | 
			
		||||
#define TARGET_FREEBSD_NR_thr_kill2 481
 | 
			
		||||
#define TARGET_FREEBSD_NR_shm_open  482
 | 
			
		||||
#define TARGET_FREEBSD_NR_shm_unlink    483
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset    484
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset_setid  485
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset_getid  486
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset_getaffinity    487
 | 
			
		||||
#define TARGET_FREEBSD_NR_cpuset_setaffinity    488
 | 
			
		||||
#define TARGET_FREEBSD_NR_faccessat 489
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchmodat  490
 | 
			
		||||
#define TARGET_FREEBSD_NR_fchownat  491
 | 
			
		||||
#define TARGET_FREEBSD_NR_fexecve   492
 | 
			
		||||
#define TARGET_FREEBSD_NR_fstatat   493
 | 
			
		||||
#define TARGET_FREEBSD_NR_futimesat 494
 | 
			
		||||
#define TARGET_FREEBSD_NR_linkat    495
 | 
			
		||||
#define TARGET_FREEBSD_NR_mkdirat   496
 | 
			
		||||
#define TARGET_FREEBSD_NR_mkfifoat  497
 | 
			
		||||
#define TARGET_FREEBSD_NR_mknodat   498
 | 
			
		||||
#define TARGET_FREEBSD_NR_openat    499
 | 
			
		||||
#define TARGET_FREEBSD_NR_readlinkat    500
 | 
			
		||||
#define TARGET_FREEBSD_NR_renameat  501
 | 
			
		||||
#define TARGET_FREEBSD_NR_symlinkat 502
 | 
			
		||||
#define TARGET_FREEBSD_NR_unlinkat  503
 | 
			
		||||
#define TARGET_FREEBSD_NR_posix_openpt  504
 | 
			
		||||
#define TARGET_FREEBSD_NR_gssd_syscall  505
 | 
			
		||||
#define TARGET_FREEBSD_NR_jail_get  506
 | 
			
		||||
#define TARGET_FREEBSD_NR_jail_set  507
 | 
			
		||||
#define TARGET_FREEBSD_NR_jail_remove   508
 | 
			
		||||
#define TARGET_FREEBSD_NR_closefrom 509
 | 
			
		||||
#define TARGET_FREEBSD_NR___semctl  510
 | 
			
		||||
#define TARGET_FREEBSD_NR_msgctl    511
 | 
			
		||||
#define TARGET_FREEBSD_NR_shmctl    512
 | 
			
		||||
#define TARGET_FREEBSD_NR_lpathconf 513
 | 
			
		||||
#define TARGET_FREEBSD_NR_cap_new   514
 | 
			
		||||
#define TARGET_FREEBSD_NR_cap_getrights 515
 | 
			
		||||
#define TARGET_FREEBSD_NR_cap_enter 516
 | 
			
		||||
#define TARGET_FREEBSD_NR_cap_getmode   517
 | 
			
		||||
#define TARGET_FREEBSD_NR_pdfork    518
 | 
			
		||||
#define TARGET_FREEBSD_NR_pdkill    519
 | 
			
		||||
#define TARGET_FREEBSD_NR_pdgetpid  520
 | 
			
		||||
#define TARGET_FREEBSD_NR_pselect   522
 | 
			
		||||
#define TARGET_FREEBSD_NR_getloginclass 523
 | 
			
		||||
#define TARGET_FREEBSD_NR_setloginclass 524
 | 
			
		||||
#define TARGET_FREEBSD_NR_rctl_get_racct    525
 | 
			
		||||
#define TARGET_FREEBSD_NR_rctl_get_rules    526
 | 
			
		||||
#define TARGET_FREEBSD_NR_rctl_get_limits   527
 | 
			
		||||
#define TARGET_FREEBSD_NR_rctl_add_rule 528
 | 
			
		||||
#define TARGET_FREEBSD_NR_rctl_remove_rule  529
 | 
			
		||||
#define TARGET_FREEBSD_NR_posix_fallocate   530
 | 
			
		||||
#define TARGET_FREEBSD_NR_posix_fadvise 531
 | 
			
		||||
#define TARGET_FREEBSD_NR_MAXSYSCALL    532
 | 
			
		||||
 
 | 
			
		||||
@@ -1004,7 +1004,7 @@ int main(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_I386)
 | 
			
		||||
    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
 | 
			
		||||
    env->hflags |= HF_PE_MASK;
 | 
			
		||||
    env->hflags |= HF_PE_MASK | HF_CPL_MASK;
 | 
			
		||||
    if (env->features[FEAT_1_EDX] & CPUID_SSE) {
 | 
			
		||||
        env->cr[4] |= CR4_OSFXSR_MASK;
 | 
			
		||||
        env->hflags |= HF_OSFXSR_MASK;
 | 
			
		||||
 
 | 
			
		||||
@@ -74,66 +74,6 @@ void mmap_unlock(void)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void *bsd_vmalloc(size_t size)
 | 
			
		||||
{
 | 
			
		||||
    void *p;
 | 
			
		||||
    mmap_lock();
 | 
			
		||||
    /* Use map and mark the pages as used.  */
 | 
			
		||||
    p = mmap(NULL, size, PROT_READ | PROT_WRITE,
 | 
			
		||||
             MAP_PRIVATE | MAP_ANON, -1, 0);
 | 
			
		||||
 | 
			
		||||
    if (h2g_valid(p)) {
 | 
			
		||||
        /* Allocated region overlaps guest address space.
 | 
			
		||||
           This may recurse.  */
 | 
			
		||||
        abi_ulong addr = h2g(p);
 | 
			
		||||
        page_set_flags(addr & TARGET_PAGE_MASK, TARGET_PAGE_ALIGN(addr + size),
 | 
			
		||||
                       PAGE_RESERVED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mmap_unlock();
 | 
			
		||||
    return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *g_malloc(size_t size)
 | 
			
		||||
{
 | 
			
		||||
    char * p;
 | 
			
		||||
    size += 16;
 | 
			
		||||
    p = bsd_vmalloc(size);
 | 
			
		||||
    *(size_t *)p = size;
 | 
			
		||||
    return p + 16;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* We use map, which is always zero initialized.  */
 | 
			
		||||
void * g_malloc0(size_t size)
 | 
			
		||||
{
 | 
			
		||||
    return g_malloc(size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void g_free(void *ptr)
 | 
			
		||||
{
 | 
			
		||||
    /* FIXME: We should unmark the reserved pages here.  However this gets
 | 
			
		||||
       complicated when one target page spans multiple host pages, so we
 | 
			
		||||
       don't bother.  */
 | 
			
		||||
    size_t *p;
 | 
			
		||||
    p = (size_t *)((char *)ptr - 16);
 | 
			
		||||
    munmap(p, *p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *g_realloc(void *ptr, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    size_t old_size, copy;
 | 
			
		||||
    void *new_ptr;
 | 
			
		||||
 | 
			
		||||
    if (!ptr)
 | 
			
		||||
        return g_malloc(size);
 | 
			
		||||
    old_size = *(size_t *)((char *)ptr - 16);
 | 
			
		||||
    copy = old_size < size ? old_size : size;
 | 
			
		||||
    new_ptr = g_malloc(size);
 | 
			
		||||
    memcpy(new_ptr, ptr, copy);
 | 
			
		||||
    g_free(ptr);
 | 
			
		||||
    return new_ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* NOTE: all the constants are the HOST ones, but addresses are target. */
 | 
			
		||||
int target_mprotect(abi_ulong start, abi_ulong len, int prot)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,19 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  qemu bsd user mode definition
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 *  (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef QEMU_H
 | 
			
		||||
#define QEMU_H
 | 
			
		||||
 | 
			
		||||
@@ -5,6 +21,7 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "exec/cpu_ldst.h"
 | 
			
		||||
 | 
			
		||||
#undef DEBUG_REMAP
 | 
			
		||||
#ifdef DEBUG_REMAP
 | 
			
		||||
@@ -149,6 +166,16 @@ void fork_end(int child);
 | 
			
		||||
#include "qemu/log.h"
 | 
			
		||||
 | 
			
		||||
/* strace.c */
 | 
			
		||||
struct syscallname {
 | 
			
		||||
    int nr;
 | 
			
		||||
    const char *name;
 | 
			
		||||
    const char *format;
 | 
			
		||||
    void (*call)(const struct syscallname *,
 | 
			
		||||
                 abi_long, abi_long, abi_long,
 | 
			
		||||
                 abi_long, abi_long, abi_long);
 | 
			
		||||
    void (*result)(const struct syscallname *, abi_long);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
print_freebsd_syscall(int num,
 | 
			
		||||
                      abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,37 +1,71 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  System call tracing and debugging
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 *  (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <sys/select.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <sys/ioccom.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
#include "qemu.h"
 | 
			
		||||
 | 
			
		||||
int do_strace=0;
 | 
			
		||||
 | 
			
		||||
struct syscallname {
 | 
			
		||||
    int nr;
 | 
			
		||||
    const char *name;
 | 
			
		||||
    const char *format;
 | 
			
		||||
    void (*call)(const struct syscallname *,
 | 
			
		||||
                 abi_long, abi_long, abi_long,
 | 
			
		||||
                 abi_long, abi_long, abi_long);
 | 
			
		||||
    void (*result)(const struct syscallname *, abi_long);
 | 
			
		||||
};
 | 
			
		||||
int do_strace;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Utility functions
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
print_execve(const struct syscallname *name,
 | 
			
		||||
             abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
             abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
static void print_sysctl(const struct syscallname *name, abi_long arg1,
 | 
			
		||||
        abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
 | 
			
		||||
        abi_long arg6)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
    int32_t *namep;
 | 
			
		||||
 | 
			
		||||
    gemu_log("%s({ ", name->name);
 | 
			
		||||
    namep = lock_user(VERIFY_READ, arg1, sizeof(int32_t) * arg2, 1);
 | 
			
		||||
    if (namep) {
 | 
			
		||||
        int32_t *p = namep;
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < (uint32_t)arg2; i++) {
 | 
			
		||||
            gemu_log("%d ", tswap32(*p++));
 | 
			
		||||
        }
 | 
			
		||||
        unlock_user(namep, arg1, 0);
 | 
			
		||||
    }
 | 
			
		||||
    gemu_log("}, %u, 0x" TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ", 0x"
 | 
			
		||||
        TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ")",
 | 
			
		||||
        (uint32_t)arg2, arg3, arg4, arg5, arg6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void print_execve(const struct syscallname *name, abi_long arg1,
 | 
			
		||||
        abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
 | 
			
		||||
        abi_long arg6)
 | 
			
		||||
{
 | 
			
		||||
    abi_ulong arg_ptr_addr;
 | 
			
		||||
    char *s;
 | 
			
		||||
 | 
			
		||||
    if (!(s = lock_user_string(arg1)))
 | 
			
		||||
    s = lock_user_string(arg1);
 | 
			
		||||
    if (s == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    gemu_log("%s(\"%s\",{", name->name, s);
 | 
			
		||||
    unlock_user(s, arg1, 0);
 | 
			
		||||
 | 
			
		||||
@@ -39,29 +73,48 @@ print_execve(const struct syscallname *name,
 | 
			
		||||
        abi_ulong *arg_ptr, arg_addr;
 | 
			
		||||
 | 
			
		||||
        arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
 | 
			
		||||
        if (!arg_ptr)
 | 
			
		||||
        if (!arg_ptr) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        arg_addr = tswapl(*arg_ptr);
 | 
			
		||||
        unlock_user(arg_ptr, arg_ptr_addr, 0);
 | 
			
		||||
        if (!arg_addr)
 | 
			
		||||
        if (!arg_addr) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if ((s = lock_user_string(arg_addr))) {
 | 
			
		||||
            gemu_log("\"%s\",", s);
 | 
			
		||||
            unlock_user(s, arg_addr, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gemu_log("NULL})");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void print_ioctl(const struct syscallname *name,
 | 
			
		||||
        abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4,
 | 
			
		||||
        abi_long arg5, abi_long arg6)
 | 
			
		||||
{
 | 
			
		||||
    /* Decode the ioctl request */
 | 
			
		||||
    gemu_log("%s(%d, 0x%0lx { IO%s%s GRP:0x%x('%c') CMD:%d LEN:%d }, 0x"
 | 
			
		||||
            TARGET_ABI_FMT_lx ", ...)",
 | 
			
		||||
            name->name,
 | 
			
		||||
            (int)arg1,
 | 
			
		||||
            (unsigned long)arg2,
 | 
			
		||||
            arg2 & IOC_OUT ? "R" : "",
 | 
			
		||||
            arg2 & IOC_IN ? "W" : "",
 | 
			
		||||
            (unsigned)IOCGROUP(arg2),
 | 
			
		||||
            isprint(IOCGROUP(arg2)) ? (char)IOCGROUP(arg2) : '?',
 | 
			
		||||
            (int)arg2 & 0xFF,
 | 
			
		||||
            (int)IOCPARM_LEN(arg2),
 | 
			
		||||
            arg3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Variants for the return value output function
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
 | 
			
		||||
static void print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
 | 
			
		||||
{
 | 
			
		||||
if( ret == -1 ) {
 | 
			
		||||
    if (ret == -1) {
 | 
			
		||||
        gemu_log(" = -1 errno=%d (%s)\n", errno, strerror(errno));
 | 
			
		||||
    } else {
 | 
			
		||||
        gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
 | 
			
		||||
@@ -90,10 +143,9 @@ static const struct syscallname openbsd_scnames[] = {
 | 
			
		||||
#include "openbsd/strace.list"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
print_syscall(int num, const struct syscallname *scnames, unsigned int nscnames,
 | 
			
		||||
              abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
              abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
static void print_syscall(int num, const struct syscallname *scnames,
 | 
			
		||||
        unsigned int nscnames, abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
        abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int i;
 | 
			
		||||
    const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ","
 | 
			
		||||
@@ -102,36 +154,37 @@ print_syscall(int num, const struct syscallname *scnames, unsigned int nscnames,
 | 
			
		||||
 | 
			
		||||
    gemu_log("%d ", getpid() );
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < nscnames; i++)
 | 
			
		||||
    for (i = 0; i < nscnames; i++) {
 | 
			
		||||
        if (scnames[i].nr == num) {
 | 
			
		||||
            if (scnames[i].call != NULL) {
 | 
			
		||||
                scnames[i].call(&scnames[i], arg1, arg2, arg3, arg4, arg5,
 | 
			
		||||
                                arg6);
 | 
			
		||||
                        arg6);
 | 
			
		||||
            } else {
 | 
			
		||||
                /* XXX: this format system is broken because it uses
 | 
			
		||||
                   host types and host pointers for strings */
 | 
			
		||||
                if (scnames[i].format != NULL)
 | 
			
		||||
                if (scnames[i].format != NULL) {
 | 
			
		||||
                    format = scnames[i].format;
 | 
			
		||||
                gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4,
 | 
			
		||||
                         arg5, arg6);
 | 
			
		||||
                }
 | 
			
		||||
                gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4, arg5,
 | 
			
		||||
                        arg6);
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    gemu_log("Unknown syscall %d\n", num);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
print_syscall_ret(int num, abi_long ret, const struct syscallname *scnames,
 | 
			
		||||
                  unsigned int nscnames)
 | 
			
		||||
static void print_syscall_ret(int num, abi_long ret,
 | 
			
		||||
        const struct syscallname *scnames, unsigned int nscnames)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < nscnames; i++)
 | 
			
		||||
    for (i = 0; i < nscnames; i++) {
 | 
			
		||||
        if (scnames[i].nr == num) {
 | 
			
		||||
            if (scnames[i].result != NULL) {
 | 
			
		||||
                scnames[i].result(&scnames[i], ret);
 | 
			
		||||
            } else {
 | 
			
		||||
                if( ret < 0 ) {
 | 
			
		||||
                if (ret < 0) {
 | 
			
		||||
                    gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret,
 | 
			
		||||
                             strerror(-ret));
 | 
			
		||||
                } else {
 | 
			
		||||
@@ -140,52 +193,50 @@ print_syscall_ret(int num, abi_long ret, const struct syscallname *scnames,
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The public interface to this module.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
print_freebsd_syscall(int num,
 | 
			
		||||
                      abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
                      abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
void print_freebsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
        abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
{
 | 
			
		||||
    print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames),
 | 
			
		||||
                  arg1, arg2, arg3, arg4, arg5, arg6);
 | 
			
		||||
 | 
			
		||||
    print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames), arg1, arg2,
 | 
			
		||||
            arg3, arg4, arg5, arg6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
print_freebsd_syscall_ret(int num, abi_long ret)
 | 
			
		||||
void print_freebsd_syscall_ret(int num, abi_long ret)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    print_syscall_ret(num, ret, freebsd_scnames, ARRAY_SIZE(freebsd_scnames));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
print_netbsd_syscall(int num,
 | 
			
		||||
                      abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
                      abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
void print_netbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
        abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    print_syscall(num, netbsd_scnames, ARRAY_SIZE(netbsd_scnames),
 | 
			
		||||
                  arg1, arg2, arg3, arg4, arg5, arg6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
print_netbsd_syscall_ret(int num, abi_long ret)
 | 
			
		||||
void print_netbsd_syscall_ret(int num, abi_long ret)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    print_syscall_ret(num, ret, netbsd_scnames, ARRAY_SIZE(netbsd_scnames));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
print_openbsd_syscall(int num,
 | 
			
		||||
                      abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
                      abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
void print_openbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
 | 
			
		||||
        abi_long arg4, abi_long arg5, abi_long arg6)
 | 
			
		||||
{
 | 
			
		||||
    print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames),
 | 
			
		||||
                  arg1, arg2, arg3, arg4, arg5, arg6);
 | 
			
		||||
 | 
			
		||||
    print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames), arg1, arg2,
 | 
			
		||||
            arg3, arg4, arg5, arg6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
print_openbsd_syscall_ret(int num, abi_long ret)
 | 
			
		||||
void print_openbsd_syscall_ret(int num, abi_long ret)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										73
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@@ -3,6 +3,11 @@
 | 
			
		||||
# qemu configure script (c) 2003 Fabrice Bellard
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# Unset some variables known to interfere with behavior of common tools,
 | 
			
		||||
# just as autoconf does.
 | 
			
		||||
CLICOLOR_FORCE= GREP_OPTIONS=
 | 
			
		||||
unset CLICOLOR_FORCE GREP_OPTIONS
 | 
			
		||||
 | 
			
		||||
# Temporary directory used for files created while
 | 
			
		||||
# configure runs. Since it is in the build directory
 | 
			
		||||
# we can safely blow away any previous version of it
 | 
			
		||||
@@ -182,6 +187,10 @@ path_of() {
 | 
			
		||||
    return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
have_backend () {
 | 
			
		||||
    echo "$trace_backends" | grep "$1" >/dev/null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# default parameters
 | 
			
		||||
source_path=`dirname "$0"`
 | 
			
		||||
cpu=""
 | 
			
		||||
@@ -293,7 +302,7 @@ pkgversion=""
 | 
			
		||||
pie=""
 | 
			
		||||
zero_malloc=""
 | 
			
		||||
qom_cast_debug="yes"
 | 
			
		||||
trace_backend="nop"
 | 
			
		||||
trace_backends="nop"
 | 
			
		||||
trace_file="trace"
 | 
			
		||||
spice=""
 | 
			
		||||
rbd=""
 | 
			
		||||
@@ -537,6 +546,9 @@ fi
 | 
			
		||||
 | 
			
		||||
# OS specific
 | 
			
		||||
 | 
			
		||||
# host *BSD for user mode
 | 
			
		||||
HOST_VARIANT_DIR=""
 | 
			
		||||
 | 
			
		||||
case $targetos in
 | 
			
		||||
CYGWIN*)
 | 
			
		||||
  mingw32="yes"
 | 
			
		||||
@@ -562,12 +574,14 @@ FreeBSD)
 | 
			
		||||
  # needed for kinfo_getvmmap(3) in libutil.h
 | 
			
		||||
  LIBS="-lutil $LIBS"
 | 
			
		||||
  netmap=""  # enable netmap autodetect
 | 
			
		||||
  HOST_VARIANT_DIR="freebsd"
 | 
			
		||||
;;
 | 
			
		||||
DragonFly)
 | 
			
		||||
  bsd="yes"
 | 
			
		||||
  make="${MAKE-gmake}"
 | 
			
		||||
  audio_drv_list="oss"
 | 
			
		||||
  audio_possible_drivers="oss sdl esd pa"
 | 
			
		||||
  HOST_VARIANT_DIR="dragonfly"
 | 
			
		||||
;;
 | 
			
		||||
NetBSD)
 | 
			
		||||
  bsd="yes"
 | 
			
		||||
@@ -575,12 +589,14 @@ NetBSD)
 | 
			
		||||
  audio_drv_list="oss"
 | 
			
		||||
  audio_possible_drivers="oss sdl esd"
 | 
			
		||||
  oss_lib="-lossaudio"
 | 
			
		||||
  HOST_VARIANT_DIR="netbsd"
 | 
			
		||||
;;
 | 
			
		||||
OpenBSD)
 | 
			
		||||
  bsd="yes"
 | 
			
		||||
  make="${MAKE-gmake}"
 | 
			
		||||
  audio_drv_list="sdl"
 | 
			
		||||
  audio_possible_drivers="sdl esd"
 | 
			
		||||
  HOST_VARIANT_DIR="openbsd"
 | 
			
		||||
;;
 | 
			
		||||
Darwin)
 | 
			
		||||
  bsd="yes"
 | 
			
		||||
@@ -598,6 +614,7 @@ Darwin)
 | 
			
		||||
  # Disable attempts to use ObjectiveC features in os/object.h since they
 | 
			
		||||
  # won't work when we're compiling with gcc as a C compiler.
 | 
			
		||||
  QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
 | 
			
		||||
  HOST_VARIANT_DIR="darwin"
 | 
			
		||||
;;
 | 
			
		||||
SunOS)
 | 
			
		||||
  solaris="yes"
 | 
			
		||||
@@ -753,7 +770,10 @@ for opt do
 | 
			
		||||
  ;;
 | 
			
		||||
  --target-list=*) target_list="$optarg"
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-trace-backend=*) trace_backend="$optarg"
 | 
			
		||||
  --enable-trace-backends=*) trace_backends="$optarg"
 | 
			
		||||
  ;;
 | 
			
		||||
  # XXX: backwards compatibility
 | 
			
		||||
  --enable-trace-backend=*) trace_backends="$optarg"
 | 
			
		||||
  ;;
 | 
			
		||||
  --with-trace-file=*) trace_file="$optarg"
 | 
			
		||||
  ;;
 | 
			
		||||
@@ -1320,7 +1340,7 @@ Advanced options (experts only):
 | 
			
		||||
  --disable-docs           disable documentation build
 | 
			
		||||
  --disable-vhost-net      disable vhost-net acceleration support
 | 
			
		||||
  --enable-vhost-net       enable vhost-net acceleration support
 | 
			
		||||
  --enable-trace-backend=B Set trace backend
 | 
			
		||||
  --enable-trace-backends=B Set trace backend
 | 
			
		||||
                           Available backends: $($python $source_path/scripts/tracetool.py --list-backends)
 | 
			
		||||
  --with-trace-file=NAME   Full PATH,NAME of file to store traces
 | 
			
		||||
                           Default:trace-<pid>
 | 
			
		||||
@@ -1986,6 +2006,7 @@ fi
 | 
			
		||||
 | 
			
		||||
if test "$gtk" != "no"; then
 | 
			
		||||
    gtkpackage="gtk+-$gtkabi"
 | 
			
		||||
    gtkx11package="gtk+-x11-$gtkabi"
 | 
			
		||||
    if test "$gtkabi" = "3.0" ; then
 | 
			
		||||
      gtkversion="3.0.0"
 | 
			
		||||
    else
 | 
			
		||||
@@ -1994,6 +2015,9 @@ if test "$gtk" != "no"; then
 | 
			
		||||
    if $pkg_config --exists "$gtkpackage >= $gtkversion"; then
 | 
			
		||||
        gtk_cflags=`$pkg_config --cflags $gtkpackage`
 | 
			
		||||
        gtk_libs=`$pkg_config --libs $gtkpackage`
 | 
			
		||||
        if $pkg_config --exists "$gtkx11package >= $gtkversion"; then
 | 
			
		||||
            gtk_libs="$gtk_libs -lX11"
 | 
			
		||||
        fi
 | 
			
		||||
        libs_softmmu="$gtk_libs $libs_softmmu"
 | 
			
		||||
        gtk="yes"
 | 
			
		||||
    elif test "$gtk" = "yes"; then
 | 
			
		||||
@@ -3445,9 +3469,9 @@ EOF
 | 
			
		||||
if compile_prog "" "" ; then
 | 
			
		||||
  :
 | 
			
		||||
# we need pthread for static linking. use previous pthread test result
 | 
			
		||||
elif compile_prog "" "-lrt $pthread_lib" ; then
 | 
			
		||||
  LIBS="-lrt $LIBS"
 | 
			
		||||
  libs_qga="-lrt $libs_qga"
 | 
			
		||||
elif compile_prog "" "$pthread_lib -lrt" ; then
 | 
			
		||||
  LIBS="$LIBS -lrt"
 | 
			
		||||
  libs_qga="$libs_qga -lrt"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \
 | 
			
		||||
@@ -3666,15 +3690,15 @@ fi
 | 
			
		||||
##########################################
 | 
			
		||||
# check if trace backend exists
 | 
			
		||||
 | 
			
		||||
$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend  > /dev/null 2> /dev/null
 | 
			
		||||
$python "$source_path/scripts/tracetool.py" "--backends=$trace_backends" --check-backends  > /dev/null 2> /dev/null
 | 
			
		||||
if test "$?" -ne 0 ; then
 | 
			
		||||
  error_exit "invalid trace backend" \
 | 
			
		||||
      "Please choose a supported trace backend."
 | 
			
		||||
  error_exit "invalid trace backends" \
 | 
			
		||||
      "Please choose supported trace backends."
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# For 'ust' backend, test if ust headers are present
 | 
			
		||||
if test "$trace_backend" = "ust"; then
 | 
			
		||||
if have_backend "ust"; then
 | 
			
		||||
  cat > $TMPC << EOF
 | 
			
		||||
#include <lttng/tracepoint.h>
 | 
			
		||||
int main(void) { return 0; }
 | 
			
		||||
@@ -3700,7 +3724,7 @@ fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# For 'dtrace' backend, test if 'dtrace' command is present
 | 
			
		||||
if test "$trace_backend" = "dtrace"; then
 | 
			
		||||
if have_backend "dtrace"; then
 | 
			
		||||
  if ! has 'dtrace' ; then
 | 
			
		||||
    error_exit "dtrace command is not found in PATH $PATH"
 | 
			
		||||
  fi
 | 
			
		||||
@@ -4170,7 +4194,7 @@ echo "uuid support      $uuid"
 | 
			
		||||
echo "libcap-ng support $cap_ng"
 | 
			
		||||
echo "vhost-net support $vhost_net"
 | 
			
		||||
echo "vhost-scsi support $vhost_scsi"
 | 
			
		||||
echo "Trace backend     $trace_backend"
 | 
			
		||||
echo "Trace backends    $trace_backends"
 | 
			
		||||
if test "$trace_backend" = "simple"; then
 | 
			
		||||
echo "Trace output file $trace_file-<pid>"
 | 
			
		||||
fi
 | 
			
		||||
@@ -4664,43 +4688,35 @@ if test "$tpm" = "yes"; then
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# use default implementation for tracing backend-specific routines
 | 
			
		||||
trace_default=yes
 | 
			
		||||
echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
 | 
			
		||||
if test "$trace_backend" = "nop"; then
 | 
			
		||||
echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
 | 
			
		||||
if have_backend "nop"; then
 | 
			
		||||
  echo "CONFIG_TRACE_NOP=y" >> $config_host_mak
 | 
			
		||||
fi
 | 
			
		||||
if test "$trace_backend" = "simple"; then
 | 
			
		||||
if have_backend "simple"; then
 | 
			
		||||
  echo "CONFIG_TRACE_SIMPLE=y" >> $config_host_mak
 | 
			
		||||
  trace_default=no
 | 
			
		||||
  # Set the appropriate trace file.
 | 
			
		||||
  trace_file="\"$trace_file-\" FMT_pid"
 | 
			
		||||
fi
 | 
			
		||||
if test "$trace_backend" = "stderr"; then
 | 
			
		||||
if have_backend "stderr"; then
 | 
			
		||||
  echo "CONFIG_TRACE_STDERR=y" >> $config_host_mak
 | 
			
		||||
  trace_default=no
 | 
			
		||||
fi
 | 
			
		||||
if test "$trace_backend" = "ust"; then
 | 
			
		||||
if have_backend "ust"; then
 | 
			
		||||
  echo "CONFIG_TRACE_UST=y" >> $config_host_mak
 | 
			
		||||
fi
 | 
			
		||||
if test "$trace_backend" = "dtrace"; then
 | 
			
		||||
if have_backend "dtrace"; then
 | 
			
		||||
  echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak
 | 
			
		||||
  if test "$trace_backend_stap" = "yes" ; then
 | 
			
		||||
    echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
if test "$trace_backend" = "ftrace"; then
 | 
			
		||||
if have_backend "ftrace"; then
 | 
			
		||||
  if test "$linux" = "yes" ; then
 | 
			
		||||
    echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak
 | 
			
		||||
    trace_default=no
 | 
			
		||||
  else
 | 
			
		||||
    feature_not_found "ftrace(trace backend)" "ftrace requires Linux"
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
 | 
			
		||||
if test "$trace_default" = "yes"; then
 | 
			
		||||
  echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test "$rdma" = "yes" ; then
 | 
			
		||||
  echo "CONFIG_RDMA=y" >> $config_host_mak
 | 
			
		||||
@@ -4982,6 +4998,9 @@ if [ "$TARGET_ABI_DIR" = "" ]; then
 | 
			
		||||
  TARGET_ABI_DIR=$TARGET_ARCH
 | 
			
		||||
fi
 | 
			
		||||
echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak
 | 
			
		||||
if [ "$HOST_VARIANT_DIR" != "" ]; then
 | 
			
		||||
    echo "HOST_VARIANT_DIR=$HOST_VARIANT_DIR" >> $config_target_mak
 | 
			
		||||
fi
 | 
			
		||||
case "$target_name" in
 | 
			
		||||
  i386|x86_64)
 | 
			
		||||
    if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
 | 
			
		||||
 
 | 
			
		||||
@@ -30,20 +30,14 @@ typedef struct {
 | 
			
		||||
    CoroutineAction action;
 | 
			
		||||
} CoroutineGThread;
 | 
			
		||||
 | 
			
		||||
static GStaticMutex coroutine_lock = G_STATIC_MUTEX_INIT;
 | 
			
		||||
static CompatGMutex coroutine_lock;
 | 
			
		||||
static CompatGCond coroutine_cond;
 | 
			
		||||
 | 
			
		||||
/* GLib 2.31 and beyond deprecated various parts of the thread API,
 | 
			
		||||
 * but the new interfaces are not available in older GLib versions
 | 
			
		||||
 * so we have to cope with both.
 | 
			
		||||
 */
 | 
			
		||||
#if GLIB_CHECK_VERSION(2, 31, 0)
 | 
			
		||||
/* Default zero-initialisation is sufficient for 2.31+ GCond */
 | 
			
		||||
static GCond the_coroutine_cond;
 | 
			
		||||
static GCond *coroutine_cond = &the_coroutine_cond;
 | 
			
		||||
static inline void init_coroutine_cond(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Awkwardly, the GPrivate API doesn't provide a way to update the
 | 
			
		||||
 * GDestroyNotify handler for the coroutine key dynamically. So instead
 | 
			
		||||
 * we track whether or not the CoroutineGThread should be freed on
 | 
			
		||||
@@ -84,11 +78,6 @@ static inline GThread *create_thread(GThreadFunc func, gpointer data)
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
/* Handle older GLib versions */
 | 
			
		||||
static GCond *coroutine_cond;
 | 
			
		||||
static inline void init_coroutine_cond(void)
 | 
			
		||||
{
 | 
			
		||||
    coroutine_cond = g_cond_new();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
 | 
			
		||||
 | 
			
		||||
@@ -120,22 +109,20 @@ static void __attribute__((constructor)) coroutine_init(void)
 | 
			
		||||
        g_thread_init(NULL);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    init_coroutine_cond();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void coroutine_wait_runnable_locked(CoroutineGThread *co)
 | 
			
		||||
{
 | 
			
		||||
    while (!co->runnable) {
 | 
			
		||||
        g_cond_wait(coroutine_cond, g_static_mutex_get_mutex(&coroutine_lock));
 | 
			
		||||
        g_cond_wait(&coroutine_cond, &coroutine_lock);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void coroutine_wait_runnable(CoroutineGThread *co)
 | 
			
		||||
{
 | 
			
		||||
    g_static_mutex_lock(&coroutine_lock);
 | 
			
		||||
    g_mutex_lock(&coroutine_lock);
 | 
			
		||||
    coroutine_wait_runnable_locked(co);
 | 
			
		||||
    g_static_mutex_unlock(&coroutine_lock);
 | 
			
		||||
    g_mutex_unlock(&coroutine_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gpointer coroutine_thread(gpointer opaque)
 | 
			
		||||
@@ -177,17 +164,17 @@ CoroutineAction qemu_coroutine_switch(Coroutine *from_,
 | 
			
		||||
    CoroutineGThread *from = DO_UPCAST(CoroutineGThread, base, from_);
 | 
			
		||||
    CoroutineGThread *to = DO_UPCAST(CoroutineGThread, base, to_);
 | 
			
		||||
 | 
			
		||||
    g_static_mutex_lock(&coroutine_lock);
 | 
			
		||||
    g_mutex_lock(&coroutine_lock);
 | 
			
		||||
    from->runnable = false;
 | 
			
		||||
    from->action = action;
 | 
			
		||||
    to->runnable = true;
 | 
			
		||||
    to->action = action;
 | 
			
		||||
    g_cond_broadcast(coroutine_cond);
 | 
			
		||||
    g_cond_broadcast(&coroutine_cond);
 | 
			
		||||
 | 
			
		||||
    if (action != COROUTINE_TERMINATE) {
 | 
			
		||||
        coroutine_wait_runnable_locked(from);
 | 
			
		||||
    }
 | 
			
		||||
    g_static_mutex_unlock(&coroutine_lock);
 | 
			
		||||
    g_mutex_unlock(&coroutine_lock);
 | 
			
		||||
    return from->action;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								cputlb.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								cputlb.c
									
									
									
									
									
								
							@@ -22,11 +22,13 @@
 | 
			
		||||
#include "exec/exec-all.h"
 | 
			
		||||
#include "exec/memory.h"
 | 
			
		||||
#include "exec/address-spaces.h"
 | 
			
		||||
#include "exec/cpu_ldst.h"
 | 
			
		||||
 | 
			
		||||
#include "exec/cputlb.h"
 | 
			
		||||
 | 
			
		||||
#include "exec/memory-internal.h"
 | 
			
		||||
#include "exec/ram_addr.h"
 | 
			
		||||
#include "tcg/tcg.h"
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_TLB
 | 
			
		||||
//#define DEBUG_TLB_CHECK
 | 
			
		||||
@@ -330,21 +332,36 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
 | 
			
		||||
    return qemu_ram_addr_from_host_nofail(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MMUSUFFIX _mmu
 | 
			
		||||
 | 
			
		||||
#define SHIFT 0
 | 
			
		||||
#include "softmmu_template.h"
 | 
			
		||||
 | 
			
		||||
#define SHIFT 1
 | 
			
		||||
#include "softmmu_template.h"
 | 
			
		||||
 | 
			
		||||
#define SHIFT 2
 | 
			
		||||
#include "softmmu_template.h"
 | 
			
		||||
 | 
			
		||||
#define SHIFT 3
 | 
			
		||||
#include "softmmu_template.h"
 | 
			
		||||
#undef MMUSUFFIX
 | 
			
		||||
 | 
			
		||||
#define MMUSUFFIX _cmmu
 | 
			
		||||
#undef GETPC
 | 
			
		||||
#define GETPC() ((uintptr_t)0)
 | 
			
		||||
#undef GETPC_ADJ
 | 
			
		||||
#define GETPC_ADJ 0
 | 
			
		||||
#undef GETRA
 | 
			
		||||
#define GETRA() ((uintptr_t)0)
 | 
			
		||||
#define SOFTMMU_CODE_ACCESS
 | 
			
		||||
 | 
			
		||||
#define SHIFT 0
 | 
			
		||||
#include "exec/softmmu_template.h"
 | 
			
		||||
#include "softmmu_template.h"
 | 
			
		||||
 | 
			
		||||
#define SHIFT 1
 | 
			
		||||
#include "exec/softmmu_template.h"
 | 
			
		||||
#include "softmmu_template.h"
 | 
			
		||||
 | 
			
		||||
#define SHIFT 2
 | 
			
		||||
#include "exec/softmmu_template.h"
 | 
			
		||||
#include "softmmu_template.h"
 | 
			
		||||
 | 
			
		||||
#define SHIFT 3
 | 
			
		||||
#include "exec/softmmu_template.h"
 | 
			
		||||
 | 
			
		||||
#undef env
 | 
			
		||||
#include "softmmu_template.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,7 @@ In ubuntu/debian:
 | 
			
		||||
Configuring and building:
 | 
			
		||||
    ./configure --enable-smartcard && make
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
3. Using ccid-card-emulated with hardware
 | 
			
		||||
 | 
			
		||||
Assuming you have a working smartcard on the host with the current
 | 
			
		||||
@@ -54,19 +55,55 @@ user, using NSS, qemu acts as another NSS client using ccid-card-emulated:
 | 
			
		||||
 | 
			
		||||
    qemu -usb -device usb-ccid -device ccid-card-emulated
 | 
			
		||||
 | 
			
		||||
4. Using ccid-card-emulated with certificates
 | 
			
		||||
 | 
			
		||||
You must create the certificates. This is a one time process. We use NSS
 | 
			
		||||
certificates:
 | 
			
		||||
4. Using ccid-card-emulated with certificates stored in files
 | 
			
		||||
 | 
			
		||||
    certutil -d /etc/pki/nssdb -x -t "CT,CT,CT" -S -s "CN=cert1" -n cert1
 | 
			
		||||
You must create the CA and card certificates. This is a one time process.
 | 
			
		||||
We use NSS certificates:
 | 
			
		||||
 | 
			
		||||
    mkdir fake-smartcard
 | 
			
		||||
    cd fake-smartcard
 | 
			
		||||
    certutil -N -d sql:$PWD
 | 
			
		||||
    certutil -S -d sql:$PWD -s "CN=Fake Smart Card CA" -x -t TC,TC,TC -n fake-smartcard-ca
 | 
			
		||||
    certutil -S -d sql:$PWD -t ,, -s "CN=John Doe" -n id-cert -c fake-smartcard-ca
 | 
			
		||||
    certutil -S -d sql:$PWD -t ,, -s "CN=John Doe (signing)" --nsCertType smime -n signing-cert -c fake-smartcard-ca
 | 
			
		||||
    certutil -S -d sql:$PWD -t ,, -s "CN=John Doe (encryption)" --nsCertType sslClient -n encryption-cert -c fake-smartcard-ca
 | 
			
		||||
 | 
			
		||||
Note: you must have exactly three certificates.
 | 
			
		||||
 | 
			
		||||
Assuming the current user can access the certificates (use certutil -L to
 | 
			
		||||
verify), you can use the emulated card type with the certificates backend:
 | 
			
		||||
You can use the emulated card type with the certificates backend:
 | 
			
		||||
 | 
			
		||||
    qemu -usb -device usb-ccid -device ccid-card-emulated,backend=certificates,db=sql:$PWD,cert1=id-cert,cert2=signing-cert,cert3=encryption-cert
 | 
			
		||||
 | 
			
		||||
To use the certificates in the guest, export the CA certificate:
 | 
			
		||||
 | 
			
		||||
    certutil -L -r -d sql:$PWD -o fake-smartcard-ca.cer -n fake-smartcard-ca
 | 
			
		||||
 | 
			
		||||
and import it in the guest:
 | 
			
		||||
 | 
			
		||||
    certutil -A -d /etc/pki/nssdb -i fake-smartcard-ca.cer -t TC,TC,TC -n fake-smartcard-ca
 | 
			
		||||
 | 
			
		||||
In a Linux guest you can then use the CoolKey PKCS #11 module to access
 | 
			
		||||
the card:
 | 
			
		||||
 | 
			
		||||
    certutil -d /etc/pki/nssdb -L -h all
 | 
			
		||||
 | 
			
		||||
It will prompt you for the PIN (which is the password you assigned to the
 | 
			
		||||
certificate database early on), and then show you all three certificates
 | 
			
		||||
together with the manually imported CA cert:
 | 
			
		||||
 | 
			
		||||
    Certificate Nickname                        Trust Attributes
 | 
			
		||||
    fake-smartcard-ca                           CT,C,C
 | 
			
		||||
    John Doe:CAC ID Certificate                 u,u,u
 | 
			
		||||
    John Doe:CAC Email Signature Certificate    u,u,u
 | 
			
		||||
    John Doe:CAC Email Encryption Certificate   u,u,u
 | 
			
		||||
 | 
			
		||||
If this does not happen, CoolKey is not installed or not registered with
 | 
			
		||||
NSS.  Registration can be done from Firefox or the command line:
 | 
			
		||||
 | 
			
		||||
    modutil -dbdir /etc/pki/nssdb -add "CAC Module" -libfile /usr/lib64/pkcs11/libcoolkeypk11.so
 | 
			
		||||
    modutil -dbdir /etc/pki/nssdb -list
 | 
			
		||||
 | 
			
		||||
    qemu -usb -device usb-ccid -device ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3
 | 
			
		||||
 | 
			
		||||
5. Using ccid-card-passthru with client side hardware
 | 
			
		||||
 | 
			
		||||
@@ -74,15 +111,23 @@ on the host specify the ccid-card-passthru device with a suitable chardev:
 | 
			
		||||
 | 
			
		||||
    qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
 | 
			
		||||
 | 
			
		||||
on the client run vscclient, built when you built the libcacard library:
 | 
			
		||||
    libcacard/vscclient <qemu-host> 2001
 | 
			
		||||
on the client run vscclient, built when you built QEMU:
 | 
			
		||||
 | 
			
		||||
    vscclient <qemu-host> 2001
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
6. Using ccid-card-passthru with client side certificates
 | 
			
		||||
 | 
			
		||||
Run qemu as per #5, and run vscclient as follows:
 | 
			
		||||
(Note: vscclient command line interface is in a state of change)
 | 
			
		||||
This case is not particularly useful, but you can use it to debug
 | 
			
		||||
your setup if #4 works but #5 does not.
 | 
			
		||||
 | 
			
		||||
Follow instructions as per #4, except run QEMU and vscclient as follows:
 | 
			
		||||
Run qemu as per #5, and run vscclient from the "fake-smartcard"
 | 
			
		||||
directory as follows:
 | 
			
		||||
 | 
			
		||||
    qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
 | 
			
		||||
    vscclient -e "db=\"sql:$PWD\" use_hw=no soft=(,Test,CAC,,id-cert,signing-cert,encryption-cert)" <qemu-host> 2001
 | 
			
		||||
 | 
			
		||||
    libcacard/vscclient -e "db=\"/etc/pki/nssdb\" use_hw=no soft=(,Test,CAC,,cert1,cert2,cert3)" <qemu-host> 2001
 | 
			
		||||
 | 
			
		||||
7. Passthrough protocol scenario
 | 
			
		||||
 | 
			
		||||
@@ -126,10 +171,11 @@ kill/quit         |                          |                |               |
 | 
			
		||||
 | 
			
		||||
8. libcacard
 | 
			
		||||
 | 
			
		||||
ccid-card-passthru and vscclient use libcacard as the card emulator.
 | 
			
		||||
libcacard implements a completely virtual CAC (DoD standard for smart cards)
 | 
			
		||||
compliant card and uses NSS to actually retrive certificates and do any
 | 
			
		||||
encryption using the backend (real reader + card or file backed certificates).
 | 
			
		||||
Both ccid-card-emulated and vscclient use libcacard as the card emulator.
 | 
			
		||||
libcacard implements a completely virtual CAC (DoD standard for smart
 | 
			
		||||
cards) compliant card and uses NSS to retrieve certificates and do
 | 
			
		||||
any encryption.  The backend can then be a real reader and card, or
 | 
			
		||||
certificates stored in files.
 | 
			
		||||
 | 
			
		||||
For documentation of cac_card see README in libcacard subdirectory.
 | 
			
		||||
For documentation of the library see docs/libcacard.txt.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ for debugging, profiling, and observing execution.
 | 
			
		||||
 | 
			
		||||
1. Build with the 'simple' trace backend:
 | 
			
		||||
 | 
			
		||||
    ./configure --enable-trace-backend=simple
 | 
			
		||||
    ./configure --enable-trace-backends=simple
 | 
			
		||||
    make
 | 
			
		||||
 | 
			
		||||
2. Create a file with the events you want to trace:
 | 
			
		||||
@@ -142,7 +142,7 @@ script.
 | 
			
		||||
The trace backend is chosen at configure time and only one trace backend can
 | 
			
		||||
be built into the binary:
 | 
			
		||||
 | 
			
		||||
    ./configure --trace-backend=simple
 | 
			
		||||
    ./configure --trace-backends=simple
 | 
			
		||||
 | 
			
		||||
For a list of supported trace backends, try ./configure --help or see below.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,8 @@ which will return a dictionary containing:
 | 
			
		||||
 | 
			
		||||
  o A key named last-update, which contains the last stats update
 | 
			
		||||
    timestamp in seconds. Since this timestamp is generated by the host,
 | 
			
		||||
    a buggy guest can't influence its value
 | 
			
		||||
    a buggy guest can't influence its value. The value is 0 if the guest
 | 
			
		||||
    has not updated the stats (yet).
 | 
			
		||||
 | 
			
		||||
It's also important to note the following:
 | 
			
		||||
 | 
			
		||||
@@ -49,7 +50,7 @@ It's also important to note the following:
 | 
			
		||||
 | 
			
		||||
 - Polling can be enabled even if the guest doesn't have stats support
 | 
			
		||||
   or the balloon driver wasn't loaded in the guest. If this is the case
 | 
			
		||||
   and stats are queried, an error will be returned
 | 
			
		||||
   and stats are queried, last-update will be 0.
 | 
			
		||||
 | 
			
		||||
 - The polling timer is only re-armed when the guest responds to the
 | 
			
		||||
   statistics request. This means that if a (buggy) guest doesn't ever
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										140
									
								
								dump.c
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								dump.c
									
									
									
									
									
								
							@@ -90,8 +90,6 @@ typedef struct DumpState {
 | 
			
		||||
    uint8_t *note_buf;          /* buffer for notes */
 | 
			
		||||
    size_t note_buf_offset;     /* the writing place in note_buf */
 | 
			
		||||
    uint32_t nr_cpus;           /* number of guest's cpu */
 | 
			
		||||
    size_t page_size;           /* guest's page size */
 | 
			
		||||
    uint32_t page_shift;        /* guest's page shift */
 | 
			
		||||
    uint64_t max_mapnr;         /* the biggest guest's phys-mem's number */
 | 
			
		||||
    size_t len_dump_bitmap;     /* the size of the place used to store
 | 
			
		||||
                                   dump_bitmap in vmcore */
 | 
			
		||||
@@ -711,27 +709,25 @@ static int create_vmcore(DumpState *s)
 | 
			
		||||
 | 
			
		||||
static int write_start_flat_header(int fd)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *buf;
 | 
			
		||||
    MakedumpfileHeader mh;
 | 
			
		||||
    MakedumpfileHeader *mh;
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    memset(&mh, 0, sizeof(mh));
 | 
			
		||||
    strncpy(mh.signature, MAKEDUMPFILE_SIGNATURE,
 | 
			
		||||
            strlen(MAKEDUMPFILE_SIGNATURE));
 | 
			
		||||
    QEMU_BUILD_BUG_ON(sizeof *mh > MAX_SIZE_MDF_HEADER);
 | 
			
		||||
    mh = g_malloc0(MAX_SIZE_MDF_HEADER);
 | 
			
		||||
 | 
			
		||||
    mh.type = cpu_to_be64(TYPE_FLAT_HEADER);
 | 
			
		||||
    mh.version = cpu_to_be64(VERSION_FLAT_HEADER);
 | 
			
		||||
    memcpy(mh->signature, MAKEDUMPFILE_SIGNATURE,
 | 
			
		||||
           MIN(sizeof mh->signature, sizeof MAKEDUMPFILE_SIGNATURE));
 | 
			
		||||
 | 
			
		||||
    buf = g_malloc0(MAX_SIZE_MDF_HEADER);
 | 
			
		||||
    memcpy(buf, &mh, sizeof(mh));
 | 
			
		||||
    mh->type = cpu_to_be64(TYPE_FLAT_HEADER);
 | 
			
		||||
    mh->version = cpu_to_be64(VERSION_FLAT_HEADER);
 | 
			
		||||
 | 
			
		||||
    size_t written_size;
 | 
			
		||||
    written_size = qemu_write_full(fd, buf, MAX_SIZE_MDF_HEADER);
 | 
			
		||||
    written_size = qemu_write_full(fd, mh, MAX_SIZE_MDF_HEADER);
 | 
			
		||||
    if (written_size != MAX_SIZE_MDF_HEADER) {
 | 
			
		||||
        ret = -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_free(buf);
 | 
			
		||||
    g_free(mh);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -808,7 +804,7 @@ static int create_header32(DumpState *s)
 | 
			
		||||
 | 
			
		||||
    strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
 | 
			
		||||
    dh->header_version = cpu_convert_to_target32(6, endian);
 | 
			
		||||
    block_size = s->page_size;
 | 
			
		||||
    block_size = TARGET_PAGE_SIZE;
 | 
			
		||||
    dh->block_size = cpu_convert_to_target32(block_size, endian);
 | 
			
		||||
    sub_hdr_size = sizeof(struct KdumpSubHeader32) + s->note_size;
 | 
			
		||||
    sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, block_size);
 | 
			
		||||
@@ -915,7 +911,7 @@ static int create_header64(DumpState *s)
 | 
			
		||||
 | 
			
		||||
    strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
 | 
			
		||||
    dh->header_version = cpu_convert_to_target32(6, endian);
 | 
			
		||||
    block_size = s->page_size;
 | 
			
		||||
    block_size = TARGET_PAGE_SIZE;
 | 
			
		||||
    dh->block_size = cpu_convert_to_target32(block_size, endian);
 | 
			
		||||
    sub_hdr_size = sizeof(struct KdumpSubHeader64) + s->note_size;
 | 
			
		||||
    sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, block_size);
 | 
			
		||||
@@ -1004,7 +1000,7 @@ out:
 | 
			
		||||
 | 
			
		||||
static int write_dump_header(DumpState *s)
 | 
			
		||||
{
 | 
			
		||||
    if (s->dump_info.d_machine == EM_386) {
 | 
			
		||||
    if (s->dump_info.d_class == ELFCLASS32) {
 | 
			
		||||
        return create_header32(s);
 | 
			
		||||
    } else {
 | 
			
		||||
        return create_header64(s);
 | 
			
		||||
@@ -1086,9 +1082,9 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
 | 
			
		||||
    if (!block) {
 | 
			
		||||
        block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
 | 
			
		||||
        *blockptr = block;
 | 
			
		||||
        assert(block->target_start % s->page_size == 0);
 | 
			
		||||
        assert(block->target_end % s->page_size == 0);
 | 
			
		||||
        *pfnptr = paddr_to_pfn(block->target_start, s->page_shift);
 | 
			
		||||
        assert((block->target_start & ~TARGET_PAGE_MASK) == 0);
 | 
			
		||||
        assert((block->target_end & ~TARGET_PAGE_MASK) == 0);
 | 
			
		||||
        *pfnptr = paddr_to_pfn(block->target_start);
 | 
			
		||||
        if (bufptr) {
 | 
			
		||||
            *bufptr = block->host_addr;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1096,10 +1092,10 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *pfnptr = *pfnptr + 1;
 | 
			
		||||
    addr = pfn_to_paddr(*pfnptr, s->page_shift);
 | 
			
		||||
    addr = pfn_to_paddr(*pfnptr);
 | 
			
		||||
 | 
			
		||||
    if ((addr >= block->target_start) &&
 | 
			
		||||
        (addr + s->page_size <= block->target_end)) {
 | 
			
		||||
        (addr + TARGET_PAGE_SIZE <= block->target_end)) {
 | 
			
		||||
        buf = block->host_addr + (addr - block->target_start);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* the next page is in the next block */
 | 
			
		||||
@@ -1108,9 +1104,9 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
 | 
			
		||||
        if (!block) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        assert(block->target_start % s->page_size == 0);
 | 
			
		||||
        assert(block->target_end % s->page_size == 0);
 | 
			
		||||
        *pfnptr = paddr_to_pfn(block->target_start, s->page_shift);
 | 
			
		||||
        assert((block->target_start & ~TARGET_PAGE_MASK) == 0);
 | 
			
		||||
        assert((block->target_end & ~TARGET_PAGE_MASK) == 0);
 | 
			
		||||
        *pfnptr = paddr_to_pfn(block->target_start);
 | 
			
		||||
        buf = block->host_addr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1224,42 +1220,24 @@ static void free_data_cache(DataCache *data_cache)
 | 
			
		||||
 | 
			
		||||
static size_t get_len_buf_out(size_t page_size, uint32_t flag_compress)
 | 
			
		||||
{
 | 
			
		||||
    size_t len_buf_out_zlib, len_buf_out_lzo, len_buf_out_snappy;
 | 
			
		||||
    size_t len_buf_out;
 | 
			
		||||
    switch (flag_compress) {
 | 
			
		||||
    case DUMP_DH_COMPRESSED_ZLIB:
 | 
			
		||||
        return compressBound(page_size);
 | 
			
		||||
 | 
			
		||||
    /* init buf_out */
 | 
			
		||||
    len_buf_out_zlib = len_buf_out_lzo = len_buf_out_snappy = 0;
 | 
			
		||||
 | 
			
		||||
    /* buf size for zlib */
 | 
			
		||||
    len_buf_out_zlib = compressBound(page_size);
 | 
			
		||||
 | 
			
		||||
    /* buf size for lzo */
 | 
			
		||||
#ifdef CONFIG_LZO
 | 
			
		||||
    if (flag_compress & DUMP_DH_COMPRESSED_LZO) {
 | 
			
		||||
        if (lzo_init() != LZO_E_OK) {
 | 
			
		||||
            /* return 0 to indicate lzo is unavailable */
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * LZO will expand incompressible data by a little amount. please check the
 | 
			
		||||
     * following URL to see the expansion calculation:
 | 
			
		||||
     * http://www.oberhumer.com/opensource/lzo/lzofaq.php
 | 
			
		||||
     */
 | 
			
		||||
    len_buf_out_lzo = page_size + page_size / 16 + 64 + 3;
 | 
			
		||||
#endif
 | 
			
		||||
    case DUMP_DH_COMPRESSED_LZO:
 | 
			
		||||
        /*
 | 
			
		||||
         * LZO will expand incompressible data by a little amount. Please check
 | 
			
		||||
         * the following URL to see the expansion calculation:
 | 
			
		||||
         * http://www.oberhumer.com/opensource/lzo/lzofaq.php
 | 
			
		||||
         */
 | 
			
		||||
        return page_size + page_size / 16 + 64 + 3;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SNAPPY
 | 
			
		||||
    /* buf size for snappy */
 | 
			
		||||
    len_buf_out_snappy = snappy_max_compressed_length(page_size);
 | 
			
		||||
    case DUMP_DH_COMPRESSED_SNAPPY:
 | 
			
		||||
        return snappy_max_compressed_length(page_size);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* get the biggest that can store all kinds of compressed page */
 | 
			
		||||
    len_buf_out = MAX(len_buf_out_zlib,
 | 
			
		||||
                      MAX(len_buf_out_lzo, len_buf_out_snappy));
 | 
			
		||||
 | 
			
		||||
    return len_buf_out;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -1294,11 +1272,8 @@ static int write_dump_pages(DumpState *s)
 | 
			
		||||
    prepare_data_cache(&page_data, s, offset_data);
 | 
			
		||||
 | 
			
		||||
    /* prepare buffer to store compressed data */
 | 
			
		||||
    len_buf_out = get_len_buf_out(s->page_size, s->flag_compress);
 | 
			
		||||
    if (len_buf_out == 0) {
 | 
			
		||||
        dump_error(s, "dump: failed to get length of output buffer.\n");
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    len_buf_out = get_len_buf_out(TARGET_PAGE_SIZE, s->flag_compress);
 | 
			
		||||
    assert(len_buf_out != 0);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_LZO
 | 
			
		||||
    wrkmem = g_malloc(LZO1X_1_MEM_COMPRESS);
 | 
			
		||||
@@ -1310,19 +1285,19 @@ static int write_dump_pages(DumpState *s)
 | 
			
		||||
     * init zero page's page_desc and page_data, because every zero page
 | 
			
		||||
     * uses the same page_data
 | 
			
		||||
     */
 | 
			
		||||
    pd_zero.size = cpu_convert_to_target32(s->page_size, endian);
 | 
			
		||||
    pd_zero.size = cpu_convert_to_target32(TARGET_PAGE_SIZE, endian);
 | 
			
		||||
    pd_zero.flags = cpu_convert_to_target32(0, endian);
 | 
			
		||||
    pd_zero.offset = cpu_convert_to_target64(offset_data, endian);
 | 
			
		||||
    pd_zero.page_flags = cpu_convert_to_target64(0, endian);
 | 
			
		||||
    buf = g_malloc0(s->page_size);
 | 
			
		||||
    ret = write_cache(&page_data, buf, s->page_size, false);
 | 
			
		||||
    buf = g_malloc0(TARGET_PAGE_SIZE);
 | 
			
		||||
    ret = write_cache(&page_data, buf, TARGET_PAGE_SIZE, false);
 | 
			
		||||
    g_free(buf);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        dump_error(s, "dump: failed to write page data(zero page).\n");
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    offset_data += s->page_size;
 | 
			
		||||
    offset_data += TARGET_PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * dump memory to vmcore page by page. zero page will all be resided in the
 | 
			
		||||
@@ -1330,7 +1305,7 @@ static int write_dump_pages(DumpState *s)
 | 
			
		||||
     */
 | 
			
		||||
    while (get_next_page(&block_iter, &pfn_iter, &buf, s)) {
 | 
			
		||||
        /* check zero page */
 | 
			
		||||
        if (is_zero_page(buf, s->page_size)) {
 | 
			
		||||
        if (is_zero_page(buf, TARGET_PAGE_SIZE)) {
 | 
			
		||||
            ret = write_cache(&page_desc, &pd_zero, sizeof(PageDescriptor),
 | 
			
		||||
                              false);
 | 
			
		||||
            if (ret < 0) {
 | 
			
		||||
@@ -1351,8 +1326,9 @@ static int write_dump_pages(DumpState *s)
 | 
			
		||||
             */
 | 
			
		||||
             size_out = len_buf_out;
 | 
			
		||||
             if ((s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) &&
 | 
			
		||||
                    (compress2(buf_out, (uLongf *)&size_out, buf, s->page_size,
 | 
			
		||||
                    Z_BEST_SPEED) == Z_OK) && (size_out < s->page_size)) {
 | 
			
		||||
                 (compress2(buf_out, (uLongf *)&size_out, buf,
 | 
			
		||||
                            TARGET_PAGE_SIZE, Z_BEST_SPEED) == Z_OK) &&
 | 
			
		||||
                 (size_out < TARGET_PAGE_SIZE)) {
 | 
			
		||||
                pd.flags = cpu_convert_to_target32(DUMP_DH_COMPRESSED_ZLIB,
 | 
			
		||||
                                                   endian);
 | 
			
		||||
                pd.size  = cpu_convert_to_target32(size_out, endian);
 | 
			
		||||
@@ -1364,9 +1340,9 @@ static int write_dump_pages(DumpState *s)
 | 
			
		||||
                }
 | 
			
		||||
#ifdef CONFIG_LZO
 | 
			
		||||
            } else if ((s->flag_compress & DUMP_DH_COMPRESSED_LZO) &&
 | 
			
		||||
                    (lzo1x_1_compress(buf, s->page_size, buf_out,
 | 
			
		||||
                    (lzo1x_1_compress(buf, TARGET_PAGE_SIZE, buf_out,
 | 
			
		||||
                    (lzo_uint *)&size_out, wrkmem) == LZO_E_OK) &&
 | 
			
		||||
                    (size_out < s->page_size)) {
 | 
			
		||||
                    (size_out < TARGET_PAGE_SIZE)) {
 | 
			
		||||
                pd.flags = cpu_convert_to_target32(DUMP_DH_COMPRESSED_LZO,
 | 
			
		||||
                                                   endian);
 | 
			
		||||
                pd.size  = cpu_convert_to_target32(size_out, endian);
 | 
			
		||||
@@ -1379,9 +1355,9 @@ static int write_dump_pages(DumpState *s)
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_SNAPPY
 | 
			
		||||
            } else if ((s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) &&
 | 
			
		||||
                    (snappy_compress((char *)buf, s->page_size,
 | 
			
		||||
                    (snappy_compress((char *)buf, TARGET_PAGE_SIZE,
 | 
			
		||||
                    (char *)buf_out, &size_out) == SNAPPY_OK) &&
 | 
			
		||||
                    (size_out < s->page_size)) {
 | 
			
		||||
                    (size_out < TARGET_PAGE_SIZE)) {
 | 
			
		||||
                pd.flags = cpu_convert_to_target32(
 | 
			
		||||
                                        DUMP_DH_COMPRESSED_SNAPPY, endian);
 | 
			
		||||
                pd.size  = cpu_convert_to_target32(size_out, endian);
 | 
			
		||||
@@ -1395,13 +1371,13 @@ static int write_dump_pages(DumpState *s)
 | 
			
		||||
            } else {
 | 
			
		||||
                /*
 | 
			
		||||
                 * fall back to save in plaintext, size_out should be
 | 
			
		||||
                 * assigned to s->page_size
 | 
			
		||||
                 * assigned TARGET_PAGE_SIZE
 | 
			
		||||
                 */
 | 
			
		||||
                pd.flags = cpu_convert_to_target32(0, endian);
 | 
			
		||||
                size_out = s->page_size;
 | 
			
		||||
                size_out = TARGET_PAGE_SIZE;
 | 
			
		||||
                pd.size = cpu_convert_to_target32(size_out, endian);
 | 
			
		||||
 | 
			
		||||
                ret = write_cache(&page_data, buf, s->page_size, false);
 | 
			
		||||
                ret = write_cache(&page_data, buf, TARGET_PAGE_SIZE, false);
 | 
			
		||||
                if (ret < 0) {
 | 
			
		||||
                    dump_error(s, "dump: failed to write page data.\n");
 | 
			
		||||
                    goto out;
 | 
			
		||||
@@ -1536,7 +1512,7 @@ static void get_max_mapnr(DumpState *s)
 | 
			
		||||
    GuestPhysBlock *last_block;
 | 
			
		||||
 | 
			
		||||
    last_block = QTAILQ_LAST(&s->guest_phys_blocks.head, GuestPhysBlockHead);
 | 
			
		||||
    s->max_mapnr = paddr_to_pfn(last_block->target_end, s->page_shift);
 | 
			
		||||
    s->max_mapnr = paddr_to_pfn(last_block->target_end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dump_init(DumpState *s, int fd, bool has_format,
 | 
			
		||||
@@ -1613,14 +1589,12 @@ static int dump_init(DumpState *s, int fd, bool has_format,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->nr_cpus = nr_cpus;
 | 
			
		||||
    s->page_size = TARGET_PAGE_SIZE;
 | 
			
		||||
    s->page_shift = ffs(s->page_size) - 1;
 | 
			
		||||
 | 
			
		||||
    get_max_mapnr(s);
 | 
			
		||||
 | 
			
		||||
    uint64_t tmp;
 | 
			
		||||
    tmp = DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), s->page_size);
 | 
			
		||||
    s->len_dump_bitmap = tmp * s->page_size;
 | 
			
		||||
    tmp = DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), TARGET_PAGE_SIZE);
 | 
			
		||||
    s->len_dump_bitmap = tmp * TARGET_PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
    /* init for kdump-compressed format */
 | 
			
		||||
    if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
 | 
			
		||||
@@ -1630,6 +1604,12 @@ static int dump_init(DumpState *s, int fd, bool has_format,
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO:
 | 
			
		||||
#ifdef CONFIG_LZO
 | 
			
		||||
            if (lzo_init() != LZO_E_OK) {
 | 
			
		||||
                error_setg(errp, "failed to initialize the LZO library");
 | 
			
		||||
                goto cleanup;
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            s->flag_compress = DUMP_DH_COMPRESSED_LZO;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -335,6 +335,7 @@ ETEXI
 | 
			
		||||
        .params     = "tag|id",
 | 
			
		||||
        .help       = "restore a VM snapshot from its tag or id",
 | 
			
		||||
        .mhandler.cmd = do_loadvm,
 | 
			
		||||
        .command_completion = loadvm_completion,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
@@ -350,6 +351,7 @@ ETEXI
 | 
			
		||||
        .params     = "tag|id",
 | 
			
		||||
        .help       = "delete a VM snapshot from its tag or id",
 | 
			
		||||
        .mhandler.cmd = do_delvm,
 | 
			
		||||
        .command_completion = delvm_completion,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
@@ -852,6 +854,7 @@ ETEXI
 | 
			
		||||
        .params     = "device data",
 | 
			
		||||
        .help       = "Write to a ring buffer character device",
 | 
			
		||||
        .mhandler.cmd = hmp_ringbuf_write,
 | 
			
		||||
        .command_completion = ringbuf_write_completion,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
@@ -868,6 +871,7 @@ ETEXI
 | 
			
		||||
        .params     = "device size",
 | 
			
		||||
        .help       = "Read from a ring buffer character device",
 | 
			
		||||
        .mhandler.cmd = hmp_ringbuf_read,
 | 
			
		||||
        .command_completion = ringbuf_write_completion,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
@@ -973,6 +977,7 @@ ETEXI
 | 
			
		||||
        .params     = "capability state",
 | 
			
		||||
        .help       = "Enable/Disable the usage of a capability for migration",
 | 
			
		||||
        .mhandler.cmd = hmp_migrate_set_capability,
 | 
			
		||||
        .command_completion = migrate_set_capability_completion,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
@@ -1206,9 +1211,10 @@ ETEXI
 | 
			
		||||
    {
 | 
			
		||||
        .name       = "host_net_add",
 | 
			
		||||
        .args_type  = "device:s,opts:s?",
 | 
			
		||||
        .params     = "tap|user|socket|vde|netmap|dump [options]",
 | 
			
		||||
        .params     = "tap|user|socket|vde|netmap|bridge|dump [options]",
 | 
			
		||||
        .help       = "add host VLAN client",
 | 
			
		||||
        .mhandler.cmd = net_host_device_add,
 | 
			
		||||
        .command_completion = host_net_add_completion,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
@@ -1223,6 +1229,7 @@ ETEXI
 | 
			
		||||
        .params     = "vlan_id name",
 | 
			
		||||
        .help       = "remove host VLAN client",
 | 
			
		||||
        .mhandler.cmd = net_host_device_remove,
 | 
			
		||||
        .command_completion = host_net_remove_completion,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
@@ -1357,6 +1364,7 @@ ETEXI
 | 
			
		||||
        .params     = "[reset|shutdown|poweroff|pause|debug|none]",
 | 
			
		||||
        .help       = "change watchdog action",
 | 
			
		||||
        .mhandler.cmd = do_watchdog_action,
 | 
			
		||||
        .command_completion = watchdog_action_completion,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								hmp.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								hmp.h
									
									
									
									
									
								
							@@ -103,5 +103,16 @@ void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
void set_link_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
void ringbuf_read_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
void watchdog_action_completion(ReadLineState *rs, int nb_args,
 | 
			
		||||
                                const char *str);
 | 
			
		||||
void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
 | 
			
		||||
                                       const char *str);
 | 
			
		||||
void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
void host_net_remove_completion(ReadLineState *rs, int nb_args,
 | 
			
		||||
                                const char *str);
 | 
			
		||||
void delvm_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
void loadvm_completion(ReadLineState *rs, int nb_args, const char *str);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
 | 
			
		||||
 | 
			
		||||
    len = strlen(s->tag);
 | 
			
		||||
    cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
 | 
			
		||||
    stw_raw(&cfg->tag_len, len);
 | 
			
		||||
    stw_p(&cfg->tag_len, len);
 | 
			
		||||
    /* We don't copy the terminating null to config space */
 | 
			
		||||
    memcpy(cfg->tag, s->tag, len);
 | 
			
		||||
    memcpy(config, cfg, s->config_size);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										316
									
								
								hw/arm/nseries.c
									
									
									
									
									
								
							
							
						
						
									
										316
									
								
								hw/arm/nseries.c
									
									
									
									
									
								
							@@ -239,8 +239,9 @@ static void n800_key_event(void *opaque, int keycode)
 | 
			
		||||
    int code = s->keymap[keycode & 0x7f];
 | 
			
		||||
 | 
			
		||||
    if (code == -1) {
 | 
			
		||||
        if ((keycode & 0x7f) == RETU_KEYCODE)
 | 
			
		||||
        if ((keycode & 0x7f) == RETU_KEYCODE) {
 | 
			
		||||
            retu_key_event(s->retu, !(keycode & 0x80));
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -280,11 +281,14 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
 | 
			
		||||
    s->ts.opaque = s->ts.chip->opaque;
 | 
			
		||||
    s->ts.txrx = tsc210x_txrx;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 0x80; i ++)
 | 
			
		||||
    for (i = 0; i < 0x80; i++) {
 | 
			
		||||
        s->keymap[i] = -1;
 | 
			
		||||
    for (i = 0; i < 0x10; i ++)
 | 
			
		||||
        if (n800_keys[i] >= 0)
 | 
			
		||||
    }
 | 
			
		||||
    for (i = 0; i < 0x10; i++) {
 | 
			
		||||
        if (n800_keys[i] >= 0) {
 | 
			
		||||
            s->keymap[n800_keys[i]] = i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_add_kbd_event_handler(n800_key_event, s);
 | 
			
		||||
 | 
			
		||||
@@ -308,8 +312,9 @@ static void n810_key_event(void *opaque, int keycode)
 | 
			
		||||
    int code = s->keymap[keycode & 0x7f];
 | 
			
		||||
 | 
			
		||||
    if (code == -1) {
 | 
			
		||||
        if ((keycode & 0x7f) == RETU_KEYCODE)
 | 
			
		||||
        if ((keycode & 0x7f) == RETU_KEYCODE) {
 | 
			
		||||
            retu_key_event(s->retu, !(keycode & 0x80));
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -388,11 +393,14 @@ static void n810_kbd_setup(struct n800_s *s)
 | 
			
		||||
    qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 0x80; i ++)
 | 
			
		||||
    for (i = 0; i < 0x80; i++) {
 | 
			
		||||
        s->keymap[i] = -1;
 | 
			
		||||
    for (i = 0; i < 0x80; i ++)
 | 
			
		||||
        if (n810_keys[i] > 0)
 | 
			
		||||
    }
 | 
			
		||||
    for (i = 0; i < 0x80; i++) {
 | 
			
		||||
        if (n810_keys[i] > 0) {
 | 
			
		||||
            s->keymap[n810_keys[i]] = i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_add_kbd_event_handler(n810_key_event, s);
 | 
			
		||||
 | 
			
		||||
@@ -449,17 +457,20 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 | 
			
		||||
    struct mipid_s *s = (struct mipid_s *) opaque;
 | 
			
		||||
    uint8_t ret;
 | 
			
		||||
 | 
			
		||||
    if (len > 9)
 | 
			
		||||
    if (len > 9) {
 | 
			
		||||
        hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (s->p >= ARRAY_SIZE(s->resp))
 | 
			
		||||
    if (s->p >= ARRAY_SIZE(s->resp)) {
 | 
			
		||||
        ret = 0;
 | 
			
		||||
    else
 | 
			
		||||
        ret = s->resp[s->p ++];
 | 
			
		||||
    if (s->pm --> 0)
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = s->resp[s->p++];
 | 
			
		||||
    }
 | 
			
		||||
    if (s->pm-- > 0) {
 | 
			
		||||
        s->param[s->pm] = cmd;
 | 
			
		||||
    else
 | 
			
		||||
    } else {
 | 
			
		||||
        s->cmd = cmd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (s->cmd) {
 | 
			
		||||
    case 0x00:	/* NOP */
 | 
			
		||||
@@ -560,15 +571,17 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 | 
			
		||||
        goto bad_cmd;
 | 
			
		||||
 | 
			
		||||
    case 0x25:	/* WRCNTR */
 | 
			
		||||
        if (s->pm < 0)
 | 
			
		||||
        if (s->pm < 0) {
 | 
			
		||||
            s->pm = 1;
 | 
			
		||||
        }
 | 
			
		||||
        goto bad_cmd;
 | 
			
		||||
 | 
			
		||||
    case 0x26:	/* GAMSET */
 | 
			
		||||
        if (!s->pm)
 | 
			
		||||
        if (!s->pm) {
 | 
			
		||||
            s->gamma = ffs(s->param[0] & 0xf) - 1;
 | 
			
		||||
        else if (s->pm < 0)
 | 
			
		||||
        } else if (s->pm < 0) {
 | 
			
		||||
            s->pm = 1;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 0x28:	/* DISPOFF */
 | 
			
		||||
@@ -591,10 +604,11 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 | 
			
		||||
        s->te = 0;
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x35:	/* TEON */
 | 
			
		||||
        if (!s->pm)
 | 
			
		||||
        if (!s->pm) {
 | 
			
		||||
            s->te = 1;
 | 
			
		||||
        else if (s->pm < 0)
 | 
			
		||||
        } else if (s->pm < 0) {
 | 
			
		||||
            s->pm = 1;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 0x36:	/* MADCTR */
 | 
			
		||||
@@ -613,8 +627,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 | 
			
		||||
 | 
			
		||||
    case 0xb0:	/* CLKINT / DISCTL */
 | 
			
		||||
    case 0xb1:	/* CLKEXT */
 | 
			
		||||
        if (s->pm < 0)
 | 
			
		||||
        if (s->pm < 0) {
 | 
			
		||||
            s->pm = 2;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 0xb4:	/* FRMSEL */
 | 
			
		||||
@@ -635,8 +650,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 0xc2:	/* IFMOD */
 | 
			
		||||
        if (s->pm < 0)
 | 
			
		||||
        if (s->pm < 0) {
 | 
			
		||||
            s->pm = 2;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 0xc6:	/* PWRCTL */
 | 
			
		||||
@@ -834,118 +850,119 @@ static void n800_setup_nolo_tags(void *sram_base)
 | 
			
		||||
 | 
			
		||||
    strcpy((void *) (p + 8), "F5");
 | 
			
		||||
 | 
			
		||||
    stl_raw(p + 10, 0x04f70000);
 | 
			
		||||
    stl_p(p + 10, 0x04f70000);
 | 
			
		||||
    strcpy((void *) (p + 9), "RX-34");
 | 
			
		||||
 | 
			
		||||
    /* RAM size in MB? */
 | 
			
		||||
    stl_raw(p + 12, 0x80);
 | 
			
		||||
    stl_p(p + 12, 0x80);
 | 
			
		||||
 | 
			
		||||
    /* Pointer to the list of tags */
 | 
			
		||||
    stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
 | 
			
		||||
    stl_p(p + 13, OMAP2_SRAM_BASE + 0x9000);
 | 
			
		||||
 | 
			
		||||
    /* The NOLO tags start here */
 | 
			
		||||
    p = sram_base + 0x9000;
 | 
			
		||||
#define ADD_TAG(tag, len)				\
 | 
			
		||||
    stw_raw((uint16_t *) p + 0, tag);			\
 | 
			
		||||
    stw_raw((uint16_t *) p + 1, len); p ++;		\
 | 
			
		||||
    stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
 | 
			
		||||
    stw_p((uint16_t *) p + 0, tag);			\
 | 
			
		||||
    stw_p((uint16_t *) p + 1, len); p++;		\
 | 
			
		||||
    stl_p(p++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
 | 
			
		||||
 | 
			
		||||
    /* OMAP STI console? Pin out settings? */
 | 
			
		||||
    ADD_TAG(0x6e01, 414);
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
 | 
			
		||||
        stl_raw(v ++, n800_pinout[i]);
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(n800_pinout); i++) {
 | 
			
		||||
        stl_p(v++, n800_pinout[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Kernel memsize? */
 | 
			
		||||
    ADD_TAG(0x6e05, 1);
 | 
			
		||||
    stl_raw(v ++, 2);
 | 
			
		||||
    stl_p(v++, 2);
 | 
			
		||||
 | 
			
		||||
    /* NOLO serial console */
 | 
			
		||||
    ADD_TAG(0x6e02, 4);
 | 
			
		||||
    stl_raw(v ++, XLDR_LL_UART);	/* UART number (1 - 3) */
 | 
			
		||||
    stl_p(v++, XLDR_LL_UART);		/* UART number (1 - 3) */
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    /* CBUS settings (Retu/AVilma) */
 | 
			
		||||
    ADD_TAG(0x6e03, 6);
 | 
			
		||||
    stw_raw((uint16_t *) v + 0, 65);	/* CBUS GPIO0 */
 | 
			
		||||
    stw_raw((uint16_t *) v + 1, 66);	/* CBUS GPIO1 */
 | 
			
		||||
    stw_raw((uint16_t *) v + 2, 64);	/* CBUS GPIO2 */
 | 
			
		||||
    stw_p((uint16_t *) v + 0, 65);	/* CBUS GPIO0 */
 | 
			
		||||
    stw_p((uint16_t *) v + 1, 66);	/* CBUS GPIO1 */
 | 
			
		||||
    stw_p((uint16_t *) v + 2, 64);	/* CBUS GPIO2 */
 | 
			
		||||
    v += 2;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* Nokia ASIC BB5 (Retu/Tahvo) */
 | 
			
		||||
    ADD_TAG(0x6e0a, 4);
 | 
			
		||||
    stw_raw((uint16_t *) v + 0, 111);	/* "Retu" interrupt GPIO */
 | 
			
		||||
    stw_raw((uint16_t *) v + 1, 108);	/* "Tahvo" interrupt GPIO */
 | 
			
		||||
    v ++;
 | 
			
		||||
    stw_p((uint16_t *) v + 0, 111);	/* "Retu" interrupt GPIO */
 | 
			
		||||
    stw_p((uint16_t *) v + 1, 108);	/* "Tahvo" interrupt GPIO */
 | 
			
		||||
    v++;
 | 
			
		||||
 | 
			
		||||
    /* LCD console? */
 | 
			
		||||
    ADD_TAG(0x6e04, 4);
 | 
			
		||||
    stw_raw((uint16_t *) v + 0, 30);	/* ??? */
 | 
			
		||||
    stw_raw((uint16_t *) v + 1, 24);	/* ??? */
 | 
			
		||||
    v ++;
 | 
			
		||||
    stw_p((uint16_t *) v + 0, 30);	/* ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 1, 24);	/* ??? */
 | 
			
		||||
    v++;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    /* LCD settings */
 | 
			
		||||
    ADD_TAG(0x6e06, 2);
 | 
			
		||||
    stw_raw((uint16_t *) (v ++), 15);	/* ??? */
 | 
			
		||||
    stw_p((uint16_t *) (v++), 15);	/* ??? */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* I^2C (Menelaus) */
 | 
			
		||||
    ADD_TAG(0x6e07, 4);
 | 
			
		||||
    stl_raw(v ++, 0x00720000);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x00720000);		/* ??? */
 | 
			
		||||
 | 
			
		||||
    /* Unknown */
 | 
			
		||||
    ADD_TAG(0x6e0b, 6);
 | 
			
		||||
    stw_raw((uint16_t *) v + 0, 94);	/* ??? */
 | 
			
		||||
    stw_raw((uint16_t *) v + 1, 23);	/* ??? */
 | 
			
		||||
    stw_raw((uint16_t *) v + 2, 0);	/* ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 0, 94);	/* ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 1, 23);	/* ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 2, 0);	/* ??? */
 | 
			
		||||
    v += 2;
 | 
			
		||||
 | 
			
		||||
    /* OMAP gpio switch info */
 | 
			
		||||
    ADD_TAG(0x6e0c, 80);
 | 
			
		||||
    strcpy((void *) v, "bat_cover");	v += 3;
 | 
			
		||||
    stw_raw((uint16_t *) v + 0, 110);	/* GPIO num ??? */
 | 
			
		||||
    stw_raw((uint16_t *) v + 1, 1);	/* GPIO num ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 0, 110);	/* GPIO num ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 1, 1);	/* GPIO num ??? */
 | 
			
		||||
    v += 2;
 | 
			
		||||
    strcpy((void *) v, "cam_act");	v += 3;
 | 
			
		||||
    stw_raw((uint16_t *) v + 0, 95);	/* GPIO num ??? */
 | 
			
		||||
    stw_raw((uint16_t *) v + 1, 32);	/* GPIO num ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 0, 95);	/* GPIO num ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 1, 32);	/* GPIO num ??? */
 | 
			
		||||
    v += 2;
 | 
			
		||||
    strcpy((void *) v, "cam_turn");	v += 3;
 | 
			
		||||
    stw_raw((uint16_t *) v + 0, 12);	/* GPIO num ??? */
 | 
			
		||||
    stw_raw((uint16_t *) v + 1, 33);	/* GPIO num ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 0, 12);	/* GPIO num ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 1, 33);	/* GPIO num ??? */
 | 
			
		||||
    v += 2;
 | 
			
		||||
    strcpy((void *) v, "headphone");	v += 3;
 | 
			
		||||
    stw_raw((uint16_t *) v + 0, 107);	/* GPIO num ??? */
 | 
			
		||||
    stw_raw((uint16_t *) v + 1, 17);	/* GPIO num ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 0, 107);	/* GPIO num ??? */
 | 
			
		||||
    stw_p((uint16_t *) v + 1, 17);	/* GPIO num ??? */
 | 
			
		||||
    v += 2;
 | 
			
		||||
 | 
			
		||||
    /* Bluetooth */
 | 
			
		||||
    ADD_TAG(0x6e0e, 12);
 | 
			
		||||
    stl_raw(v ++, 0x5c623d01);		/* ??? */
 | 
			
		||||
    stl_raw(v ++, 0x00000201);		/* ??? */
 | 
			
		||||
    stl_raw(v ++, 0x00000000);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x5c623d01);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x00000201);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x00000000);		/* ??? */
 | 
			
		||||
 | 
			
		||||
    /* CX3110x WLAN settings */
 | 
			
		||||
    ADD_TAG(0x6e0f, 8);
 | 
			
		||||
    stl_raw(v ++, 0x00610025);		/* ??? */
 | 
			
		||||
    stl_raw(v ++, 0xffff0057);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x00610025);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0xffff0057);		/* ??? */
 | 
			
		||||
 | 
			
		||||
    /* MMC host settings */
 | 
			
		||||
    ADD_TAG(0x6e10, 12);
 | 
			
		||||
    stl_raw(v ++, 0xffff000f);		/* ??? */
 | 
			
		||||
    stl_raw(v ++, 0xffffffff);		/* ??? */
 | 
			
		||||
    stl_raw(v ++, 0x00000060);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0xffff000f);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0xffffffff);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x00000060);		/* ??? */
 | 
			
		||||
 | 
			
		||||
    /* OneNAND chip select */
 | 
			
		||||
    ADD_TAG(0x6e11, 10);
 | 
			
		||||
    stl_raw(v ++, 0x00000401);		/* ??? */
 | 
			
		||||
    stl_raw(v ++, 0x0002003a);		/* ??? */
 | 
			
		||||
    stl_raw(v ++, 0x00000002);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x00000401);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x0002003a);		/* ??? */
 | 
			
		||||
    stl_p(v++, 0x00000002);		/* ??? */
 | 
			
		||||
 | 
			
		||||
    /* TEA5761 sensor settings */
 | 
			
		||||
    ADD_TAG(0x6e12, 2);
 | 
			
		||||
    stl_raw(v ++, 93);			/* GPIO num ??? */
 | 
			
		||||
    stl_p(v++, 93);			/* GPIO num ??? */
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    /* Unknown tag */
 | 
			
		||||
@@ -956,8 +973,8 @@ static void n800_setup_nolo_tags(void *sram_base)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* End of the list */
 | 
			
		||||
    stl_raw(p ++, 0x00000000);
 | 
			
		||||
    stl_raw(p ++, 0x00000000);
 | 
			
		||||
    stl_p(p++, 0x00000000);
 | 
			
		||||
    stl_p(p++, 0x00000000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This task is normally performed by the bootloader.  If we're loading
 | 
			
		||||
@@ -1032,8 +1049,9 @@ static void n8x0_boot_init(void *opaque)
 | 
			
		||||
    s->mpu->cpu->env.GE = 0x5;
 | 
			
		||||
 | 
			
		||||
    /* If the machine has a slided keyboard, open it */
 | 
			
		||||
    if (s->kbd)
 | 
			
		||||
    if (s->kbd) {
 | 
			
		||||
        qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define OMAP_TAG_NOKIA_BT	0x4e01
 | 
			
		||||
@@ -1119,112 +1137,112 @@ static int n8x0_atag_setup(void *p, int model)
 | 
			
		||||
 | 
			
		||||
    w = p;
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_UART);		/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 4);				/* u16 len */
 | 
			
		||||
    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
 | 
			
		||||
    w ++;
 | 
			
		||||
    stw_p(w++, OMAP_TAG_UART);			/* u16 tag */
 | 
			
		||||
    stw_p(w++, 4);				/* u16 len */
 | 
			
		||||
    stw_p(w++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
 | 
			
		||||
    w++;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE);	/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 4);				/* u16 len */
 | 
			
		||||
    stw_raw(w ++, XLDR_LL_UART + 1);		/* u8 console_uart */
 | 
			
		||||
    stw_raw(w ++, 115200);			/* u32 console_speed */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_SERIAL_CONSOLE);	/* u16 tag */
 | 
			
		||||
    stw_p(w++, 4);				/* u16 len */
 | 
			
		||||
    stw_p(w++, XLDR_LL_UART + 1);		/* u8 console_uart */
 | 
			
		||||
    stw_p(w++, 115200);				/* u32 console_speed */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_LCD);		/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 36);				/* u16 len */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_LCD);			/* u16 tag */
 | 
			
		||||
    stw_p(w++, 36);				/* u16 len */
 | 
			
		||||
    strcpy((void *) w, "QEMU LCD panel");	/* char panel_name[16] */
 | 
			
		||||
    w += 8;
 | 
			
		||||
    strcpy((void *) w, "blizzard");		/* char ctrl_name[16] */
 | 
			
		||||
    w += 8;
 | 
			
		||||
    stw_raw(w ++, N810_BLIZZARD_RESET_GPIO);	/* TODO: n800 s16 nreset_gpio */
 | 
			
		||||
    stw_raw(w ++, 24);				/* u8 data_lines */
 | 
			
		||||
    stw_p(w++, N810_BLIZZARD_RESET_GPIO);	/* TODO: n800 s16 nreset_gpio */
 | 
			
		||||
    stw_p(w++, 24);				/* u8 data_lines */
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_CBUS);		/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 8);				/* u16 len */
 | 
			
		||||
    stw_raw(w ++, N8X0_CBUS_CLK_GPIO);		/* s16 clk_gpio */
 | 
			
		||||
    stw_raw(w ++, N8X0_CBUS_DAT_GPIO);		/* s16 dat_gpio */
 | 
			
		||||
    stw_raw(w ++, N8X0_CBUS_SEL_GPIO);		/* s16 sel_gpio */
 | 
			
		||||
    w ++;
 | 
			
		||||
    stw_p(w++, OMAP_TAG_CBUS);			/* u16 tag */
 | 
			
		||||
    stw_p(w++, 8);				/* u16 len */
 | 
			
		||||
    stw_p(w++, N8X0_CBUS_CLK_GPIO);		/* s16 clk_gpio */
 | 
			
		||||
    stw_p(w++, N8X0_CBUS_DAT_GPIO);		/* s16 dat_gpio */
 | 
			
		||||
    stw_p(w++, N8X0_CBUS_SEL_GPIO);		/* s16 sel_gpio */
 | 
			
		||||
    w++;
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);	/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 4);				/* u16 len */
 | 
			
		||||
    stw_raw(w ++, N8X0_RETU_GPIO);		/* s16 retu_irq_gpio */
 | 
			
		||||
    stw_raw(w ++, N8X0_TAHVO_GPIO);		/* s16 tahvo_irq_gpio */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_EM_ASIC_BB5);		/* u16 tag */
 | 
			
		||||
    stw_p(w++, 4);				/* u16 len */
 | 
			
		||||
    stw_p(w++, N8X0_RETU_GPIO);			/* s16 retu_irq_gpio */
 | 
			
		||||
    stw_p(w++, N8X0_TAHVO_GPIO);		/* s16 tahvo_irq_gpio */
 | 
			
		||||
 | 
			
		||||
    gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
 | 
			
		||||
    for (; gpiosw->name; gpiosw ++) {
 | 
			
		||||
        stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
 | 
			
		||||
        stw_raw(w ++, 20);			/* u16 len */
 | 
			
		||||
    for (; gpiosw->name; gpiosw++) {
 | 
			
		||||
        stw_p(w++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
 | 
			
		||||
        stw_p(w++, 20);				/* u16 len */
 | 
			
		||||
        strcpy((void *) w, gpiosw->name);	/* char name[12] */
 | 
			
		||||
        w += 6;
 | 
			
		||||
        stw_raw(w ++, gpiosw->line);		/* u16 gpio */
 | 
			
		||||
        stw_raw(w ++, gpiosw->type);
 | 
			
		||||
        stw_raw(w ++, 0);
 | 
			
		||||
        stw_raw(w ++, 0);
 | 
			
		||||
        stw_p(w++, gpiosw->line);		/* u16 gpio */
 | 
			
		||||
        stw_p(w++, gpiosw->type);
 | 
			
		||||
        stw_p(w++, 0);
 | 
			
		||||
        stw_p(w++, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_NOKIA_BT);		/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 12);				/* u16 len */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_NOKIA_BT);		/* u16 tag */
 | 
			
		||||
    stw_p(w++, 12);				/* u16 len */
 | 
			
		||||
    b = (void *) w;
 | 
			
		||||
    stb_raw(b ++, 0x01);			/* u8 chip_type	(CSR) */
 | 
			
		||||
    stb_raw(b ++, N8X0_BT_WKUP_GPIO);		/* u8 bt_wakeup_gpio */
 | 
			
		||||
    stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);	/* u8 host_wakeup_gpio */
 | 
			
		||||
    stb_raw(b ++, N8X0_BT_RESET_GPIO);		/* u8 reset_gpio */
 | 
			
		||||
    stb_raw(b ++, BT_UART + 1);			/* u8 bt_uart */
 | 
			
		||||
    stb_p(b++, 0x01);				/* u8 chip_type	(CSR) */
 | 
			
		||||
    stb_p(b++, N8X0_BT_WKUP_GPIO);		/* u8 bt_wakeup_gpio */
 | 
			
		||||
    stb_p(b++, N8X0_BT_HOST_WKUP_GPIO);		/* u8 host_wakeup_gpio */
 | 
			
		||||
    stb_p(b++, N8X0_BT_RESET_GPIO);		/* u8 reset_gpio */
 | 
			
		||||
    stb_p(b++, BT_UART + 1);			/* u8 bt_uart */
 | 
			
		||||
    memcpy(b, &n8x0_bd_addr, 6);		/* u8 bd_addr[6] */
 | 
			
		||||
    b += 6;
 | 
			
		||||
    stb_raw(b ++, 0x02);			/* u8 bt_sysclk (38.4) */
 | 
			
		||||
    stb_p(b++, 0x02);				/* u8 bt_sysclk (38.4) */
 | 
			
		||||
    w = (void *) b;
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);	/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 8);				/* u16 len */
 | 
			
		||||
    stw_raw(w ++, 0x25);			/* u8 chip_type */
 | 
			
		||||
    stw_raw(w ++, N8X0_WLAN_PWR_GPIO);		/* s16 power_gpio */
 | 
			
		||||
    stw_raw(w ++, N8X0_WLAN_IRQ_GPIO);		/* s16 irq_gpio */
 | 
			
		||||
    stw_raw(w ++, -1);				/* s16 spi_cs_gpio */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_WLAN_CX3110X);		/* u16 tag */
 | 
			
		||||
    stw_p(w++, 8);				/* u16 len */
 | 
			
		||||
    stw_p(w++, 0x25);				/* u8 chip_type */
 | 
			
		||||
    stw_p(w++, N8X0_WLAN_PWR_GPIO);		/* s16 power_gpio */
 | 
			
		||||
    stw_p(w++, N8X0_WLAN_IRQ_GPIO);		/* s16 irq_gpio */
 | 
			
		||||
    stw_p(w++, -1);				/* s16 spi_cs_gpio */
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_MMC);		/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 16);				/* u16 len */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_MMC);			/* u16 tag */
 | 
			
		||||
    stw_p(w++, 16);				/* u16 len */
 | 
			
		||||
    if (model == 810) {
 | 
			
		||||
        stw_raw(w ++, 0x23f);			/* unsigned flags */
 | 
			
		||||
        stw_raw(w ++, -1);			/* s16 power_pin */
 | 
			
		||||
        stw_raw(w ++, -1);			/* s16 switch_pin */
 | 
			
		||||
        stw_raw(w ++, -1);			/* s16 wp_pin */
 | 
			
		||||
        stw_raw(w ++, 0x240);			/* unsigned flags */
 | 
			
		||||
        stw_raw(w ++, 0xc000);			/* s16 power_pin */
 | 
			
		||||
        stw_raw(w ++, 0x0248);			/* s16 switch_pin */
 | 
			
		||||
        stw_raw(w ++, 0xc000);			/* s16 wp_pin */
 | 
			
		||||
        stw_p(w++, 0x23f);			/* unsigned flags */
 | 
			
		||||
        stw_p(w++, -1);				/* s16 power_pin */
 | 
			
		||||
        stw_p(w++, -1);				/* s16 switch_pin */
 | 
			
		||||
        stw_p(w++, -1);				/* s16 wp_pin */
 | 
			
		||||
        stw_p(w++, 0x240);			/* unsigned flags */
 | 
			
		||||
        stw_p(w++, 0xc000);			/* s16 power_pin */
 | 
			
		||||
        stw_p(w++, 0x0248);			/* s16 switch_pin */
 | 
			
		||||
        stw_p(w++, 0xc000);			/* s16 wp_pin */
 | 
			
		||||
    } else {
 | 
			
		||||
        stw_raw(w ++, 0xf);			/* unsigned flags */
 | 
			
		||||
        stw_raw(w ++, -1);			/* s16 power_pin */
 | 
			
		||||
        stw_raw(w ++, -1);			/* s16 switch_pin */
 | 
			
		||||
        stw_raw(w ++, -1);			/* s16 wp_pin */
 | 
			
		||||
        stw_raw(w ++, 0);			/* unsigned flags */
 | 
			
		||||
        stw_raw(w ++, 0);			/* s16 power_pin */
 | 
			
		||||
        stw_raw(w ++, 0);			/* s16 switch_pin */
 | 
			
		||||
        stw_raw(w ++, 0);			/* s16 wp_pin */
 | 
			
		||||
        stw_p(w++, 0xf);			/* unsigned flags */
 | 
			
		||||
        stw_p(w++, -1);				/* s16 power_pin */
 | 
			
		||||
        stw_p(w++, -1);				/* s16 switch_pin */
 | 
			
		||||
        stw_p(w++, -1);				/* s16 wp_pin */
 | 
			
		||||
        stw_p(w++, 0);				/* unsigned flags */
 | 
			
		||||
        stw_p(w++, 0);				/* s16 power_pin */
 | 
			
		||||
        stw_p(w++, 0);				/* s16 switch_pin */
 | 
			
		||||
        stw_p(w++, 0);				/* s16 wp_pin */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_TEA5761);		/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 4);				/* u16 len */
 | 
			
		||||
    stw_raw(w ++, N8X0_TEA5761_CS_GPIO);	/* u16 enable_gpio */
 | 
			
		||||
    w ++;
 | 
			
		||||
    stw_p(w++, OMAP_TAG_TEA5761);		/* u16 tag */
 | 
			
		||||
    stw_p(w++, 4);				/* u16 len */
 | 
			
		||||
    stw_p(w++, N8X0_TEA5761_CS_GPIO);		/* u16 enable_gpio */
 | 
			
		||||
    w++;
 | 
			
		||||
 | 
			
		||||
    partition = (model == 810) ? n810_part_info : n800_part_info;
 | 
			
		||||
    for (; partition->name; partition ++) {
 | 
			
		||||
        stw_raw(w ++, OMAP_TAG_PARTITION);	/* u16 tag */
 | 
			
		||||
        stw_raw(w ++, 28);			/* u16 len */
 | 
			
		||||
    for (; partition->name; partition++) {
 | 
			
		||||
        stw_p(w++, OMAP_TAG_PARTITION);		/* u16 tag */
 | 
			
		||||
        stw_p(w++, 28);				/* u16 len */
 | 
			
		||||
        strcpy((void *) w, partition->name);	/* char name[16] */
 | 
			
		||||
        l = (void *) (w + 8);
 | 
			
		||||
        stl_raw(l ++, partition->size);		/* unsigned int size */
 | 
			
		||||
        stl_raw(l ++, partition->offset);	/* unsigned int offset */
 | 
			
		||||
        stl_raw(l ++, partition->mask);		/* unsigned int mask_flags */
 | 
			
		||||
        stl_p(l++, partition->size);		/* unsigned int size */
 | 
			
		||||
        stl_p(l++, partition->offset);		/* unsigned int offset */
 | 
			
		||||
        stl_p(l++, partition->mask);		/* unsigned int mask_flags */
 | 
			
		||||
        w = (void *) l;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_BOOT_REASON);	/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 12);				/* u16 len */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_BOOT_REASON);		/* u16 tag */
 | 
			
		||||
    stw_p(w++, 12);				/* u16 len */
 | 
			
		||||
#if 0
 | 
			
		||||
    strcpy((void *) w, "por");			/* char reason_str[12] */
 | 
			
		||||
    strcpy((void *) w, "charger");		/* char reason_str[12] */
 | 
			
		||||
@@ -1242,15 +1260,15 @@ static int n8x0_atag_setup(void *p, int model)
 | 
			
		||||
    w += 6;
 | 
			
		||||
 | 
			
		||||
    tag = (model == 810) ? "RX-44" : "RX-34";
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 24);				/* u16 len */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_VERSION_STR);		/* u16 tag */
 | 
			
		||||
    stw_p(w++, 24);				/* u16 len */
 | 
			
		||||
    strcpy((void *) w, "product");		/* char component[12] */
 | 
			
		||||
    w += 6;
 | 
			
		||||
    strcpy((void *) w, tag);			/* char version[12] */
 | 
			
		||||
    w += 6;
 | 
			
		||||
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 24);				/* u16 len */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_VERSION_STR);		/* u16 tag */
 | 
			
		||||
    stw_p(w++, 24);				/* u16 len */
 | 
			
		||||
    strcpy((void *) w, "hw-build");		/* char component[12] */
 | 
			
		||||
    w += 6;
 | 
			
		||||
    strcpy((void *) w, "QEMU ");
 | 
			
		||||
@@ -1258,8 +1276,8 @@ static int n8x0_atag_setup(void *p, int model)
 | 
			
		||||
    w += 6;
 | 
			
		||||
 | 
			
		||||
    tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
 | 
			
		||||
    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
 | 
			
		||||
    stw_raw(w ++, 24);				/* u16 len */
 | 
			
		||||
    stw_p(w++, OMAP_TAG_VERSION_STR);		/* u16 tag */
 | 
			
		||||
    stw_p(w++, 24);				/* u16 len */
 | 
			
		||||
    strcpy((void *) w, "nolo");			/* char component[12] */
 | 
			
		||||
    w += 6;
 | 
			
		||||
    strcpy((void *) w, tag);			/* char version[12] */
 | 
			
		||||
@@ -1315,9 +1333,9 @@ static void n8x0_init(MachineState *machine,
 | 
			
		||||
    n8x0_gpio_setup(s);
 | 
			
		||||
    n8x0_nand_setup(s);
 | 
			
		||||
    n8x0_i2c_setup(s);
 | 
			
		||||
    if (model == 800)
 | 
			
		||||
    if (model == 800) {
 | 
			
		||||
        n800_tsc_kbd_setup(s);
 | 
			
		||||
    else if (model == 810) {
 | 
			
		||||
    } else if (model == 810) {
 | 
			
		||||
        n810_tsc_setup(s);
 | 
			
		||||
        n810_kbd_setup(s);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@
 | 
			
		||||
#include "net/net.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "hw/boards.h"
 | 
			
		||||
#include "hw/loader.h"
 | 
			
		||||
#include "exec/address-spaces.h"
 | 
			
		||||
#include "sysemu/blockdev.h"
 | 
			
		||||
#include "hw/block/flash.h"
 | 
			
		||||
@@ -528,6 +529,18 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
 | 
			
		||||
    daughterboard->init(daughterboard, machine->ram_size, machine->cpu_model,
 | 
			
		||||
                        pic);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * If a bios file was provided, attempt to map it into memory
 | 
			
		||||
     */
 | 
			
		||||
    if (bios_name) {
 | 
			
		||||
        const char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 | 
			
		||||
        if (!fn || load_image_targphys(fn, map[VE_NORFLASH0],
 | 
			
		||||
                                       VEXPRESS_FLASH_SIZE) < 0) {
 | 
			
		||||
            error_report("Could not load ROM image '%s'", bios_name);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Motherboard peripherals: the wiring is the same but the
 | 
			
		||||
     * addresses vary between the legacy and A-Series memory maps.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
obj-y += ioq.o virtio-blk.o
 | 
			
		||||
obj-y += virtio-blk.o
 | 
			
		||||
 
 | 
			
		||||
@@ -1,117 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Linux AIO request queue
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2012 IBM, Corp.
 | 
			
		||||
 * Copyright 2012 Red Hat, Inc. and/or its affiliates
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "ioq.h"
 | 
			
		||||
 | 
			
		||||
void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs)
 | 
			
		||||
{
 | 
			
		||||
    int rc;
 | 
			
		||||
 | 
			
		||||
    ioq->fd = fd;
 | 
			
		||||
    ioq->max_reqs = max_reqs;
 | 
			
		||||
 | 
			
		||||
    memset(&ioq->io_ctx, 0, sizeof ioq->io_ctx);
 | 
			
		||||
    rc = io_setup(max_reqs, &ioq->io_ctx);
 | 
			
		||||
    if (rc != 0) {
 | 
			
		||||
        fprintf(stderr, "ioq io_setup failed %d\n", rc);
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rc = event_notifier_init(&ioq->io_notifier, 0);
 | 
			
		||||
    if (rc != 0) {
 | 
			
		||||
        fprintf(stderr, "ioq io event notifier creation failed %d\n", rc);
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ioq->freelist = g_malloc0(sizeof ioq->freelist[0] * max_reqs);
 | 
			
		||||
    ioq->freelist_idx = 0;
 | 
			
		||||
 | 
			
		||||
    ioq->queue = g_malloc0(sizeof ioq->queue[0] * max_reqs);
 | 
			
		||||
    ioq->queue_idx = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ioq_cleanup(IOQueue *ioq)
 | 
			
		||||
{
 | 
			
		||||
    g_free(ioq->freelist);
 | 
			
		||||
    g_free(ioq->queue);
 | 
			
		||||
 | 
			
		||||
    event_notifier_cleanup(&ioq->io_notifier);
 | 
			
		||||
    io_destroy(ioq->io_ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EventNotifier *ioq_get_notifier(IOQueue *ioq)
 | 
			
		||||
{
 | 
			
		||||
    return &ioq->io_notifier;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct iocb *ioq_get_iocb(IOQueue *ioq)
 | 
			
		||||
{
 | 
			
		||||
    /* Underflow cannot happen since ioq is sized for max_reqs */
 | 
			
		||||
    assert(ioq->freelist_idx != 0);
 | 
			
		||||
 | 
			
		||||
    struct iocb *iocb = ioq->freelist[--ioq->freelist_idx];
 | 
			
		||||
    ioq->queue[ioq->queue_idx++] = iocb;
 | 
			
		||||
    return iocb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb)
 | 
			
		||||
{
 | 
			
		||||
    /* Overflow cannot happen since ioq is sized for max_reqs */
 | 
			
		||||
    assert(ioq->freelist_idx != ioq->max_reqs);
 | 
			
		||||
 | 
			
		||||
    ioq->freelist[ioq->freelist_idx++] = iocb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov,
 | 
			
		||||
                      unsigned int count, long long offset)
 | 
			
		||||
{
 | 
			
		||||
    struct iocb *iocb = ioq_get_iocb(ioq);
 | 
			
		||||
 | 
			
		||||
    if (read) {
 | 
			
		||||
        io_prep_preadv(iocb, ioq->fd, iov, count, offset);
 | 
			
		||||
    } else {
 | 
			
		||||
        io_prep_pwritev(iocb, ioq->fd, iov, count, offset);
 | 
			
		||||
    }
 | 
			
		||||
    io_set_eventfd(iocb, event_notifier_get_fd(&ioq->io_notifier));
 | 
			
		||||
    return iocb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ioq_submit(IOQueue *ioq)
 | 
			
		||||
{
 | 
			
		||||
    int rc = io_submit(ioq->io_ctx, ioq->queue_idx, ioq->queue);
 | 
			
		||||
    ioq->queue_idx = 0; /* reset */
 | 
			
		||||
    return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion,
 | 
			
		||||
                       void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    struct io_event events[ioq->max_reqs];
 | 
			
		||||
    int nevents, i;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        nevents = io_getevents(ioq->io_ctx, 0, ioq->max_reqs, events, NULL);
 | 
			
		||||
    } while (nevents < 0 && errno == EINTR);
 | 
			
		||||
    if (nevents < 0) {
 | 
			
		||||
        return nevents;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < nevents; i++) {
 | 
			
		||||
        ssize_t ret = ((uint64_t)events[i].res2 << 32) | events[i].res;
 | 
			
		||||
 | 
			
		||||
        completion(events[i].obj, ret, opaque);
 | 
			
		||||
        ioq_put_iocb(ioq, events[i].obj);
 | 
			
		||||
    }
 | 
			
		||||
    return nevents;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,57 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Linux AIO request queue
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2012 IBM, Corp.
 | 
			
		||||
 * Copyright 2012 Red Hat, Inc. and/or its affiliates
 | 
			
		||||
 *
 | 
			
		||||
 * 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 IOQ_H
 | 
			
		||||
#define IOQ_H
 | 
			
		||||
 | 
			
		||||
#include <libaio.h>
 | 
			
		||||
#include "qemu/event_notifier.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    int fd;                         /* file descriptor */
 | 
			
		||||
    unsigned int max_reqs;          /* max length of freelist and queue */
 | 
			
		||||
 | 
			
		||||
    io_context_t io_ctx;            /* Linux AIO context */
 | 
			
		||||
    EventNotifier io_notifier;      /* Linux AIO eventfd */
 | 
			
		||||
 | 
			
		||||
    /* Requests can complete in any order so a free list is necessary to manage
 | 
			
		||||
     * available iocbs.
 | 
			
		||||
     */
 | 
			
		||||
    struct iocb **freelist;         /* free iocbs */
 | 
			
		||||
    unsigned int freelist_idx;
 | 
			
		||||
 | 
			
		||||
    /* Multiple requests are queued up before submitting them all in one go */
 | 
			
		||||
    struct iocb **queue;            /* queued iocbs */
 | 
			
		||||
    unsigned int queue_idx;
 | 
			
		||||
} IOQueue;
 | 
			
		||||
 | 
			
		||||
void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs);
 | 
			
		||||
void ioq_cleanup(IOQueue *ioq);
 | 
			
		||||
EventNotifier *ioq_get_notifier(IOQueue *ioq);
 | 
			
		||||
struct iocb *ioq_get_iocb(IOQueue *ioq);
 | 
			
		||||
void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb);
 | 
			
		||||
struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov,
 | 
			
		||||
                      unsigned int count, long long offset);
 | 
			
		||||
int ioq_submit(IOQueue *ioq);
 | 
			
		||||
 | 
			
		||||
static inline unsigned int ioq_num_queued(IOQueue *ioq)
 | 
			
		||||
{
 | 
			
		||||
    return ioq->queue_idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef void IOQueueCompletion(struct iocb *iocb, ssize_t ret, void *opaque);
 | 
			
		||||
int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion,
 | 
			
		||||
                       void *opaque);
 | 
			
		||||
 | 
			
		||||
#endif /* IOQ_H */
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
#include "qemu/thread.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
#include "hw/virtio/dataplane/vring.h"
 | 
			
		||||
#include "ioq.h"
 | 
			
		||||
#include "block/block.h"
 | 
			
		||||
#include "hw/virtio/virtio-blk.h"
 | 
			
		||||
#include "virtio-blk.h"
 | 
			
		||||
@@ -25,20 +24,14 @@
 | 
			
		||||
#include "hw/virtio/virtio-bus.h"
 | 
			
		||||
#include "qom/object_interfaces.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    SEG_MAX = 126,                  /* maximum number of I/O segments */
 | 
			
		||||
    VRING_MAX = SEG_MAX + 2,        /* maximum number of vring descriptors */
 | 
			
		||||
    REQ_MAX = VRING_MAX,            /* maximum number of requests in the vring,
 | 
			
		||||
                                     * is VRING_MAX / 2 with traditional and
 | 
			
		||||
                                     * VRING_MAX with indirect descriptors */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    struct iocb iocb;               /* Linux AIO control block */
 | 
			
		||||
    VirtIOBlockDataPlane *s;
 | 
			
		||||
    QEMUIOVector *inhdr;            /* iovecs for virtio_blk_inhdr */
 | 
			
		||||
    VirtQueueElement *elem;         /* saved data from the virtqueue */
 | 
			
		||||
    struct iovec *bounce_iov;       /* used if guest buffers are unaligned */
 | 
			
		||||
    QEMUIOVector *read_qiov;        /* for read completion /w bounce buffer */
 | 
			
		||||
    QEMUIOVector qiov;              /* original request iovecs */
 | 
			
		||||
    struct iovec bounce_iov;        /* used if guest buffers are unaligned */
 | 
			
		||||
    QEMUIOVector bounce_qiov;       /* bounce buffer iovecs */
 | 
			
		||||
    bool read;                      /* read or write? */
 | 
			
		||||
} VirtIOBlockRequest;
 | 
			
		||||
 | 
			
		||||
struct VirtIOBlockDataPlane {
 | 
			
		||||
@@ -47,7 +40,6 @@ struct VirtIOBlockDataPlane {
 | 
			
		||||
    bool stopping;
 | 
			
		||||
 | 
			
		||||
    VirtIOBlkConf *blk;
 | 
			
		||||
    int fd;                         /* image file descriptor */
 | 
			
		||||
 | 
			
		||||
    VirtIODevice *vdev;
 | 
			
		||||
    Vring vring;                    /* virtqueue vring */
 | 
			
		||||
@@ -61,16 +53,8 @@ struct VirtIOBlockDataPlane {
 | 
			
		||||
    IOThread *iothread;
 | 
			
		||||
    IOThread internal_iothread_obj;
 | 
			
		||||
    AioContext *ctx;
 | 
			
		||||
    EventNotifier io_notifier;      /* Linux AIO completion */
 | 
			
		||||
    EventNotifier host_notifier;    /* doorbell */
 | 
			
		||||
 | 
			
		||||
    IOQueue ioqueue;                /* Linux AIO queue (should really be per
 | 
			
		||||
                                       IOThread) */
 | 
			
		||||
    VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the
 | 
			
		||||
                                             queue */
 | 
			
		||||
 | 
			
		||||
    unsigned int num_reqs;
 | 
			
		||||
 | 
			
		||||
    /* Operation blocker on BDS */
 | 
			
		||||
    Error *blocker;
 | 
			
		||||
};
 | 
			
		||||
@@ -85,33 +69,28 @@ static void notify_guest(VirtIOBlockDataPlane *s)
 | 
			
		||||
    event_notifier_set(s->guest_notifier);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque)
 | 
			
		||||
static void complete_rdwr(void *opaque, int ret)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBlockDataPlane *s = opaque;
 | 
			
		||||
    VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb);
 | 
			
		||||
    VirtIOBlockRequest *req = opaque;
 | 
			
		||||
    struct virtio_blk_inhdr hdr;
 | 
			
		||||
    int len;
 | 
			
		||||
 | 
			
		||||
    if (likely(ret >= 0)) {
 | 
			
		||||
    if (likely(ret == 0)) {
 | 
			
		||||
        hdr.status = VIRTIO_BLK_S_OK;
 | 
			
		||||
        len = ret;
 | 
			
		||||
        len = req->qiov.size;
 | 
			
		||||
    } else {
 | 
			
		||||
        hdr.status = VIRTIO_BLK_S_IOERR;
 | 
			
		||||
        len = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    trace_virtio_blk_data_plane_complete_request(s, req->elem->index, ret);
 | 
			
		||||
    trace_virtio_blk_data_plane_complete_request(req->s, req->elem->index, ret);
 | 
			
		||||
 | 
			
		||||
    if (req->read_qiov) {
 | 
			
		||||
        assert(req->bounce_iov);
 | 
			
		||||
        qemu_iovec_from_buf(req->read_qiov, 0, req->bounce_iov->iov_base, len);
 | 
			
		||||
        qemu_iovec_destroy(req->read_qiov);
 | 
			
		||||
        g_slice_free(QEMUIOVector, req->read_qiov);
 | 
			
		||||
    if (req->read && req->bounce_iov.iov_base) {
 | 
			
		||||
        qemu_iovec_from_buf(&req->qiov, 0, req->bounce_iov.iov_base, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (req->bounce_iov) {
 | 
			
		||||
        qemu_vfree(req->bounce_iov->iov_base);
 | 
			
		||||
        g_slice_free(struct iovec, req->bounce_iov);
 | 
			
		||||
    if (req->bounce_iov.iov_base) {
 | 
			
		||||
        qemu_vfree(req->bounce_iov.iov_base);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_iovec_from_buf(req->inhdr, 0, &hdr, sizeof(hdr));
 | 
			
		||||
@@ -122,9 +101,9 @@ static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque)
 | 
			
		||||
     * written to, but for virtio-blk it seems to be the number of bytes
 | 
			
		||||
     * transferred plus the status bytes.
 | 
			
		||||
     */
 | 
			
		||||
    vring_push(&s->vring, req->elem, len + sizeof(hdr));
 | 
			
		||||
    req->elem = NULL;
 | 
			
		||||
    s->num_reqs--;
 | 
			
		||||
    vring_push(&req->s->vring, req->elem, len + sizeof(hdr));
 | 
			
		||||
    notify_guest(req->s);
 | 
			
		||||
    g_slice_free(VirtIOBlockRequest, req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void complete_request_early(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
 | 
			
		||||
@@ -155,51 +134,87 @@ static void do_get_id_cmd(VirtIOBlockDataPlane *s,
 | 
			
		||||
    complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read,
 | 
			
		||||
                       struct iovec *iov, unsigned iov_cnt,
 | 
			
		||||
                       long long offset, VirtQueueElement *elem,
 | 
			
		||||
                       QEMUIOVector *inhdr)
 | 
			
		||||
static void do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read,
 | 
			
		||||
                        struct iovec *iov, unsigned iov_cnt,
 | 
			
		||||
                        int64_t sector_num, VirtQueueElement *elem,
 | 
			
		||||
                        QEMUIOVector *inhdr)
 | 
			
		||||
{
 | 
			
		||||
    struct iocb *iocb;
 | 
			
		||||
    QEMUIOVector qiov;
 | 
			
		||||
    struct iovec *bounce_iov = NULL;
 | 
			
		||||
    QEMUIOVector *read_qiov = NULL;
 | 
			
		||||
    VirtIOBlockRequest *req = g_slice_new0(VirtIOBlockRequest);
 | 
			
		||||
    QEMUIOVector *qiov;
 | 
			
		||||
    int nb_sectors;
 | 
			
		||||
 | 
			
		||||
    qemu_iovec_init_external(&qiov, iov, iov_cnt);
 | 
			
		||||
    if (!bdrv_qiov_is_aligned(s->blk->conf.bs, &qiov)) {
 | 
			
		||||
        void *bounce_buffer = qemu_blockalign(s->blk->conf.bs, qiov.size);
 | 
			
		||||
    /* Fill in virtio block metadata needed for completion */
 | 
			
		||||
    req->s = s;
 | 
			
		||||
    req->elem = elem;
 | 
			
		||||
    req->inhdr = inhdr;
 | 
			
		||||
    req->read = read;
 | 
			
		||||
    qemu_iovec_init_external(&req->qiov, iov, iov_cnt);
 | 
			
		||||
 | 
			
		||||
        if (read) {
 | 
			
		||||
            /* Need to copy back from bounce buffer on completion */
 | 
			
		||||
            read_qiov = g_slice_new(QEMUIOVector);
 | 
			
		||||
            qemu_iovec_init(read_qiov, iov_cnt);
 | 
			
		||||
            qemu_iovec_concat_iov(read_qiov, iov, iov_cnt, 0, qiov.size);
 | 
			
		||||
        } else {
 | 
			
		||||
            qemu_iovec_to_buf(&qiov, 0, bounce_buffer, qiov.size);
 | 
			
		||||
    qiov = &req->qiov;
 | 
			
		||||
 | 
			
		||||
    if (!bdrv_qiov_is_aligned(s->blk->conf.bs, qiov)) {
 | 
			
		||||
        void *bounce_buffer = qemu_blockalign(s->blk->conf.bs, qiov->size);
 | 
			
		||||
 | 
			
		||||
        /* Populate bounce buffer with data for writes */
 | 
			
		||||
        if (!read) {
 | 
			
		||||
            qemu_iovec_to_buf(qiov, 0, bounce_buffer, qiov->size);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Redirect I/O to aligned bounce buffer */
 | 
			
		||||
        bounce_iov = g_slice_new(struct iovec);
 | 
			
		||||
        bounce_iov->iov_base = bounce_buffer;
 | 
			
		||||
        bounce_iov->iov_len = qiov.size;
 | 
			
		||||
        iov = bounce_iov;
 | 
			
		||||
        iov_cnt = 1;
 | 
			
		||||
        req->bounce_iov.iov_base = bounce_buffer;
 | 
			
		||||
        req->bounce_iov.iov_len = qiov->size;
 | 
			
		||||
        qemu_iovec_init_external(&req->bounce_qiov, &req->bounce_iov, 1);
 | 
			
		||||
        qiov = &req->bounce_qiov;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    iocb = ioq_rdwr(&s->ioqueue, read, iov, iov_cnt, offset);
 | 
			
		||||
    nb_sectors = qiov->size / BDRV_SECTOR_SIZE;
 | 
			
		||||
 | 
			
		||||
    /* Fill in virtio block metadata needed for completion */
 | 
			
		||||
    VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb);
 | 
			
		||||
    req->elem = elem;
 | 
			
		||||
    req->inhdr = inhdr;
 | 
			
		||||
    req->bounce_iov = bounce_iov;
 | 
			
		||||
    req->read_qiov = read_qiov;
 | 
			
		||||
    return 0;
 | 
			
		||||
    if (read) {
 | 
			
		||||
        bdrv_aio_readv(s->blk->conf.bs, sector_num, qiov, nb_sectors,
 | 
			
		||||
                       complete_rdwr, req);
 | 
			
		||||
    } else {
 | 
			
		||||
        bdrv_aio_writev(s->blk->conf.bs, sector_num, qiov, nb_sectors,
 | 
			
		||||
                        complete_rdwr, req);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int process_request(IOQueue *ioq, VirtQueueElement *elem)
 | 
			
		||||
static void complete_flush(void *opaque, int ret)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBlockRequest *req = opaque;
 | 
			
		||||
    unsigned char status;
 | 
			
		||||
 | 
			
		||||
    if (ret == 0) {
 | 
			
		||||
        status = VIRTIO_BLK_S_OK;
 | 
			
		||||
    } else {
 | 
			
		||||
        status = VIRTIO_BLK_S_IOERR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    complete_request_early(req->s, req->elem, req->inhdr, status);
 | 
			
		||||
    g_slice_free(VirtIOBlockRequest, req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void do_flush_cmd(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
 | 
			
		||||
                         QEMUIOVector *inhdr)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBlockRequest *req = g_slice_new(VirtIOBlockRequest);
 | 
			
		||||
    req->s = s;
 | 
			
		||||
    req->elem = elem;
 | 
			
		||||
    req->inhdr = inhdr;
 | 
			
		||||
 | 
			
		||||
    bdrv_aio_flush(s->blk->conf.bs, complete_flush, req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void do_scsi_cmd(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
 | 
			
		||||
                        QEMUIOVector *inhdr)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
 | 
			
		||||
    status = virtio_blk_handle_scsi_req(VIRTIO_BLK(s->vdev), elem);
 | 
			
		||||
    complete_request_early(s, elem, inhdr, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int process_request(VirtIOBlockDataPlane *s, VirtQueueElement *elem)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBlockDataPlane *s = container_of(ioq, VirtIOBlockDataPlane, ioqueue);
 | 
			
		||||
    struct iovec *iov = elem->out_sg;
 | 
			
		||||
    struct iovec *in_iov = elem->in_sg;
 | 
			
		||||
    unsigned out_num = elem->out_num;
 | 
			
		||||
@@ -234,25 +249,23 @@ static int process_request(IOQueue *ioq, VirtQueueElement *elem)
 | 
			
		||||
 | 
			
		||||
    switch (outhdr.type) {
 | 
			
		||||
    case VIRTIO_BLK_T_IN:
 | 
			
		||||
        do_rdwr_cmd(s, true, in_iov, in_num, outhdr.sector * 512, elem, inhdr);
 | 
			
		||||
        do_rdwr_cmd(s, true, in_iov, in_num,
 | 
			
		||||
                    outhdr.sector * 512 / BDRV_SECTOR_SIZE,
 | 
			
		||||
                    elem, inhdr);
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    case VIRTIO_BLK_T_OUT:
 | 
			
		||||
        do_rdwr_cmd(s, false, iov, out_num, outhdr.sector * 512, elem, inhdr);
 | 
			
		||||
        do_rdwr_cmd(s, false, iov, out_num,
 | 
			
		||||
                    outhdr.sector * 512 / BDRV_SECTOR_SIZE,
 | 
			
		||||
                    elem, inhdr);
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    case VIRTIO_BLK_T_SCSI_CMD:
 | 
			
		||||
        /* TODO support SCSI commands */
 | 
			
		||||
        complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_UNSUPP);
 | 
			
		||||
        do_scsi_cmd(s, elem, inhdr);
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    case VIRTIO_BLK_T_FLUSH:
 | 
			
		||||
        /* TODO fdsync not supported by Linux AIO, do it synchronously here! */
 | 
			
		||||
        if (qemu_fdatasync(s->fd) < 0) {
 | 
			
		||||
            complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_IOERR);
 | 
			
		||||
        } else {
 | 
			
		||||
            complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_OK);
 | 
			
		||||
        }
 | 
			
		||||
        do_flush_cmd(s, elem, inhdr);
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    case VIRTIO_BLK_T_GET_ID:
 | 
			
		||||
@@ -274,7 +287,6 @@ static void handle_notify(EventNotifier *e)
 | 
			
		||||
 | 
			
		||||
    VirtQueueElement *elem;
 | 
			
		||||
    int ret;
 | 
			
		||||
    unsigned int num_queued;
 | 
			
		||||
 | 
			
		||||
    event_notifier_test_and_clear(&s->host_notifier);
 | 
			
		||||
    for (;;) {
 | 
			
		||||
@@ -291,7 +303,7 @@ static void handle_notify(EventNotifier *e)
 | 
			
		||||
            trace_virtio_blk_data_plane_process_request(s, elem->out_num,
 | 
			
		||||
                                                        elem->in_num, elem->index);
 | 
			
		||||
 | 
			
		||||
            if (process_request(&s->ioqueue, elem) < 0) {
 | 
			
		||||
            if (process_request(s, elem) < 0) {
 | 
			
		||||
                vring_set_broken(&s->vring);
 | 
			
		||||
                vring_free_element(elem);
 | 
			
		||||
                ret = -EFAULT;
 | 
			
		||||
@@ -306,44 +318,10 @@ static void handle_notify(EventNotifier *e)
 | 
			
		||||
            if (vring_enable_notification(s->vdev, &s->vring)) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        } else { /* ret == -ENOBUFS or fatal error, iovecs[] is depleted */
 | 
			
		||||
            /* Since there are no iovecs[] left, stop processing for now.  Do
 | 
			
		||||
             * not re-enable guest->host notifies since the I/O completion
 | 
			
		||||
             * handler knows to check for more vring descriptors anyway.
 | 
			
		||||
             */
 | 
			
		||||
        } else { /* fatal error */
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    num_queued = ioq_num_queued(&s->ioqueue);
 | 
			
		||||
    if (num_queued > 0) {
 | 
			
		||||
        s->num_reqs += num_queued;
 | 
			
		||||
 | 
			
		||||
        int rc = ioq_submit(&s->ioqueue);
 | 
			
		||||
        if (unlikely(rc < 0)) {
 | 
			
		||||
            fprintf(stderr, "ioq_submit failed %d\n", rc);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_io(EventNotifier *e)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
 | 
			
		||||
                                           io_notifier);
 | 
			
		||||
 | 
			
		||||
    event_notifier_test_and_clear(&s->io_notifier);
 | 
			
		||||
    if (ioq_run_completion(&s->ioqueue, complete_request, s) > 0) {
 | 
			
		||||
        notify_guest(s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If there were more requests than iovecs, the vring will not be empty yet
 | 
			
		||||
     * so check again.  There should now be enough resources to process more
 | 
			
		||||
     * requests.
 | 
			
		||||
     */
 | 
			
		||||
    if (unlikely(vring_more_avail(&s->vring))) {
 | 
			
		||||
        handle_notify(&s->host_notifier);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Context: QEMU global mutex held */
 | 
			
		||||
@@ -352,7 +330,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
 | 
			
		||||
                                  Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBlockDataPlane *s;
 | 
			
		||||
    int fd;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
 | 
			
		||||
    *dataplane = NULL;
 | 
			
		||||
@@ -361,18 +338,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (blk->scsi) {
 | 
			
		||||
        error_setg(errp,
 | 
			
		||||
                   "device is incompatible with x-data-plane, use scsi=off");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (blk->config_wce) {
 | 
			
		||||
        error_setg(errp, "device is incompatible with x-data-plane, "
 | 
			
		||||
                         "use config-wce=off");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If dataplane is (re-)enabled while the guest is running there could be
 | 
			
		||||
     * block jobs that can conflict.
 | 
			
		||||
     */
 | 
			
		||||
@@ -383,16 +348,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fd = raw_get_aio_fd(blk->conf.bs);
 | 
			
		||||
    if (fd < 0) {
 | 
			
		||||
        error_setg(errp, "drive is incompatible with x-data-plane, "
 | 
			
		||||
                         "use format=raw,cache=none,aio=native");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s = g_new0(VirtIOBlockDataPlane, 1);
 | 
			
		||||
    s->vdev = vdev;
 | 
			
		||||
    s->fd = fd;
 | 
			
		||||
    s->blk = blk;
 | 
			
		||||
 | 
			
		||||
    if (blk->iothread) {
 | 
			
		||||
@@ -437,7 +394,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 | 
			
		||||
    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
 | 
			
		||||
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
 | 
			
		||||
    VirtQueue *vq;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (s->started) {
 | 
			
		||||
        return;
 | 
			
		||||
@@ -470,24 +426,18 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 | 
			
		||||
    }
 | 
			
		||||
    s->host_notifier = *virtio_queue_get_host_notifier(vq);
 | 
			
		||||
 | 
			
		||||
    /* Set up ioqueue */
 | 
			
		||||
    ioq_init(&s->ioqueue, s->fd, REQ_MAX);
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(s->requests); i++) {
 | 
			
		||||
        ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb);
 | 
			
		||||
    }
 | 
			
		||||
    s->io_notifier = *ioq_get_notifier(&s->ioqueue);
 | 
			
		||||
 | 
			
		||||
    s->starting = false;
 | 
			
		||||
    s->started = true;
 | 
			
		||||
    trace_virtio_blk_data_plane_start(s);
 | 
			
		||||
 | 
			
		||||
    bdrv_set_aio_context(s->blk->conf.bs, s->ctx);
 | 
			
		||||
 | 
			
		||||
    /* Kick right away to begin processing requests already in vring */
 | 
			
		||||
    event_notifier_set(virtio_queue_get_host_notifier(vq));
 | 
			
		||||
 | 
			
		||||
    /* Get this show started by hooking up our callbacks */
 | 
			
		||||
    aio_context_acquire(s->ctx);
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -507,13 +457,8 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
 | 
			
		||||
    /* Stop notifications for new requests from guest */
 | 
			
		||||
    aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
 | 
			
		||||
 | 
			
		||||
    /* Complete pending requests */
 | 
			
		||||
    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);
 | 
			
		||||
    /* Drain and switch bs back to the QEMU main loop */
 | 
			
		||||
    bdrv_set_aio_context(s->blk->conf.bs, qemu_get_aio_context());
 | 
			
		||||
 | 
			
		||||
    aio_context_release(s->ctx);
 | 
			
		||||
 | 
			
		||||
@@ -522,7 +467,6 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
 | 
			
		||||
     */
 | 
			
		||||
    vring_teardown(&s->vring, s->vdev, 0);
 | 
			
		||||
 | 
			
		||||
    ioq_cleanup(&s->ioqueue);
 | 
			
		||||
    k->set_host_notifier(qbus->parent, 0, false);
 | 
			
		||||
 | 
			
		||||
    /* Clean up guest notifier (irq) */
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,6 @@ typedef struct VirtIOBlockReq
 | 
			
		||||
    VirtQueueElement elem;
 | 
			
		||||
    struct virtio_blk_inhdr *in;
 | 
			
		||||
    struct virtio_blk_outhdr *out;
 | 
			
		||||
    struct virtio_scsi_inhdr *scsi;
 | 
			
		||||
    QEMUIOVector qiov;
 | 
			
		||||
    struct VirtIOBlockReq *next;
 | 
			
		||||
    BlockAcctCookie acct;
 | 
			
		||||
@@ -125,13 +124,15 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 | 
			
		||||
int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
 | 
			
		||||
                               VirtQueueElement *elem)
 | 
			
		||||
{
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
    int ret;
 | 
			
		||||
    int i;
 | 
			
		||||
#endif
 | 
			
		||||
    int status = VIRTIO_BLK_S_OK;
 | 
			
		||||
    struct virtio_scsi_inhdr *scsi = NULL;
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
    int i;
 | 
			
		||||
    struct sg_io_hdr hdr;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * We require at least one output segment each for the virtio_blk_outhdr
 | 
			
		||||
@@ -140,19 +141,18 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 | 
			
		||||
     * We also at least require the virtio_blk_inhdr, the virtio_scsi_inhdr
 | 
			
		||||
     * and the sense buffer pointer in the input segments.
 | 
			
		||||
     */
 | 
			
		||||
    if (req->elem.out_num < 2 || req->elem.in_num < 3) {
 | 
			
		||||
        virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
 | 
			
		||||
        g_free(req);
 | 
			
		||||
        return;
 | 
			
		||||
    if (elem->out_num < 2 || elem->in_num < 3) {
 | 
			
		||||
        status = VIRTIO_BLK_S_IOERR;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * The scsi inhdr is placed in the second-to-last input segment, just
 | 
			
		||||
     * before the regular inhdr.
 | 
			
		||||
     */
 | 
			
		||||
    req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
 | 
			
		||||
    scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
 | 
			
		||||
 | 
			
		||||
    if (!req->dev->blk.scsi) {
 | 
			
		||||
    if (!blk->blk.scsi) {
 | 
			
		||||
        status = VIRTIO_BLK_S_UNSUPP;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
@@ -160,43 +160,42 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 | 
			
		||||
    /*
 | 
			
		||||
     * No support for bidirection commands yet.
 | 
			
		||||
     */
 | 
			
		||||
    if (req->elem.out_num > 2 && req->elem.in_num > 3) {
 | 
			
		||||
    if (elem->out_num > 2 && elem->in_num > 3) {
 | 
			
		||||
        status = VIRTIO_BLK_S_UNSUPP;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
    struct sg_io_hdr hdr;
 | 
			
		||||
    memset(&hdr, 0, sizeof(struct sg_io_hdr));
 | 
			
		||||
    hdr.interface_id = 'S';
 | 
			
		||||
    hdr.cmd_len = req->elem.out_sg[1].iov_len;
 | 
			
		||||
    hdr.cmdp = req->elem.out_sg[1].iov_base;
 | 
			
		||||
    hdr.cmd_len = elem->out_sg[1].iov_len;
 | 
			
		||||
    hdr.cmdp = elem->out_sg[1].iov_base;
 | 
			
		||||
    hdr.dxfer_len = 0;
 | 
			
		||||
 | 
			
		||||
    if (req->elem.out_num > 2) {
 | 
			
		||||
    if (elem->out_num > 2) {
 | 
			
		||||
        /*
 | 
			
		||||
         * If there are more than the minimally required 2 output segments
 | 
			
		||||
         * there is write payload starting from the third iovec.
 | 
			
		||||
         */
 | 
			
		||||
        hdr.dxfer_direction = SG_DXFER_TO_DEV;
 | 
			
		||||
        hdr.iovec_count = req->elem.out_num - 2;
 | 
			
		||||
        hdr.iovec_count = elem->out_num - 2;
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < hdr.iovec_count; i++)
 | 
			
		||||
            hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len;
 | 
			
		||||
            hdr.dxfer_len += elem->out_sg[i + 2].iov_len;
 | 
			
		||||
 | 
			
		||||
        hdr.dxferp = req->elem.out_sg + 2;
 | 
			
		||||
        hdr.dxferp = elem->out_sg + 2;
 | 
			
		||||
 | 
			
		||||
    } else if (req->elem.in_num > 3) {
 | 
			
		||||
    } else if (elem->in_num > 3) {
 | 
			
		||||
        /*
 | 
			
		||||
         * If we have more than 3 input segments the guest wants to actually
 | 
			
		||||
         * read data.
 | 
			
		||||
         */
 | 
			
		||||
        hdr.dxfer_direction = SG_DXFER_FROM_DEV;
 | 
			
		||||
        hdr.iovec_count = req->elem.in_num - 3;
 | 
			
		||||
        hdr.iovec_count = elem->in_num - 3;
 | 
			
		||||
        for (i = 0; i < hdr.iovec_count; i++)
 | 
			
		||||
            hdr.dxfer_len += req->elem.in_sg[i].iov_len;
 | 
			
		||||
            hdr.dxfer_len += elem->in_sg[i].iov_len;
 | 
			
		||||
 | 
			
		||||
        hdr.dxferp = req->elem.in_sg;
 | 
			
		||||
        hdr.dxferp = elem->in_sg;
 | 
			
		||||
    } else {
 | 
			
		||||
        /*
 | 
			
		||||
         * Some SCSI commands don't actually transfer any data.
 | 
			
		||||
@@ -204,11 +203,11 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 | 
			
		||||
        hdr.dxfer_direction = SG_DXFER_NONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base;
 | 
			
		||||
    hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len;
 | 
			
		||||
    hdr.sbp = elem->in_sg[elem->in_num - 3].iov_base;
 | 
			
		||||
    hdr.mx_sb_len = elem->in_sg[elem->in_num - 3].iov_len;
 | 
			
		||||
 | 
			
		||||
    ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
    status = bdrv_ioctl(blk->bs, SG_IO, &hdr);
 | 
			
		||||
    if (status) {
 | 
			
		||||
        status = VIRTIO_BLK_S_UNSUPP;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
@@ -224,23 +223,31 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 | 
			
		||||
        hdr.status = CHECK_CONDITION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stl_p(&req->scsi->errors,
 | 
			
		||||
    stl_p(&scsi->errors,
 | 
			
		||||
          hdr.status | (hdr.msg_status << 8) |
 | 
			
		||||
          (hdr.host_status << 16) | (hdr.driver_status << 24));
 | 
			
		||||
    stl_p(&req->scsi->residual, hdr.resid);
 | 
			
		||||
    stl_p(&req->scsi->sense_len, hdr.sb_len_wr);
 | 
			
		||||
    stl_p(&req->scsi->data_len, hdr.dxfer_len);
 | 
			
		||||
    stl_p(&scsi->residual, hdr.resid);
 | 
			
		||||
    stl_p(&scsi->sense_len, hdr.sb_len_wr);
 | 
			
		||||
    stl_p(&scsi->data_len, hdr.dxfer_len);
 | 
			
		||||
 | 
			
		||||
    virtio_blk_req_complete(req, status);
 | 
			
		||||
    g_free(req);
 | 
			
		||||
    return;
 | 
			
		||||
    return status;
 | 
			
		||||
#else
 | 
			
		||||
    abort();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
    /* Just put anything nonzero so that the ioctl fails in the guest.  */
 | 
			
		||||
    stl_p(&req->scsi->errors, 255);
 | 
			
		||||
    if (scsi) {
 | 
			
		||||
        stl_p(&scsi->errors, 255);
 | 
			
		||||
    }
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
 | 
			
		||||
    status = virtio_blk_handle_scsi_req(req->dev, &req->elem);
 | 
			
		||||
    virtio_blk_req_complete(req, status);
 | 
			
		||||
    g_free(req);
 | 
			
		||||
}
 | 
			
		||||
@@ -487,12 +494,12 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 | 
			
		||||
 | 
			
		||||
    bdrv_get_geometry(s->bs, &capacity);
 | 
			
		||||
    memset(&blkcfg, 0, sizeof(blkcfg));
 | 
			
		||||
    stq_raw(&blkcfg.capacity, capacity);
 | 
			
		||||
    stl_raw(&blkcfg.seg_max, 128 - 2);
 | 
			
		||||
    stw_raw(&blkcfg.cylinders, s->conf->cyls);
 | 
			
		||||
    stl_raw(&blkcfg.blk_size, blk_size);
 | 
			
		||||
    stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
 | 
			
		||||
    stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
 | 
			
		||||
    stq_p(&blkcfg.capacity, capacity);
 | 
			
		||||
    stl_p(&blkcfg.seg_max, 128 - 2);
 | 
			
		||||
    stw_p(&blkcfg.cylinders, s->conf->cyls);
 | 
			
		||||
    stl_p(&blkcfg.blk_size, blk_size);
 | 
			
		||||
    stw_p(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
 | 
			
		||||
    stw_p(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
 | 
			
		||||
    blkcfg.heads = s->conf->heads;
 | 
			
		||||
    /*
 | 
			
		||||
     * We must ensure that the block device capacity is a multiple of
 | 
			
		||||
@@ -523,7 +530,10 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
 | 
			
		||||
    struct virtio_blk_config blkcfg;
 | 
			
		||||
 | 
			
		||||
    memcpy(&blkcfg, config, sizeof(blkcfg));
 | 
			
		||||
 | 
			
		||||
    aio_context_acquire(bdrv_get_aio_context(s->bs));
 | 
			
		||||
    bdrv_set_enable_write_cache(s->bs, blkcfg.wce != 0);
 | 
			
		||||
    aio_context_release(bdrv_get_aio_context(s->bs));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
 | 
			
		||||
@@ -582,7 +592,10 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
 | 
			
		||||
     * s->bs would erroneously be placed in writethrough mode.
 | 
			
		||||
     */
 | 
			
		||||
    if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) {
 | 
			
		||||
        bdrv_set_enable_write_cache(s->bs, !!(features & (1 << VIRTIO_BLK_F_WCE)));
 | 
			
		||||
        aio_context_acquire(bdrv_get_aio_context(s->bs));
 | 
			
		||||
        bdrv_set_enable_write_cache(s->bs,
 | 
			
		||||
                                    !!(features & (1 << VIRTIO_BLK_F_WCE)));
 | 
			
		||||
        aio_context_release(bdrv_get_aio_context(s->bs));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@
 | 
			
		||||
typedef struct PCISerialState {
 | 
			
		||||
    PCIDevice dev;
 | 
			
		||||
    SerialState state;
 | 
			
		||||
    uint8_t prog_if;
 | 
			
		||||
} PCISerialState;
 | 
			
		||||
 | 
			
		||||
typedef struct PCIMultiSerialState {
 | 
			
		||||
@@ -44,6 +45,7 @@ typedef struct PCIMultiSerialState {
 | 
			
		||||
    SerialState  state[PCI_SERIAL_MAX_PORTS];
 | 
			
		||||
    uint32_t     level[PCI_SERIAL_MAX_PORTS];
 | 
			
		||||
    qemu_irq     *irqs;
 | 
			
		||||
    uint8_t      prog_if;
 | 
			
		||||
} PCIMultiSerialState;
 | 
			
		||||
 | 
			
		||||
static int serial_pci_init(PCIDevice *dev)
 | 
			
		||||
@@ -60,6 +62,7 @@ static int serial_pci_init(PCIDevice *dev)
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
 | 
			
		||||
    pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
 | 
			
		||||
    s->irq = pci_allocate_irq(&pci->dev);
 | 
			
		||||
 | 
			
		||||
@@ -101,6 +104,7 @@ static int multi_serial_pci_init(PCIDevice *dev)
 | 
			
		||||
    assert(pci->ports > 0);
 | 
			
		||||
    assert(pci->ports <= PCI_SERIAL_MAX_PORTS);
 | 
			
		||||
 | 
			
		||||
    pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
 | 
			
		||||
    pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
 | 
			
		||||
    memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * pci->ports);
 | 
			
		||||
    pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
 | 
			
		||||
@@ -177,12 +181,14 @@ static const VMStateDescription vmstate_pci_multi_serial = {
 | 
			
		||||
 | 
			
		||||
static Property serial_pci_properties[] = {
 | 
			
		||||
    DEFINE_PROP_CHR("chardev",  PCISerialState, state.chr),
 | 
			
		||||
    DEFINE_PROP_UINT8("prog_if",  PCISerialState, prog_if, 0x02),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static Property multi_2x_serial_pci_properties[] = {
 | 
			
		||||
    DEFINE_PROP_CHR("chardev1",  PCIMultiSerialState, state[0].chr),
 | 
			
		||||
    DEFINE_PROP_CHR("chardev2",  PCIMultiSerialState, state[1].chr),
 | 
			
		||||
    DEFINE_PROP_UINT8("prog_if",  PCIMultiSerialState, prog_if, 0x02),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -191,6 +197,7 @@ static Property multi_4x_serial_pci_properties[] = {
 | 
			
		||||
    DEFINE_PROP_CHR("chardev2",  PCIMultiSerialState, state[1].chr),
 | 
			
		||||
    DEFINE_PROP_CHR("chardev3",  PCIMultiSerialState, state[2].chr),
 | 
			
		||||
    DEFINE_PROP_CHR("chardev4",  PCIMultiSerialState, state[3].chr),
 | 
			
		||||
    DEFINE_PROP_UINT8("prog_if",  PCIMultiSerialState, prog_if, 0x02),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -87,6 +87,11 @@ static void uart_update_status(XilinxUARTLite *s)
 | 
			
		||||
    s->regs[R_STATUS] = r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void xilinx_uartlite_reset(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    uart_update_status(XILINX_UARTLITE(dev));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint64_t
 | 
			
		||||
uart_read(void *opaque, hwaddr addr, unsigned int size)
 | 
			
		||||
{
 | 
			
		||||
@@ -196,34 +201,39 @@ static void uart_event(void *opaque, int event)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int xilinx_uartlite_init(SysBusDevice *dev)
 | 
			
		||||
static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    XilinxUARTLite *s = XILINX_UARTLITE(dev);
 | 
			
		||||
 | 
			
		||||
    sysbus_init_irq(dev, &s->irq);
 | 
			
		||||
 | 
			
		||||
    uart_update_status(s);
 | 
			
		||||
    memory_region_init_io(&s->mmio, OBJECT(s), &uart_ops, s,
 | 
			
		||||
                          "xlnx.xps-uartlite", R_MAX * 4);
 | 
			
		||||
    sysbus_init_mmio(dev, &s->mmio);
 | 
			
		||||
 | 
			
		||||
    s->chr = qemu_char_get_next_serial();
 | 
			
		||||
    if (s->chr)
 | 
			
		||||
        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void xilinx_uartlite_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    XilinxUARTLite *s = XILINX_UARTLITE(obj);
 | 
			
		||||
 | 
			
		||||
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->mmio, obj, &uart_ops, s,
 | 
			
		||||
                          "xlnx.xps-uartlite", R_MAX * 4);
 | 
			
		||||
    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    sdc->init = xilinx_uartlite_init;
 | 
			
		||||
    dc->reset = xilinx_uartlite_reset;
 | 
			
		||||
    dc->realize = xilinx_uartlite_realize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo xilinx_uartlite_info = {
 | 
			
		||||
    .name          = TYPE_XILINX_UARTLITE,
 | 
			
		||||
    .parent        = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(XilinxUARTLite),
 | 
			
		||||
    .instance_init = xilinx_uartlite_init,
 | 
			
		||||
    .class_init    = xilinx_uartlite_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -439,11 +439,27 @@ PropertyInfo qdev_prop_iothread = {
 | 
			
		||||
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    GlobalProperty *g;
 | 
			
		||||
    ObjectClass *oc;
 | 
			
		||||
 | 
			
		||||
    g = g_malloc0(sizeof(*g));
 | 
			
		||||
    g->driver   = qemu_opt_get(opts, "driver");
 | 
			
		||||
    g->property = qemu_opt_get(opts, "property");
 | 
			
		||||
    g->value    = qemu_opt_get(opts, "value");
 | 
			
		||||
    oc = object_class_by_name(g->driver);
 | 
			
		||||
    if (oc) {
 | 
			
		||||
        DeviceClass *dc = DEVICE_CLASS(oc);
 | 
			
		||||
 | 
			
		||||
        if (dc->hotpluggable) {
 | 
			
		||||
            /* If hotpluggable then skip not_used checking. */
 | 
			
		||||
            g->not_used = false;
 | 
			
		||||
        } else {
 | 
			
		||||
            /* Maybe a typo. */
 | 
			
		||||
            g->not_used = true;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Maybe a typo. */
 | 
			
		||||
        g->not_used = true;
 | 
			
		||||
    }
 | 
			
		||||
    qdev_prop_register_global(g);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -955,6 +955,23 @@ void qdev_prop_register_global_list(GlobalProperty *props)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qdev_prop_check_global(void)
 | 
			
		||||
{
 | 
			
		||||
    GlobalProperty *prop;
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH(prop, &global_props, next) {
 | 
			
		||||
        if (!prop->not_used) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        ret = 1;
 | 
			
		||||
        error_report("Warning: \"-global %s.%s=%s\" not used",
 | 
			
		||||
                     prop->driver, prop->property, prop->value);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
 | 
			
		||||
                                    Error **errp)
 | 
			
		||||
{
 | 
			
		||||
@@ -966,6 +983,7 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
 | 
			
		||||
        if (strcmp(typename, prop->driver) != 0) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        prop->not_used = false;
 | 
			
		||||
        object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
 | 
			
		||||
        if (err != NULL) {
 | 
			
		||||
            error_propagate(errp, err);
 | 
			
		||||
 
 | 
			
		||||
@@ -177,7 +177,7 @@ static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size)
 | 
			
		||||
        /* monitor ID 6, board type = 1 (color) */
 | 
			
		||||
        val = s->regs[1] | CG3_SR_1152_900_76_B | CG3_SR_ID_COLOR;
 | 
			
		||||
        break;
 | 
			
		||||
    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
 | 
			
		||||
    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1:
 | 
			
		||||
        val = s->regs[addr - 0x10];
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
@@ -247,7 +247,7 @@ static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val,
 | 
			
		||||
            qemu_irq_lower(s->irq);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
 | 
			
		||||
    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1:
 | 
			
		||||
        s->regs[addr - 0x10] = val;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
@@ -274,6 +274,20 @@ static const GraphicHwOps cg3_ops = {
 | 
			
		||||
    .gfx_update = cg3_update_display,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void cg3_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 | 
			
		||||
    CG3State *s = CG3(obj);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
 | 
			
		||||
    memory_region_set_readonly(&s->rom, true);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->rom);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
 | 
			
		||||
                          CG3_REG_SIZE);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->reg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cg3_realizefn(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 | 
			
		||||
@@ -282,11 +296,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
 | 
			
		||||
    char *fcode_filename;
 | 
			
		||||
 | 
			
		||||
    /* FCode ROM */
 | 
			
		||||
    memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
 | 
			
		||||
    vmstate_register_ram_global(&s->rom);
 | 
			
		||||
    memory_region_set_readonly(&s->rom, true);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->rom);
 | 
			
		||||
 | 
			
		||||
    fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, CG3_ROM_FILE);
 | 
			
		||||
    if (fcode_filename) {
 | 
			
		||||
        ret = load_image_targphys(fcode_filename, s->prom_addr,
 | 
			
		||||
@@ -296,10 +306,6 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
 | 
			
		||||
                          CG3_REG_SIZE);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->reg);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size);
 | 
			
		||||
    vmstate_register_ram_global(&s->vram_mem);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->vram_mem);
 | 
			
		||||
@@ -374,6 +380,7 @@ static const TypeInfo cg3_info = {
 | 
			
		||||
    .name          = TYPE_CG3,
 | 
			
		||||
    .parent        = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(CG3State),
 | 
			
		||||
    .instance_init = cg3_initfn,
 | 
			
		||||
    .class_init    = cg3_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ static void glue(draw_line2_, DEPTH)(void *opaque,
 | 
			
		||||
    uint8_t v, r, g, b;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        v = ldub_raw((void *) s);
 | 
			
		||||
        v = ldub_p((void *) s);
 | 
			
		||||
        r = (pal[v & 3] >> 4) & 0xf0;
 | 
			
		||||
        g = pal[v & 3] & 0xf0;
 | 
			
		||||
        b = (pal[v & 3] << 4) & 0xf0;
 | 
			
		||||
@@ -89,7 +89,7 @@ static void glue(draw_line4_, DEPTH)(void *opaque,
 | 
			
		||||
    uint8_t v, r, g, b;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        v = ldub_raw((void *) s);
 | 
			
		||||
        v = ldub_p((void *) s);
 | 
			
		||||
        r = (pal[v & 0xf] >> 4) & 0xf0;
 | 
			
		||||
        g = pal[v & 0xf] & 0xf0;
 | 
			
		||||
        b = (pal[v & 0xf] << 4) & 0xf0;
 | 
			
		||||
@@ -116,7 +116,7 @@ static void glue(draw_line8_, DEPTH)(void *opaque,
 | 
			
		||||
    uint8_t v, r, g, b;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        v = ldub_raw((void *) s);
 | 
			
		||||
        v = ldub_p((void *) s);
 | 
			
		||||
        r = (pal[v] >> 4) & 0xf0;
 | 
			
		||||
        g = pal[v] & 0xf0;
 | 
			
		||||
        b = (pal[v] << 4) & 0xf0;
 | 
			
		||||
@@ -136,7 +136,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque,
 | 
			
		||||
    uint8_t r, g, b;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        v = lduw_raw((void *) s);
 | 
			
		||||
        v = lduw_p((void *) s);
 | 
			
		||||
        r = (v >> 4) & 0xf0;
 | 
			
		||||
        g = v & 0xf0;
 | 
			
		||||
        b = (v << 4) & 0xf0;
 | 
			
		||||
@@ -159,7 +159,7 @@ static void glue(draw_line16_, DEPTH)(void *opaque,
 | 
			
		||||
    uint8_t r, g, b;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        v = lduw_raw((void *) s);
 | 
			
		||||
        v = lduw_p((void *) s);
 | 
			
		||||
        r = (v >> 8) & 0xf8;
 | 
			
		||||
        g = (v >> 3) & 0xfc;
 | 
			
		||||
        b = (v << 3) & 0xf8;
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ static void glue(draw_line8_, PIXEL_NAME)(
 | 
			
		||||
{
 | 
			
		||||
    uint8_t v, r, g, b;
 | 
			
		||||
    do {
 | 
			
		||||
      	v = ldub_raw(s);
 | 
			
		||||
	v = ldub_p(s);
 | 
			
		||||
	r = (pal[v] >> 16) & 0xff;
 | 
			
		||||
	g = (pal[v] >>  8) & 0xff;
 | 
			
		||||
	b = (pal[v] >>  0) & 0xff;
 | 
			
		||||
@@ -64,7 +64,7 @@ static void glue(draw_line16_, PIXEL_NAME)(
 | 
			
		||||
    uint8_t r, g, b;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
	rgb565 = lduw_raw(s);
 | 
			
		||||
	rgb565 = lduw_p(s);
 | 
			
		||||
	r = ((rgb565 >> 11) & 0x1f) << 3;
 | 
			
		||||
	g = ((rgb565 >>  5) & 0x3f) << 2;
 | 
			
		||||
	b = ((rgb565 >>  0) & 0x1f) << 3;
 | 
			
		||||
@@ -80,7 +80,7 @@ static void glue(draw_line32_, PIXEL_NAME)(
 | 
			
		||||
    uint8_t r, g, b;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
	ldub_raw(s);
 | 
			
		||||
	ldub_p(s);
 | 
			
		||||
#if defined(TARGET_WORDS_BIGENDIAN)
 | 
			
		||||
        r = s[1];
 | 
			
		||||
        g = s[2];
 | 
			
		||||
 
 | 
			
		||||
@@ -530,8 +530,36 @@ static const GraphicHwOps tcx24_ops = {
 | 
			
		||||
    .gfx_update = tcx24_update_display,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int tcx_init1(SysBusDevice *dev)
 | 
			
		||||
static void tcx_initfn(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 | 
			
		||||
    TCXState *s = TCX(obj);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE);
 | 
			
		||||
    memory_region_set_readonly(&s->rom, true);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->rom);
 | 
			
		||||
 | 
			
		||||
    /* DAC */
 | 
			
		||||
    memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
 | 
			
		||||
                          "tcx.dac", TCX_DAC_NREGS);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->dac);
 | 
			
		||||
 | 
			
		||||
    /* TEC (dummy) */
 | 
			
		||||
    memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
 | 
			
		||||
                          "tcx.tec", TCX_TEC_NREGS);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->tec);
 | 
			
		||||
 | 
			
		||||
    /* THC: NetBSD writes here even with 8-bit display: dummy */
 | 
			
		||||
    memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
 | 
			
		||||
                          TCX_THC_NREGS_24);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->thc24);
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tcx_realizefn(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 | 
			
		||||
    TCXState *s = TCX(dev);
 | 
			
		||||
    ram_addr_t vram_offset = 0;
 | 
			
		||||
    int size, ret;
 | 
			
		||||
@@ -544,18 +572,13 @@ static int tcx_init1(SysBusDevice *dev)
 | 
			
		||||
    vram_base = memory_region_get_ram_ptr(&s->vram_mem);
 | 
			
		||||
 | 
			
		||||
    /* FCode ROM */
 | 
			
		||||
    memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE);
 | 
			
		||||
    vmstate_register_ram_global(&s->rom);
 | 
			
		||||
    memory_region_set_readonly(&s->rom, true);
 | 
			
		||||
    sysbus_init_mmio(dev, &s->rom);
 | 
			
		||||
 | 
			
		||||
    fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, TCX_ROM_FILE);
 | 
			
		||||
    if (fcode_filename) {
 | 
			
		||||
        ret = load_image_targphys(fcode_filename, s->prom_addr,
 | 
			
		||||
                                  FCODE_MAX_ROM_SIZE);
 | 
			
		||||
        if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) {
 | 
			
		||||
            fprintf(stderr, "tcx: could not load prom '%s'\n", TCX_ROM_FILE);
 | 
			
		||||
            return -1;
 | 
			
		||||
            error_report("tcx: could not load prom '%s'", TCX_ROM_FILE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -564,24 +587,10 @@ static int tcx_init1(SysBusDevice *dev)
 | 
			
		||||
    size = s->vram_size;
 | 
			
		||||
    memory_region_init_alias(&s->vram_8bit, OBJECT(s), "tcx.vram.8bit",
 | 
			
		||||
                             &s->vram_mem, vram_offset, size);
 | 
			
		||||
    sysbus_init_mmio(dev, &s->vram_8bit);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->vram_8bit);
 | 
			
		||||
    vram_offset += size;
 | 
			
		||||
    vram_base += size;
 | 
			
		||||
 | 
			
		||||
    /* DAC */
 | 
			
		||||
    memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
 | 
			
		||||
                          "tcx.dac", TCX_DAC_NREGS);
 | 
			
		||||
    sysbus_init_mmio(dev, &s->dac);
 | 
			
		||||
 | 
			
		||||
    /* TEC (dummy) */
 | 
			
		||||
    memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
 | 
			
		||||
                          "tcx.tec", TCX_TEC_NREGS);
 | 
			
		||||
    sysbus_init_mmio(dev, &s->tec);
 | 
			
		||||
    /* THC: NetBSD writes here even with 8-bit display: dummy */
 | 
			
		||||
    memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
 | 
			
		||||
                          TCX_THC_NREGS_24);
 | 
			
		||||
    sysbus_init_mmio(dev, &s->thc24);
 | 
			
		||||
 | 
			
		||||
    if (s->depth == 24) {
 | 
			
		||||
        /* 24-bit plane */
 | 
			
		||||
        size = s->vram_size * 4;
 | 
			
		||||
@@ -589,7 +598,7 @@ static int tcx_init1(SysBusDevice *dev)
 | 
			
		||||
        s->vram24_offset = vram_offset;
 | 
			
		||||
        memory_region_init_alias(&s->vram_24bit, OBJECT(s), "tcx.vram.24bit",
 | 
			
		||||
                                 &s->vram_mem, vram_offset, size);
 | 
			
		||||
        sysbus_init_mmio(dev, &s->vram_24bit);
 | 
			
		||||
        sysbus_init_mmio(sbd, &s->vram_24bit);
 | 
			
		||||
        vram_offset += size;
 | 
			
		||||
        vram_base += size;
 | 
			
		||||
 | 
			
		||||
@@ -599,20 +608,19 @@ static int tcx_init1(SysBusDevice *dev)
 | 
			
		||||
        s->cplane_offset = vram_offset;
 | 
			
		||||
        memory_region_init_alias(&s->vram_cplane, OBJECT(s), "tcx.vram.cplane",
 | 
			
		||||
                                 &s->vram_mem, vram_offset, size);
 | 
			
		||||
        sysbus_init_mmio(dev, &s->vram_cplane);
 | 
			
		||||
        sysbus_init_mmio(sbd, &s->vram_cplane);
 | 
			
		||||
 | 
			
		||||
        s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* THC 8 bit (dummy) */
 | 
			
		||||
        memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8",
 | 
			
		||||
                              TCX_THC_NREGS_8);
 | 
			
		||||
        sysbus_init_mmio(dev, &s->thc8);
 | 
			
		||||
        sysbus_init_mmio(sbd, &s->thc8);
 | 
			
		||||
 | 
			
		||||
        s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_console_resize(s->con, s->width, s->height);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property tcx_properties[] = {
 | 
			
		||||
@@ -627,9 +635,8 @@ static Property tcx_properties[] = {
 | 
			
		||||
static void tcx_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    k->init = tcx_init1;
 | 
			
		||||
    dc->realize = tcx_realizefn;
 | 
			
		||||
    dc->reset = tcx_reset;
 | 
			
		||||
    dc->vmsd = &vmstate_tcx;
 | 
			
		||||
    dc->props = tcx_properties;
 | 
			
		||||
@@ -639,6 +646,7 @@ static const TypeInfo tcx_info = {
 | 
			
		||||
    .name          = TYPE_TCX,
 | 
			
		||||
    .parent        = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(TCXState),
 | 
			
		||||
    .instance_init = tcx_initfn,
 | 
			
		||||
    .class_init    = tcx_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -361,7 +361,7 @@ static void glue(vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 | 
			
		||||
 | 
			
		||||
    w = width;
 | 
			
		||||
    do {
 | 
			
		||||
        v = lduw_raw((void *)s);
 | 
			
		||||
        v = lduw_p((void *)s);
 | 
			
		||||
        r = (v >> 7) & 0xf8;
 | 
			
		||||
        g = (v >> 2) & 0xf8;
 | 
			
		||||
        b = (v << 3) & 0xf8;
 | 
			
		||||
@@ -386,7 +386,7 @@ static void glue(vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 | 
			
		||||
 | 
			
		||||
    w = width;
 | 
			
		||||
    do {
 | 
			
		||||
        v = lduw_raw((void *)s);
 | 
			
		||||
        v = lduw_p((void *)s);
 | 
			
		||||
        r = (v >> 8) & 0xf8;
 | 
			
		||||
        g = (v >> 3) & 0xfc;
 | 
			
		||||
        b = (v << 3) & 0xf8;
 | 
			
		||||
 
 | 
			
		||||
@@ -863,7 +863,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case SVGA_REG_CURSOR_Y:
 | 
			
		||||
        ret = s->cursor.x;
 | 
			
		||||
        ret = s->cursor.y;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case SVGA_REG_CURSOR_ON:
 | 
			
		||||
 
 | 
			
		||||
@@ -157,11 +157,6 @@ static inline int stream_running(struct Stream *s)
 | 
			
		||||
    return s->regs[R_DMACR] & DMACR_RUNSTOP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int stream_halted(struct Stream *s)
 | 
			
		||||
{
 | 
			
		||||
    return s->regs[R_DMASR] & DMASR_HALTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int stream_idle(struct Stream *s)
 | 
			
		||||
{
 | 
			
		||||
    return !!(s->regs[R_DMASR] & DMASR_IDLE);
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,10 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "qemu/host-utils.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "sysemu/kvm.h"
 | 
			
		||||
#include "sysemu/cpus.h"
 | 
			
		||||
#include "hw/sysbus.h"
 | 
			
		||||
#include "hw/kvm/clock.h"
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +36,48 @@ typedef struct KVMClockState {
 | 
			
		||||
    bool clock_valid;
 | 
			
		||||
} KVMClockState;
 | 
			
		||||
 | 
			
		||||
struct pvclock_vcpu_time_info {
 | 
			
		||||
    uint32_t   version;
 | 
			
		||||
    uint32_t   pad0;
 | 
			
		||||
    uint64_t   tsc_timestamp;
 | 
			
		||||
    uint64_t   system_time;
 | 
			
		||||
    uint32_t   tsc_to_system_mul;
 | 
			
		||||
    int8_t     tsc_shift;
 | 
			
		||||
    uint8_t    flags;
 | 
			
		||||
    uint8_t    pad[2];
 | 
			
		||||
} __attribute__((__packed__)); /* 32 bytes */
 | 
			
		||||
 | 
			
		||||
static uint64_t kvmclock_current_nsec(KVMClockState *s)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *cpu = first_cpu;
 | 
			
		||||
    CPUX86State *env = cpu->env_ptr;
 | 
			
		||||
    hwaddr kvmclock_struct_pa = env->system_time_msr & ~1ULL;
 | 
			
		||||
    uint64_t migration_tsc = env->tsc;
 | 
			
		||||
    struct pvclock_vcpu_time_info time;
 | 
			
		||||
    uint64_t delta;
 | 
			
		||||
    uint64_t nsec_lo;
 | 
			
		||||
    uint64_t nsec_hi;
 | 
			
		||||
    uint64_t nsec;
 | 
			
		||||
 | 
			
		||||
    if (!(env->system_time_msr & 1ULL)) {
 | 
			
		||||
        /* KVM clock not active */
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cpu_physical_memory_read(kvmclock_struct_pa, &time, sizeof(time));
 | 
			
		||||
 | 
			
		||||
    assert(time.tsc_timestamp <= migration_tsc);
 | 
			
		||||
    delta = migration_tsc - time.tsc_timestamp;
 | 
			
		||||
    if (time.tsc_shift < 0) {
 | 
			
		||||
        delta >>= -time.tsc_shift;
 | 
			
		||||
    } else {
 | 
			
		||||
        delta <<= time.tsc_shift;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mulu64(&nsec_lo, &nsec_hi, delta, time.tsc_to_system_mul);
 | 
			
		||||
    nsec = (nsec_lo >> 32) | (nsec_hi << 32);
 | 
			
		||||
    return nsec + time.system_time;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvmclock_vm_state_change(void *opaque, int running,
 | 
			
		||||
                                     RunState state)
 | 
			
		||||
@@ -45,9 +89,15 @@ static void kvmclock_vm_state_change(void *opaque, int running,
 | 
			
		||||
 | 
			
		||||
    if (running) {
 | 
			
		||||
        struct kvm_clock_data data;
 | 
			
		||||
        uint64_t time_at_migration = kvmclock_current_nsec(s);
 | 
			
		||||
 | 
			
		||||
        s->clock_valid = false;
 | 
			
		||||
 | 
			
		||||
	/* We can't rely on the migrated clock value, just discard it */
 | 
			
		||||
	if (time_at_migration) {
 | 
			
		||||
	        s->clock = time_at_migration;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        data.clock = s->clock;
 | 
			
		||||
        data.flags = 0;
 | 
			
		||||
        ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
 | 
			
		||||
@@ -75,6 +125,8 @@ static void kvmclock_vm_state_change(void *opaque, int running,
 | 
			
		||||
        if (s->clock_valid) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        cpu_synchronize_all_states();
 | 
			
		||||
        ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
 | 
			
		||||
 
 | 
			
		||||
@@ -922,9 +922,6 @@ static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
 | 
			
		||||
                                              0x280, 0x380 };
 | 
			
		||||
static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
 | 
			
		||||
 | 
			
		||||
static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 | 
			
		||||
static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 | 
			
		||||
 | 
			
		||||
void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
 | 
			
		||||
{
 | 
			
		||||
    static int nb_ne2k = 0;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										119
									
								
								hw/i386/smbios.c
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								hw/i386/smbios.c
									
									
									
									
									
								
							@@ -67,7 +67,7 @@ static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
    const char *vendor, *version, *date;
 | 
			
		||||
    bool have_major_minor;
 | 
			
		||||
    bool have_major_minor, uefi;
 | 
			
		||||
    uint8_t major, minor;
 | 
			
		||||
} type0;
 | 
			
		||||
 | 
			
		||||
@@ -134,6 +134,10 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
 | 
			
		||||
        .name = "release",
 | 
			
		||||
        .type = QEMU_OPT_STRING,
 | 
			
		||||
        .help = "revision number",
 | 
			
		||||
    },{
 | 
			
		||||
        .name = "uefi",
 | 
			
		||||
        .type = QEMU_OPT_BOOL,
 | 
			
		||||
        .help = "uefi support",
 | 
			
		||||
    },
 | 
			
		||||
    { /* end of list */ }
 | 
			
		||||
};
 | 
			
		||||
@@ -444,7 +448,7 @@ static bool smbios_skip_table(uint8_t type, bool required_table)
 | 
			
		||||
                                                                          \
 | 
			
		||||
        t->header.type = tbl_type;                                        \
 | 
			
		||||
        t->header.length = sizeof(*t);                                    \
 | 
			
		||||
        t->header.handle = tbl_handle;                                    \
 | 
			
		||||
        t->header.handle = cpu_to_le16(tbl_handle);                       \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#define SMBIOS_TABLE_SET_STR(tbl_type, field, value)                      \
 | 
			
		||||
@@ -491,19 +495,18 @@ static void smbios_build_type_0_table(void)
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version);
 | 
			
		||||
 | 
			
		||||
    t->bios_starting_address_segment = 0xE800; /* hardcoded in SeaBIOS */
 | 
			
		||||
    t->bios_starting_address_segment = cpu_to_le16(0xE800); /* from SeaBIOS */
 | 
			
		||||
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date);
 | 
			
		||||
 | 
			
		||||
    t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */
 | 
			
		||||
 | 
			
		||||
    /* BIOS characteristics not supported */
 | 
			
		||||
    memset(t->bios_characteristics, 0, 8);
 | 
			
		||||
    t->bios_characteristics[0] = 0x08;
 | 
			
		||||
 | 
			
		||||
    /* Enable targeted content distribution (needed for SVVP, per SeaBIOS) */
 | 
			
		||||
    t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
 | 
			
		||||
    t->bios_characteristics_extension_bytes[0] = 0;
 | 
			
		||||
    t->bios_characteristics_extension_bytes[1] = 4;
 | 
			
		||||
    t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
 | 
			
		||||
    if (type0.uefi) {
 | 
			
		||||
        t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (type0.have_major_minor) {
 | 
			
		||||
        t->system_bios_major_release = type0.major;
 | 
			
		||||
@@ -551,7 +554,7 @@ static void smbios_build_type_2_table(void)
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(2, asset_tag_number_str, type2.asset);
 | 
			
		||||
    t->feature_flags = 0x01; /* Motherboard */
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(2, location_str, type2.location);
 | 
			
		||||
    t->chassis_handle = 0x300; /* Type 3 (System enclosure) */
 | 
			
		||||
    t->chassis_handle = cpu_to_le16(0x300); /* Type 3 (System enclosure) */
 | 
			
		||||
    t->board_type = 0x0A; /* Motherboard */
 | 
			
		||||
    t->contained_element_count = 0;
 | 
			
		||||
 | 
			
		||||
@@ -571,7 +574,7 @@ static void smbios_build_type_3_table(void)
 | 
			
		||||
    t->power_supply_state = 0x03; /* Safe */
 | 
			
		||||
    t->thermal_state = 0x03; /* Safe */
 | 
			
		||||
    t->security_status = 0x02; /* Unknown */
 | 
			
		||||
    t->oem_defined = 0;
 | 
			
		||||
    t->oem_defined = cpu_to_le32(0);
 | 
			
		||||
    t->height = 0;
 | 
			
		||||
    t->number_of_power_cords = 0;
 | 
			
		||||
    t->contained_element_count = 0;
 | 
			
		||||
@@ -589,26 +592,27 @@ static void smbios_build_type_4_table(unsigned instance)
 | 
			
		||||
    snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str);
 | 
			
		||||
    t->processor_type = 0x03; /* CPU */
 | 
			
		||||
    t->processor_family = 0x01; /* Other */
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer);
 | 
			
		||||
    t->processor_id[0] = smbios_cpuid_version;
 | 
			
		||||
    t->processor_id[1] = smbios_cpuid_features;
 | 
			
		||||
    t->processor_id[0] = cpu_to_le32(smbios_cpuid_version);
 | 
			
		||||
    t->processor_id[1] = cpu_to_le32(smbios_cpuid_features);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
 | 
			
		||||
    t->voltage = 0;
 | 
			
		||||
    t->external_clock = 0; /* Unknown */
 | 
			
		||||
    t->max_speed = 0; /* Unknown */
 | 
			
		||||
    t->current_speed = 0; /* Unknown */
 | 
			
		||||
    t->external_clock = cpu_to_le16(0); /* Unknown */
 | 
			
		||||
    t->max_speed = cpu_to_le16(0); /* Unknown */
 | 
			
		||||
    t->current_speed = cpu_to_le16(0); /* Unknown */
 | 
			
		||||
    t->status = 0x41; /* Socket populated, CPU enabled */
 | 
			
		||||
    t->processor_upgrade = 0x01; /* Other */
 | 
			
		||||
    t->l1_cache_handle = 0xFFFF; /* N/A */
 | 
			
		||||
    t->l2_cache_handle = 0xFFFF; /* N/A */
 | 
			
		||||
    t->l3_cache_handle = 0xFFFF; /* N/A */
 | 
			
		||||
    t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
 | 
			
		||||
    t->l2_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
 | 
			
		||||
    t->l3_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
 | 
			
		||||
    t->core_count = t->core_enabled = smp_cores;
 | 
			
		||||
    t->thread_count = smp_threads;
 | 
			
		||||
    t->processor_characteristics = 0x02; /* Unknown */
 | 
			
		||||
    t->processor_family = t->processor_family2 = 0x01; /* Other */
 | 
			
		||||
    t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
 | 
			
		||||
    t->processor_family2 = cpu_to_le16(0x01); /* Other */
 | 
			
		||||
 | 
			
		||||
    SMBIOS_BUILD_TABLE_POST;
 | 
			
		||||
    smbios_type4_count++;
 | 
			
		||||
@@ -631,14 +635,14 @@ static void smbios_build_type_16_table(unsigned dimm_cnt)
 | 
			
		||||
    t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */
 | 
			
		||||
    size_kb = QEMU_ALIGN_UP(ram_size, ONE_KB) / ONE_KB;
 | 
			
		||||
    if (size_kb < MAX_T16_STD_SZ) {
 | 
			
		||||
        t->maximum_capacity = size_kb;
 | 
			
		||||
        t->extended_maximum_capacity = 0;
 | 
			
		||||
        t->maximum_capacity = cpu_to_le32(size_kb);
 | 
			
		||||
        t->extended_maximum_capacity = cpu_to_le64(0);
 | 
			
		||||
    } else {
 | 
			
		||||
        t->maximum_capacity = MAX_T16_STD_SZ;
 | 
			
		||||
        t->extended_maximum_capacity = ram_size;
 | 
			
		||||
        t->maximum_capacity = cpu_to_le32(MAX_T16_STD_SZ);
 | 
			
		||||
        t->extended_maximum_capacity = cpu_to_le64(ram_size);
 | 
			
		||||
    }
 | 
			
		||||
    t->memory_error_information_handle = 0xFFFE; /* Not provided */
 | 
			
		||||
    t->number_of_memory_devices = dimm_cnt;
 | 
			
		||||
    t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
 | 
			
		||||
    t->number_of_memory_devices = cpu_to_le16(dimm_cnt);
 | 
			
		||||
 | 
			
		||||
    SMBIOS_BUILD_TABLE_POST;
 | 
			
		||||
}
 | 
			
		||||
@@ -653,18 +657,18 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
 | 
			
		||||
 | 
			
		||||
    SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
 | 
			
		||||
 | 
			
		||||
    t->physical_memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
 | 
			
		||||
    t->memory_error_information_handle = 0xFFFE; /* Not provided */
 | 
			
		||||
    t->total_width = 0xFFFF; /* Unknown */
 | 
			
		||||
    t->data_width = 0xFFFF; /* Unknown */
 | 
			
		||||
    t->physical_memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
 | 
			
		||||
    t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
 | 
			
		||||
    t->total_width = cpu_to_le16(0xFFFF); /* Unknown */
 | 
			
		||||
    t->data_width = cpu_to_le16(0xFFFF); /* Unknown */
 | 
			
		||||
    size_mb = QEMU_ALIGN_UP(size, ONE_MB) / ONE_MB;
 | 
			
		||||
    if (size_mb < MAX_T17_STD_SZ) {
 | 
			
		||||
        t->size = size_mb;
 | 
			
		||||
        t->extended_size = 0;
 | 
			
		||||
        t->size = cpu_to_le16(size_mb);
 | 
			
		||||
        t->extended_size = cpu_to_le32(0);
 | 
			
		||||
    } else {
 | 
			
		||||
        assert(size_mb < MAX_T17_EXT_SZ);
 | 
			
		||||
        t->size = MAX_T17_STD_SZ;
 | 
			
		||||
        t->extended_size = size_mb;
 | 
			
		||||
        t->size = cpu_to_le16(MAX_T17_STD_SZ);
 | 
			
		||||
        t->extended_size = cpu_to_le32(size_mb);
 | 
			
		||||
    }
 | 
			
		||||
    t->form_factor = 0x09; /* DIMM */
 | 
			
		||||
    t->device_set = 0; /* Not in a set */
 | 
			
		||||
@@ -672,17 +676,17 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(17, device_locator_str, loc_str);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank);
 | 
			
		||||
    t->memory_type = 0x07; /* RAM */
 | 
			
		||||
    t->type_detail = 0x02; /* Other */
 | 
			
		||||
    t->speed = 0; /* Unknown */
 | 
			
		||||
    t->type_detail = cpu_to_le16(0x02); /* Other */
 | 
			
		||||
    t->speed = cpu_to_le16(0); /* Unknown */
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset);
 | 
			
		||||
    SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part);
 | 
			
		||||
    t->attributes = 0; /* Unknown */
 | 
			
		||||
    t->configured_clock_speed = 0; /* Unknown */
 | 
			
		||||
    t->minimum_voltage = 0; /* Unknown */
 | 
			
		||||
    t->maximum_voltage = 0; /* Unknown */
 | 
			
		||||
    t->configured_voltage = 0; /* Unknown */
 | 
			
		||||
    t->configured_clock_speed = cpu_to_le16(0); /* Unknown */
 | 
			
		||||
    t->minimum_voltage = cpu_to_le16(0); /* Unknown */
 | 
			
		||||
    t->maximum_voltage = cpu_to_le16(0); /* Unknown */
 | 
			
		||||
    t->configured_voltage = cpu_to_le16(0); /* Unknown */
 | 
			
		||||
 | 
			
		||||
    SMBIOS_BUILD_TABLE_POST;
 | 
			
		||||
}
 | 
			
		||||
@@ -699,15 +703,16 @@ static void smbios_build_type_19_table(unsigned instance,
 | 
			
		||||
    start_kb = start / ONE_KB;
 | 
			
		||||
    end_kb = end / ONE_KB;
 | 
			
		||||
    if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) {
 | 
			
		||||
        t->starting_address = start_kb;
 | 
			
		||||
        t->ending_address = end_kb;
 | 
			
		||||
        t->extended_starting_address = t->extended_ending_address = 0;
 | 
			
		||||
        t->starting_address = cpu_to_le32(start_kb);
 | 
			
		||||
        t->ending_address = cpu_to_le32(end_kb);
 | 
			
		||||
        t->extended_starting_address =
 | 
			
		||||
            t->extended_ending_address = cpu_to_le64(0);
 | 
			
		||||
    } else {
 | 
			
		||||
        t->starting_address = t->ending_address = UINT32_MAX;
 | 
			
		||||
        t->extended_starting_address = start;
 | 
			
		||||
        t->extended_ending_address = end;
 | 
			
		||||
        t->starting_address = t->ending_address = cpu_to_le32(UINT32_MAX);
 | 
			
		||||
        t->extended_starting_address = cpu_to_le64(start);
 | 
			
		||||
        t->extended_ending_address = cpu_to_le64(end);
 | 
			
		||||
    }
 | 
			
		||||
    t->memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
 | 
			
		||||
    t->memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
 | 
			
		||||
    t->partition_width = 1; /* One device per row */
 | 
			
		||||
 | 
			
		||||
    SMBIOS_BUILD_TABLE_POST;
 | 
			
		||||
@@ -740,11 +745,6 @@ void smbios_set_cpuid(uint32_t version, uint32_t features)
 | 
			
		||||
        field = value;                                                    \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#define G_FREE_UNLESS_NULL(ptr)                                           \
 | 
			
		||||
    if (ptr != NULL) {                                                    \
 | 
			
		||||
        g_free(ptr);                                                      \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
void smbios_set_defaults(const char *manufacturer, const char *product,
 | 
			
		||||
                         const char *version, bool legacy_mode)
 | 
			
		||||
{
 | 
			
		||||
@@ -753,7 +753,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product,
 | 
			
		||||
 | 
			
		||||
    /* drop unwanted version of command-line file blob(s) */
 | 
			
		||||
    if (smbios_legacy) {
 | 
			
		||||
        G_FREE_UNLESS_NULL(smbios_tables);
 | 
			
		||||
        g_free(smbios_tables);
 | 
			
		||||
        /* in legacy mode, also complain if fields were given for types > 1 */
 | 
			
		||||
        if (find_next_bit(have_fields_bitmap,
 | 
			
		||||
                          SMBIOS_MAX_TYPE+1, 2) < SMBIOS_MAX_TYPE+1) {
 | 
			
		||||
@@ -762,7 +762,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product,
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        G_FREE_UNLESS_NULL(smbios_entries);
 | 
			
		||||
        g_free(smbios_entries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer);
 | 
			
		||||
@@ -794,14 +794,14 @@ static void smbios_entry_point_setup(void)
 | 
			
		||||
    ep.smbios_bcd_revision = 0x28;
 | 
			
		||||
 | 
			
		||||
    /* set during table construction, but BIOS may override: */
 | 
			
		||||
    ep.structure_table_length = smbios_tables_len;
 | 
			
		||||
    ep.max_structure_size = smbios_table_max;
 | 
			
		||||
    ep.number_of_structures = smbios_table_cnt;
 | 
			
		||||
    ep.structure_table_length = cpu_to_le16(smbios_tables_len);
 | 
			
		||||
    ep.max_structure_size = cpu_to_le16(smbios_table_max);
 | 
			
		||||
    ep.number_of_structures = cpu_to_le16(smbios_table_cnt);
 | 
			
		||||
 | 
			
		||||
    /* BIOS must recalculate: */
 | 
			
		||||
    ep.checksum = 0;
 | 
			
		||||
    ep.intermediate_checksum = 0;
 | 
			
		||||
    ep.structure_table_address = 0; /* where BIOS has copied smbios_tables */
 | 
			
		||||
    ep.structure_table_address = cpu_to_le32(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void smbios_get_tables(uint8_t **tables, size_t *tables_len,
 | 
			
		||||
@@ -977,6 +977,7 @@ void smbios_entry_add(QemuOpts *opts)
 | 
			
		||||
            save_opt(&type0.vendor, opts, "vendor");
 | 
			
		||||
            save_opt(&type0.version, opts, "version");
 | 
			
		||||
            save_opt(&type0.date, opts, "date");
 | 
			
		||||
            type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
 | 
			
		||||
 | 
			
		||||
            val = qemu_opt_get(opts, "release");
 | 
			
		||||
            if (val) {
 | 
			
		||||
 
 | 
			
		||||
@@ -156,31 +156,6 @@ static inline void softusb_write_dmem(MilkymistSoftUsbState *s,
 | 
			
		||||
    memcpy(s->dmem_ptr + offset, buf, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
 | 
			
		||||
        uint32_t offset, uint8_t *buf, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
    if (offset + len >= s->pmem_size) {
 | 
			
		||||
        error_report("milkymist_softusb: read pmem out of bounds "
 | 
			
		||||
                "at offset 0x%x, len %d", offset, len);
 | 
			
		||||
        memset(buf, 0, len);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(buf, s->pmem_ptr + offset, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void softusb_write_pmem(MilkymistSoftUsbState *s,
 | 
			
		||||
        uint32_t offset, uint8_t *buf, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
    if (offset + len >= s->pmem_size) {
 | 
			
		||||
        error_report("milkymist_softusb: write pmem out of bounds "
 | 
			
		||||
                "at offset 0x%x, len %d", offset, len);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(s->pmem_ptr + offset, buf, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void softusb_mouse_changed(MilkymistSoftUsbState *s)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t m;
 | 
			
		||||
 
 | 
			
		||||
@@ -311,11 +311,6 @@ static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
 | 
			
		||||
    clear_bit(n_IRQ, q->queue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int IRQ_testbit(IRQQueue *q, int n_IRQ)
 | 
			
		||||
{
 | 
			
		||||
    return test_bit(n_IRQ, q->queue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 | 
			
		||||
{
 | 
			
		||||
    int irq = -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -117,6 +117,16 @@ static int flic_enqueue_irqs(void *buf, uint64_t len,
 | 
			
		||||
    return rc ? -errno : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_s390_inject_flic(struct kvm_s390_irq *irq)
 | 
			
		||||
{
 | 
			
		||||
    static KVMS390FLICState *flic;
 | 
			
		||||
 | 
			
		||||
    if (unlikely(!flic)) {
 | 
			
		||||
        flic = KVM_S390_FLIC(s390_get_flic());
 | 
			
		||||
    }
 | 
			
		||||
    return flic_enqueue_irqs(irq, sizeof(*irq), flic);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * __get_all_irqs - store all pending irqs in buffer
 | 
			
		||||
 * @flic: pointer to flic device state
 | 
			
		||||
@@ -170,7 +180,8 @@ static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
 | 
			
		||||
        return -ENOSYS;
 | 
			
		||||
        /* nothing to do */
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
 | 
			
		||||
@@ -195,7 +206,8 @@ static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
    if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
 | 
			
		||||
        return -ENOSYS;
 | 
			
		||||
        /* nothing to do */
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
 | 
			
		||||
 
 | 
			
		||||
@@ -161,18 +161,16 @@ static void irq_handler(void *opaque, int irq, int level)
 | 
			
		||||
    update_irq(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int xilinx_intc_init(SysBusDevice *sbd)
 | 
			
		||||
static void xilinx_intc_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev = DEVICE(sbd);
 | 
			
		||||
    struct xlx_pic *p = XILINX_INTC(dev);
 | 
			
		||||
    struct xlx_pic *p = XILINX_INTC(obj);
 | 
			
		||||
 | 
			
		||||
    qdev_init_gpio_in(dev, irq_handler, 32);
 | 
			
		||||
    sysbus_init_irq(sbd, &p->parent_irq);
 | 
			
		||||
    qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
 | 
			
		||||
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&p->mmio, OBJECT(p), &pic_ops, p, "xlnx.xps-intc",
 | 
			
		||||
    memory_region_init_io(&p->mmio, obj, &pic_ops, p, "xlnx.xps-intc",
 | 
			
		||||
                          R_MAX * 4);
 | 
			
		||||
    sysbus_init_mmio(sbd, &p->mmio);
 | 
			
		||||
    return 0;
 | 
			
		||||
    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property xilinx_intc_properties[] = {
 | 
			
		||||
@@ -183,9 +181,7 @@ static Property xilinx_intc_properties[] = {
 | 
			
		||||
static void xilinx_intc_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    k->init = xilinx_intc_init;
 | 
			
		||||
    dc->props = xilinx_intc_properties;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -193,6 +189,7 @@ static const TypeInfo xilinx_intc_info = {
 | 
			
		||||
    .name          = TYPE_XILINX_INTC,
 | 
			
		||||
    .parent        = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(struct xlx_pic),
 | 
			
		||||
    .instance_init = xilinx_intc_init,
 | 
			
		||||
    .class_init    = xilinx_intc_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -86,11 +86,6 @@ static inline uint32_t get_parallel_irq(PC87312State *s)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool is_parallel_epp(PC87312State *s)
 | 
			
		||||
{
 | 
			
		||||
    return s->regs[REG_PTR] & PTR_EPP_MODE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* UARTs */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -178,24 +178,24 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_a
 | 
			
		||||
    /* Small bootloader */
 | 
			
		||||
    p = (uint32_t *) base;
 | 
			
		||||
 | 
			
		||||
    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                      /* nop */
 | 
			
		||||
    stl_p(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                      /* nop */
 | 
			
		||||
 | 
			
		||||
    /* Second part of the bootloader */
 | 
			
		||||
    p = (uint32_t *) (base + 0x040);
 | 
			
		||||
 | 
			
		||||
    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
 | 
			
		||||
    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
 | 
			
		||||
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
 | 
			
		||||
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
 | 
			
		||||
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
 | 
			
		||||
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
 | 
			
		||||
    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
 | 
			
		||||
    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
 | 
			
		||||
    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
 | 
			
		||||
    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
 | 
			
		||||
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                      /* nop */
 | 
			
		||||
    stl_p(p++, 0x3c040000);                                      /* lui a0, 0 */
 | 
			
		||||
    stl_p(p++, 0x34840002);                                      /* ori a0, a0, 2 */
 | 
			
		||||
    stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
 | 
			
		||||
    stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
 | 
			
		||||
    stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
 | 
			
		||||
    stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
 | 
			
		||||
    stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
 | 
			
		||||
    stl_p(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
 | 
			
		||||
    stl_p(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
 | 
			
		||||
    stl_p(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
 | 
			
		||||
    stl_p(p++, 0x03e00008);                                      /* jr ra */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                      /* nop */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -609,136 +609,136 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
 | 
			
		||||
 | 
			
		||||
    /* Small bootloader */
 | 
			
		||||
    p = (uint32_t *)base;
 | 
			
		||||
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                      /* nop */
 | 
			
		||||
    stl_p(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                      /* nop */
 | 
			
		||||
 | 
			
		||||
    /* YAMON service vector */
 | 
			
		||||
    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
 | 
			
		||||
    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
 | 
			
		||||
    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
 | 
			
		||||
    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
 | 
			
		||||
    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
 | 
			
		||||
    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
 | 
			
		||||
    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
 | 
			
		||||
    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
 | 
			
		||||
    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
 | 
			
		||||
    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
 | 
			
		||||
    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
 | 
			
		||||
    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
 | 
			
		||||
    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
 | 
			
		||||
    stl_p(base + 0x500, 0xbfc00580);      /* start: */
 | 
			
		||||
    stl_p(base + 0x504, 0xbfc0083c);      /* print_count: */
 | 
			
		||||
    stl_p(base + 0x520, 0xbfc00580);      /* start: */
 | 
			
		||||
    stl_p(base + 0x52c, 0xbfc00800);      /* flush_cache: */
 | 
			
		||||
    stl_p(base + 0x534, 0xbfc00808);      /* print: */
 | 
			
		||||
    stl_p(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
 | 
			
		||||
    stl_p(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
 | 
			
		||||
    stl_p(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
 | 
			
		||||
    stl_p(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
 | 
			
		||||
    stl_p(base + 0x548, 0xbfc00800);      /* reg_esr: */
 | 
			
		||||
    stl_p(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
 | 
			
		||||
    stl_p(base + 0x550, 0xbfc00800);      /* getchar: */
 | 
			
		||||
    stl_p(base + 0x554, 0xbfc00800);      /* syscon_read: */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /* Second part of the bootloader */
 | 
			
		||||
    p = (uint32_t *) (base + 0x580);
 | 
			
		||||
    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
 | 
			
		||||
    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
 | 
			
		||||
    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
 | 
			
		||||
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
 | 
			
		||||
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
 | 
			
		||||
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
 | 
			
		||||
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
 | 
			
		||||
    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
 | 
			
		||||
    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
 | 
			
		||||
    stl_p(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
 | 
			
		||||
    stl_p(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
 | 
			
		||||
    stl_p(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
 | 
			
		||||
    stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
 | 
			
		||||
    stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
 | 
			
		||||
    stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
 | 
			
		||||
    stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
 | 
			
		||||
    stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
 | 
			
		||||
    stl_p(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
 | 
			
		||||
 | 
			
		||||
    /* Load BAR registers as done by YAMON */
 | 
			
		||||
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
 | 
			
		||||
    stl_p(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
			
		||||
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
 | 
			
		||||
    stl_p(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
 | 
			
		||||
#else
 | 
			
		||||
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
 | 
			
		||||
    stl_p(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
 | 
			
		||||
#endif
 | 
			
		||||
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
 | 
			
		||||
    stl_p(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
 | 
			
		||||
 | 
			
		||||
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
 | 
			
		||||
    stl_p(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
			
		||||
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
 | 
			
		||||
    stl_p(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
 | 
			
		||||
#else
 | 
			
		||||
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
 | 
			
		||||
    stl_p(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
 | 
			
		||||
#endif
 | 
			
		||||
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
 | 
			
		||||
    stl_p(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
 | 
			
		||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
			
		||||
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
 | 
			
		||||
    stl_p(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
 | 
			
		||||
#else
 | 
			
		||||
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
 | 
			
		||||
    stl_p(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
 | 
			
		||||
#endif
 | 
			
		||||
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
 | 
			
		||||
    stl_p(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
			
		||||
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
 | 
			
		||||
    stl_p(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
 | 
			
		||||
#else
 | 
			
		||||
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
 | 
			
		||||
    stl_p(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
 | 
			
		||||
#endif
 | 
			
		||||
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
 | 
			
		||||
    stl_p(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
 | 
			
		||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
			
		||||
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
 | 
			
		||||
    stl_p(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
 | 
			
		||||
#else
 | 
			
		||||
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
 | 
			
		||||
    stl_p(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
 | 
			
		||||
#endif
 | 
			
		||||
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
 | 
			
		||||
    stl_p(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
			
		||||
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
 | 
			
		||||
    stl_p(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
 | 
			
		||||
#else
 | 
			
		||||
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
 | 
			
		||||
    stl_p(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
 | 
			
		||||
#endif
 | 
			
		||||
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
 | 
			
		||||
    stl_p(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
 | 
			
		||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
			
		||||
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
 | 
			
		||||
    stl_p(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
 | 
			
		||||
#else
 | 
			
		||||
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
 | 
			
		||||
    stl_p(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
 | 
			
		||||
#endif
 | 
			
		||||
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
 | 
			
		||||
    stl_p(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
 | 
			
		||||
 | 
			
		||||
    /* Jump to kernel code */
 | 
			
		||||
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
 | 
			
		||||
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
 | 
			
		||||
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                      /* nop */
 | 
			
		||||
    stl_p(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
 | 
			
		||||
    stl_p(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
 | 
			
		||||
    stl_p(p++, 0x03e00008);                                      /* jr ra */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                      /* nop */
 | 
			
		||||
 | 
			
		||||
    /* YAMON subroutines */
 | 
			
		||||
    p = (uint32_t *) (base + 0x800);
 | 
			
		||||
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
 | 
			
		||||
    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
 | 
			
		||||
    stl_p(p++, 0x03e00008);                                     /* jr ra */
 | 
			
		||||
    stl_p(p++, 0x24020000);                                     /* li v0,0 */
 | 
			
		||||
   /* 808 YAMON print */
 | 
			
		||||
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
 | 
			
		||||
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
 | 
			
		||||
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
 | 
			
		||||
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
 | 
			
		||||
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
 | 
			
		||||
    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_raw(p++, 0x08000205);                                     /* j 814 */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
 | 
			
		||||
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
 | 
			
		||||
    stl_p(p++, 0x03e06821);                                     /* move t5,ra */
 | 
			
		||||
    stl_p(p++, 0x00805821);                                     /* move t3,a0 */
 | 
			
		||||
    stl_p(p++, 0x00a05021);                                     /* move t2,a1 */
 | 
			
		||||
    stl_p(p++, 0x91440000);                                     /* lbu a0,0(t2) */
 | 
			
		||||
    stl_p(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
 | 
			
		||||
    stl_p(p++, 0x10800005);                                     /* beqz a0,834 */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_p(p++, 0x0ff0021c);                                     /* jal 870 */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_p(p++, 0x08000205);                                     /* j 814 */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_p(p++, 0x01a00008);                                     /* jr t5 */
 | 
			
		||||
    stl_p(p++, 0x01602021);                                     /* move a0,t3 */
 | 
			
		||||
    /* 0x83c YAMON print_count */
 | 
			
		||||
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
 | 
			
		||||
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
 | 
			
		||||
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
 | 
			
		||||
    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
 | 
			
		||||
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
 | 
			
		||||
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
 | 
			
		||||
    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
 | 
			
		||||
    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
 | 
			
		||||
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
 | 
			
		||||
    stl_p(p++, 0x03e06821);                                     /* move t5,ra */
 | 
			
		||||
    stl_p(p++, 0x00805821);                                     /* move t3,a0 */
 | 
			
		||||
    stl_p(p++, 0x00a05021);                                     /* move t2,a1 */
 | 
			
		||||
    stl_p(p++, 0x00c06021);                                     /* move t4,a2 */
 | 
			
		||||
    stl_p(p++, 0x91440000);                                     /* lbu a0,0(t2) */
 | 
			
		||||
    stl_p(p++, 0x0ff0021c);                                     /* jal 870 */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_p(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
 | 
			
		||||
    stl_p(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
 | 
			
		||||
    stl_p(p++, 0x1580fffa);                                     /* bnez t4,84c */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_p(p++, 0x01a00008);                                     /* jr t5 */
 | 
			
		||||
    stl_p(p++, 0x01602021);                                     /* move a0,t3 */
 | 
			
		||||
    /* 0x870 */
 | 
			
		||||
    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
 | 
			
		||||
    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
 | 
			
		||||
    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
 | 
			
		||||
    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
 | 
			
		||||
    stl_raw(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
 | 
			
		||||
    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
 | 
			
		||||
    stl_p(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
 | 
			
		||||
    stl_p(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
 | 
			
		||||
    stl_p(p++, 0x91090005);                                     /* lbu t1,5(t0) */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_p(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
 | 
			
		||||
    stl_p(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
 | 
			
		||||
    stl_p(p++, 0x00000000);                                     /* nop */
 | 
			
		||||
    stl_p(p++, 0x03e00008);                                     /* jr ra */
 | 
			
		||||
    stl_p(p++, 0xa1040000);                                     /* sb a0,0(t0) */
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@
 | 
			
		||||
#define GEM_IER           (0x00000028/4) /* Interrupt Enable reg */
 | 
			
		||||
#define GEM_IDR           (0x0000002C/4) /* Interrupt Disable reg */
 | 
			
		||||
#define GEM_IMR           (0x00000030/4) /* Interrupt Mask reg */
 | 
			
		||||
#define GEM_PHYMNTNC      (0x00000034/4) /* Phy Maintaince reg */
 | 
			
		||||
#define GEM_PHYMNTNC      (0x00000034/4) /* Phy Maintenance reg */
 | 
			
		||||
#define GEM_RXPAUSE       (0x00000038/4) /* RX Pause Time reg */
 | 
			
		||||
#define GEM_TXPAUSE       (0x0000003C/4) /* TX Pause Time reg */
 | 
			
		||||
#define GEM_TXPARTIALSF   (0x00000040/4) /* TX Partial Store and Forward */
 | 
			
		||||
@@ -150,7 +150,7 @@
 | 
			
		||||
#define GEM_NWCTRL_LOCALLOOP   0x00000002 /* Local Loopback */
 | 
			
		||||
 | 
			
		||||
#define GEM_NWCFG_STRIP_FCS    0x00020000 /* Strip FCS field */
 | 
			
		||||
#define GEM_NWCFG_LERR_DISC    0x00010000 /* Discard RX frames with lenth err */
 | 
			
		||||
#define GEM_NWCFG_LERR_DISC    0x00010000 /* Discard RX frames with len err */
 | 
			
		||||
#define GEM_NWCFG_BUFF_OFST_M  0x0000C000 /* Receive buffer offset mask */
 | 
			
		||||
#define GEM_NWCFG_BUFF_OFST_S  14         /* Receive buffer offset shift */
 | 
			
		||||
#define GEM_NWCFG_UCAST_HASH   0x00000080 /* accept unicast if hash match */
 | 
			
		||||
@@ -397,7 +397,7 @@ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 | 
			
		||||
 */
 | 
			
		||||
static void gem_init_register_masks(GemState *s)
 | 
			
		||||
{
 | 
			
		||||
    /* Mask of register bits which are read only*/
 | 
			
		||||
    /* Mask of register bits which are read only */
 | 
			
		||||
    memset(&s->regs_ro[0], 0, sizeof(s->regs_ro));
 | 
			
		||||
    s->regs_ro[GEM_NWCTRL]   = 0xFFF80000;
 | 
			
		||||
    s->regs_ro[GEM_NWSTATUS] = 0xFFFFFFFF;
 | 
			
		||||
@@ -719,7 +719,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 | 
			
		||||
        unsigned crc_val;
 | 
			
		||||
 | 
			
		||||
        /* The application wants the FCS field, which QEMU does not provide.
 | 
			
		||||
         * We must try and caclculate one.
 | 
			
		||||
         * We must try and calculate one.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        memcpy(rxbuf, buf, size);
 | 
			
		||||
@@ -871,7 +871,7 @@ static void gem_transmit(GemState *s)
 | 
			
		||||
 | 
			
		||||
    DB_PRINT("\n");
 | 
			
		||||
 | 
			
		||||
    /* The packet we will hand off to qemu.
 | 
			
		||||
    /* The packet we will hand off to QEMU.
 | 
			
		||||
     * Packets scattered across multiple descriptors are gathered to this
 | 
			
		||||
     * one contiguous buffer first.
 | 
			
		||||
     */
 | 
			
		||||
@@ -880,8 +880,10 @@ static void gem_transmit(GemState *s)
 | 
			
		||||
 | 
			
		||||
    /* read current descriptor */
 | 
			
		||||
    packet_desc_addr = s->tx_desc_addr;
 | 
			
		||||
 | 
			
		||||
    DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
 | 
			
		||||
    cpu_physical_memory_read(packet_desc_addr,
 | 
			
		||||
                             (uint8_t *)&desc[0], sizeof(desc));
 | 
			
		||||
                             (uint8_t *)desc, sizeof(desc));
 | 
			
		||||
    /* Handle all descriptors owned by hardware */
 | 
			
		||||
    while (tx_desc_get_used(desc) == 0) {
 | 
			
		||||
 | 
			
		||||
@@ -911,15 +913,17 @@ static void gem_transmit(GemState *s)
 | 
			
		||||
 | 
			
		||||
        /* Last descriptor for this packet; hand the whole thing off */
 | 
			
		||||
        if (tx_desc_get_last(desc)) {
 | 
			
		||||
            unsigned    desc_first[2];
 | 
			
		||||
 | 
			
		||||
            /* Modify the 1st descriptor of this packet to be owned by
 | 
			
		||||
             * the processor.
 | 
			
		||||
             */
 | 
			
		||||
            cpu_physical_memory_read(s->tx_desc_addr,
 | 
			
		||||
                                     (uint8_t *)&desc[0], sizeof(desc));
 | 
			
		||||
            tx_desc_set_used(desc);
 | 
			
		||||
            cpu_physical_memory_write(s->tx_desc_addr,
 | 
			
		||||
                                      (uint8_t *)&desc[0], sizeof(desc));
 | 
			
		||||
            /* Advance the hardare current descriptor past this packet */
 | 
			
		||||
            cpu_physical_memory_read(s->tx_desc_addr, (uint8_t *)desc_first,
 | 
			
		||||
                                     sizeof(desc_first));
 | 
			
		||||
            tx_desc_set_used(desc_first);
 | 
			
		||||
            cpu_physical_memory_write(s->tx_desc_addr, (uint8_t *)desc_first,
 | 
			
		||||
                                      sizeof(desc_first));
 | 
			
		||||
            /* Advance the hardware current descriptor past this packet */
 | 
			
		||||
            if (tx_desc_get_wrap(desc)) {
 | 
			
		||||
                s->tx_desc_addr = s->regs[GEM_TXQBASE];
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -960,8 +964,9 @@ static void gem_transmit(GemState *s)
 | 
			
		||||
        } else {
 | 
			
		||||
            packet_desc_addr += 8;
 | 
			
		||||
        }
 | 
			
		||||
        DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
 | 
			
		||||
        cpu_physical_memory_read(packet_desc_addr,
 | 
			
		||||
                                 (uint8_t *)&desc[0], sizeof(desc));
 | 
			
		||||
                                 (uint8_t *)desc, sizeof(desc));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tx_desc_get_used(desc)) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								hw/net/e1000.c
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								hw/net/e1000.c
									
									
									
									
									
								
							@@ -69,23 +69,11 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * HW models:
 | 
			
		||||
 *  E1000_DEV_ID_82540EM works with Windows and Linux
 | 
			
		||||
 *  E1000_DEV_ID_82573L OK with windoze and Linux 2.6.22,
 | 
			
		||||
 *	appears to perform better than 82540EM, but breaks with Linux 2.6.18
 | 
			
		||||
 *  E1000_DEV_ID_82540EM works with Windows, Linux, and OS X <= 10.8
 | 
			
		||||
 *  E1000_DEV_ID_82544GC_COPPER appears to work; not well tested
 | 
			
		||||
 *  E1000_DEV_ID_82545EM_COPPER works with Linux and OS X >= 10.6
 | 
			
		||||
 *  Others never tested
 | 
			
		||||
 */
 | 
			
		||||
enum { E1000_DEVID = E1000_DEV_ID_82540EM };
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * May need to specify additional MAC-to-PHY entries --
 | 
			
		||||
 * Intel's Windows driver refuses to initialize unless they match
 | 
			
		||||
 */
 | 
			
		||||
enum {
 | 
			
		||||
    PHY_ID2_INIT = E1000_DEVID == E1000_DEV_ID_82573L ?		0xcc2 :
 | 
			
		||||
                   E1000_DEVID == E1000_DEV_ID_82544GC_COPPER ?	0xc30 :
 | 
			
		||||
                   /* default to E1000_DEV_ID_82540EM */	0xc20
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct E1000State_st {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
@@ -151,10 +139,20 @@ typedef struct E1000State_st {
 | 
			
		||||
    uint32_t compat_flags;
 | 
			
		||||
} E1000State;
 | 
			
		||||
 | 
			
		||||
#define TYPE_E1000 "e1000"
 | 
			
		||||
typedef struct E1000BaseClass {
 | 
			
		||||
    PCIDeviceClass parent_class;
 | 
			
		||||
    uint16_t phy_id2;
 | 
			
		||||
} E1000BaseClass;
 | 
			
		||||
 | 
			
		||||
#define TYPE_E1000_BASE "e1000-base"
 | 
			
		||||
 | 
			
		||||
#define E1000(obj) \
 | 
			
		||||
    OBJECT_CHECK(E1000State, (obj), TYPE_E1000)
 | 
			
		||||
    OBJECT_CHECK(E1000State, (obj), TYPE_E1000_BASE)
 | 
			
		||||
 | 
			
		||||
#define E1000_DEVICE_CLASS(klass) \
 | 
			
		||||
     OBJECT_CLASS_CHECK(E1000BaseClass, (klass), TYPE_E1000_BASE)
 | 
			
		||||
#define E1000_DEVICE_GET_CLASS(obj) \
 | 
			
		||||
    OBJECT_GET_CLASS(E1000BaseClass, (obj), TYPE_E1000_BASE)
 | 
			
		||||
 | 
			
		||||
#define	defreg(x)	x = (E1000_##x>>2)
 | 
			
		||||
enum {
 | 
			
		||||
@@ -232,10 +230,11 @@ static const char phy_regcap[0x20] = {
 | 
			
		||||
    [PHY_ID2] = PHY_R,		[M88E1000_PHY_SPEC_STATUS] = PHY_R
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* PHY_ID2 documented in 8254x_GBe_SDM.pdf, pp. 250 */
 | 
			
		||||
static const uint16_t phy_reg_init[] = {
 | 
			
		||||
    [PHY_CTRL] = 0x1140,
 | 
			
		||||
    [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */
 | 
			
		||||
    [PHY_ID1] = 0x141,				[PHY_ID2] = PHY_ID2_INIT,
 | 
			
		||||
    [PHY_ID1] = 0x141, /* [PHY_ID2] configured per DevId, from e1000_reset() */
 | 
			
		||||
    [PHY_1000T_CTRL] = 0x0e00,			[M88E1000_PHY_SPEC_CTRL] = 0x360,
 | 
			
		||||
    [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60,	[PHY_AUTONEG_ADV] = 0xde1,
 | 
			
		||||
    [PHY_LP_ABILITY] = 0x1e0,			[PHY_1000T_STATUS] = 0x3c00,
 | 
			
		||||
@@ -272,10 +271,6 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val)
 | 
			
		||||
    uint32_t pending_ints;
 | 
			
		||||
    uint32_t mit_delay;
 | 
			
		||||
 | 
			
		||||
    if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
 | 
			
		||||
        /* Only for 8257x */
 | 
			
		||||
        val |= E1000_ICR_INT_ASSERTED;
 | 
			
		||||
    }
 | 
			
		||||
    s->mac_reg[ICR] = val;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
@@ -375,6 +370,7 @@ rxbufsize(uint32_t v)
 | 
			
		||||
static void e1000_reset(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    E1000State *d = opaque;
 | 
			
		||||
    E1000BaseClass *edc = E1000_DEVICE_GET_CLASS(d);
 | 
			
		||||
    uint8_t *macaddr = d->conf.macaddr.a;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
@@ -385,6 +381,7 @@ static void e1000_reset(void *opaque)
 | 
			
		||||
    d->mit_ide = 0;
 | 
			
		||||
    memset(d->phy_reg, 0, sizeof d->phy_reg);
 | 
			
		||||
    memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
 | 
			
		||||
    d->phy_reg[PHY_ID2] = edc->phy_id2;
 | 
			
		||||
    memset(d->mac_reg, 0, sizeof d->mac_reg);
 | 
			
		||||
    memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
 | 
			
		||||
    d->rxbuf_min_shift = 1;
 | 
			
		||||
@@ -1440,9 +1437,13 @@ static const VMStateDescription vmstate_e1000 = {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * EEPROM contents documented in Tables 5-2 and 5-3, pp. 98-102.
 | 
			
		||||
 * Note: A valid DevId will be inserted during pci_e1000_init().
 | 
			
		||||
 */
 | 
			
		||||
static const uint16_t e1000_eeprom_template[64] = {
 | 
			
		||||
    0x0000, 0x0000, 0x0000, 0x0000,      0xffff, 0x0000,      0x0000, 0x0000,
 | 
			
		||||
    0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
 | 
			
		||||
    0x3000, 0x1000, 0x6403, 0 /*DevId*/, 0x8086, 0 /*DevId*/, 0x8086, 0x3040,
 | 
			
		||||
    0x0008, 0x2000, 0x7e14, 0x0048,      0x1000, 0x00d8,      0x0000, 0x2700,
 | 
			
		||||
    0x6cc9, 0x3150, 0x0722, 0x040b,      0x0984, 0x0000,      0xc000, 0x0706,
 | 
			
		||||
    0x1008, 0x0000, 0x0f04, 0x7fff,      0x4d01, 0xffff,      0xffff, 0xffff,
 | 
			
		||||
@@ -1507,6 +1508,7 @@ static int pci_e1000_init(PCIDevice *pci_dev)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev = DEVICE(pci_dev);
 | 
			
		||||
    E1000State *d = E1000(pci_dev);
 | 
			
		||||
    PCIDeviceClass *pdc = PCI_DEVICE_GET_CLASS(pci_dev);
 | 
			
		||||
    uint8_t *pci_conf;
 | 
			
		||||
    uint16_t checksum = 0;
 | 
			
		||||
    int i;
 | 
			
		||||
@@ -1531,6 +1533,7 @@ static int pci_e1000_init(PCIDevice *pci_dev)
 | 
			
		||||
    macaddr = d->conf.macaddr.a;
 | 
			
		||||
    for (i = 0; i < 3; i++)
 | 
			
		||||
        d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
 | 
			
		||||
    d->eeprom_data[11] = d->eeprom_data[13] = pdc->device_id;
 | 
			
		||||
    for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
 | 
			
		||||
        checksum += d->eeprom_data[i];
 | 
			
		||||
    checksum = (uint16_t) EEPROM_SUM - checksum;
 | 
			
		||||
@@ -1564,17 +1567,27 @@ static Property e1000_properties[] = {
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct E1000Info {
 | 
			
		||||
    const char *name;
 | 
			
		||||
    uint16_t   device_id;
 | 
			
		||||
    uint8_t    revision;
 | 
			
		||||
    uint16_t   phy_id2;
 | 
			
		||||
} E1000Info;
 | 
			
		||||
 | 
			
		||||
static void e1000_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 | 
			
		||||
    E1000BaseClass *e = E1000_DEVICE_CLASS(klass);
 | 
			
		||||
    const E1000Info *info = data;
 | 
			
		||||
 | 
			
		||||
    k->init = pci_e1000_init;
 | 
			
		||||
    k->exit = pci_e1000_uninit;
 | 
			
		||||
    k->romfile = "efi-e1000.rom";
 | 
			
		||||
    k->vendor_id = PCI_VENDOR_ID_INTEL;
 | 
			
		||||
    k->device_id = E1000_DEVID;
 | 
			
		||||
    k->revision = 0x03;
 | 
			
		||||
    k->device_id = info->device_id;
 | 
			
		||||
    k->revision = info->revision;
 | 
			
		||||
    e->phy_id2 = info->phy_id2;
 | 
			
		||||
    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 | 
			
		||||
    dc->desc = "Intel Gigabit Ethernet";
 | 
			
		||||
@@ -1583,16 +1596,57 @@ static void e1000_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
    dc->props = e1000_properties;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo e1000_info = {
 | 
			
		||||
    .name          = TYPE_E1000,
 | 
			
		||||
static const TypeInfo e1000_base_info = {
 | 
			
		||||
    .name          = TYPE_E1000_BASE,
 | 
			
		||||
    .parent        = TYPE_PCI_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(E1000State),
 | 
			
		||||
    .class_init    = e1000_class_init,
 | 
			
		||||
    .class_size    = sizeof(E1000BaseClass),
 | 
			
		||||
    .abstract      = true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const E1000Info e1000_devices[] = {
 | 
			
		||||
    {
 | 
			
		||||
        .name      = "e1000-82540em",
 | 
			
		||||
        .device_id = E1000_DEV_ID_82540EM,
 | 
			
		||||
        .revision  = 0x03,
 | 
			
		||||
        .phy_id2   = E1000_PHY_ID2_8254xx_DEFAULT,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .name      = "e1000-82544gc",
 | 
			
		||||
        .device_id = E1000_DEV_ID_82544GC_COPPER,
 | 
			
		||||
        .revision  = 0x03,
 | 
			
		||||
        .phy_id2   = E1000_PHY_ID2_82544x,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .name      = "e1000-82545em",
 | 
			
		||||
        .device_id = E1000_DEV_ID_82545EM_COPPER,
 | 
			
		||||
        .revision  = 0x03,
 | 
			
		||||
        .phy_id2   = E1000_PHY_ID2_8254xx_DEFAULT,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const TypeInfo e1000_default_info = {
 | 
			
		||||
    .name          = "e1000",
 | 
			
		||||
    .parent        = "e1000-82540em",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void e1000_register_types(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&e1000_info);
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    type_register_static(&e1000_base_info);
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(e1000_devices); i++) {
 | 
			
		||||
        const E1000Info *info = &e1000_devices[i];
 | 
			
		||||
        TypeInfo type_info = {};
 | 
			
		||||
 | 
			
		||||
        type_info.name = info->name;
 | 
			
		||||
        type_info.parent = TYPE_E1000_BASE;
 | 
			
		||||
        type_info.class_data = (void *)info;
 | 
			
		||||
        type_info.class_init = e1000_class_init;
 | 
			
		||||
 | 
			
		||||
        type_register(&type_info);
 | 
			
		||||
    }
 | 
			
		||||
    type_register_static(&e1000_default_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(e1000_register_types)
 | 
			
		||||
 
 | 
			
		||||
@@ -99,6 +99,12 @@
 | 
			
		||||
#define E1000_DEV_ID_ICH8_IFE_G          0x10C5
 | 
			
		||||
#define E1000_DEV_ID_ICH8_IGP_M          0x104D
 | 
			
		||||
 | 
			
		||||
/* Device Specific Register Defaults */
 | 
			
		||||
#define E1000_PHY_ID2_82541x 0x380
 | 
			
		||||
#define E1000_PHY_ID2_82544x 0xC30
 | 
			
		||||
#define E1000_PHY_ID2_8254xx_DEFAULT 0xC20 /* 82540x, 82545x, and 82546x */
 | 
			
		||||
#define E1000_PHY_ID2_82573x 0xCC0
 | 
			
		||||
 | 
			
		||||
/* Register Set. (82543, 82544)
 | 
			
		||||
 *
 | 
			
		||||
 * Registers are defined to be 32 bits and  should be accessed as 32 bit values.
 | 
			
		||||
 
 | 
			
		||||
@@ -98,6 +98,7 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
 | 
			
		||||
 | 
			
		||||
    dc->realize = isa_ne2000_realizefn;
 | 
			
		||||
    dc->props = ne2000_isa_properties;
 | 
			
		||||
    dc->vmsd = &vmstate_isa_ne2000;
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2050,7 +2050,7 @@ vmxnet3_cleanup_msix(VMXNET3State *s)
 | 
			
		||||
    PCIDevice *d = PCI_DEVICE(s);
 | 
			
		||||
 | 
			
		||||
    if (s->msix_used) {
 | 
			
		||||
        msix_vector_unuse(d, VMXNET3_MAX_INTRS);
 | 
			
		||||
        vmxnet3_unuse_msix_vectors(s, VMXNET3_MAX_INTRS);
 | 
			
		||||
        msix_uninit(d, &s->msix_bar, &s->msix_bar);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -196,14 +196,22 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
 | 
			
		||||
    memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);
 | 
			
		||||
 | 
			
		||||
    s->regs[rxbase + R_RX_CTRL0] |= CTRL_S;
 | 
			
		||||
    if (s->regs[rxbase + R_RX_CTRL0] & CTRL_I)
 | 
			
		||||
    if (s->regs[R_RX_CTRL0] & CTRL_I) {
 | 
			
		||||
        eth_pulse_irq(s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If c_rx_pingpong was set flip buffers.  */
 | 
			
		||||
    s->rxbuf ^= s->c_rx_pingpong;
 | 
			
		||||
    return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void xilinx_ethlite_reset(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    struct xlx_ethlite *s = XILINX_ETHLITE(dev);
 | 
			
		||||
 | 
			
		||||
    s->rxbuf = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void eth_cleanup(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    struct xlx_ethlite *s = qemu_get_nic_opaque(nc);
 | 
			
		||||
@@ -219,23 +227,25 @@ static NetClientInfo net_xilinx_ethlite_info = {
 | 
			
		||||
    .cleanup = eth_cleanup,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int xilinx_ethlite_init(SysBusDevice *sbd)
 | 
			
		||||
static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev = DEVICE(sbd);
 | 
			
		||||
    struct xlx_ethlite *s = XILINX_ETHLITE(dev);
 | 
			
		||||
 | 
			
		||||
    sysbus_init_irq(sbd, &s->irq);
 | 
			
		||||
    s->rxbuf = 0;
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->mmio, OBJECT(s), ð_ops, s,
 | 
			
		||||
                          "xlnx.xps-ethernetlite", R_MAX * 4);
 | 
			
		||||
    sysbus_init_mmio(sbd, &s->mmio);
 | 
			
		||||
 | 
			
		||||
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
 | 
			
		||||
    s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
 | 
			
		||||
                          object_get_typename(OBJECT(dev)), dev->id, s);
 | 
			
		||||
    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void xilinx_ethlite_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    struct xlx_ethlite *s = XILINX_ETHLITE(obj);
 | 
			
		||||
 | 
			
		||||
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&s->mmio, obj, ð_ops, s,
 | 
			
		||||
                          "xlnx.xps-ethernetlite", R_MAX * 4);
 | 
			
		||||
    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property xilinx_ethlite_properties[] = {
 | 
			
		||||
@@ -248,9 +258,9 @@ static Property xilinx_ethlite_properties[] = {
 | 
			
		||||
static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    k->init = xilinx_ethlite_init;
 | 
			
		||||
    dc->realize = xilinx_ethlite_realize;
 | 
			
		||||
    dc->reset = xilinx_ethlite_reset;
 | 
			
		||||
    dc->props = xilinx_ethlite_properties;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -258,6 +268,7 @@ static const TypeInfo xilinx_ethlite_info = {
 | 
			
		||||
    .name          = TYPE_XILINX_ETHLITE,
 | 
			
		||||
    .parent        = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(struct xlx_ethlite),
 | 
			
		||||
    .instance_init = xilinx_ethlite_init,
 | 
			
		||||
    .class_init    = xilinx_ethlite_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,16 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 | 
			
		||||
#define APB_DPRINTF(fmt, ...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* debug IOMMU */
 | 
			
		||||
//#define DEBUG_IOMMU
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_IOMMU
 | 
			
		||||
#define IOMMU_DPRINTF(fmt, ...) \
 | 
			
		||||
do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
 | 
			
		||||
#else
 | 
			
		||||
#define IOMMU_DPRINTF(fmt, ...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Chipset docs:
 | 
			
		||||
 * PBM: "UltraSPARC IIi User's Manual",
 | 
			
		||||
@@ -70,6 +80,51 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 | 
			
		||||
#define MAX_IVEC 0x40
 | 
			
		||||
#define NO_IRQ_REQUEST (MAX_IVEC + 1)
 | 
			
		||||
 | 
			
		||||
#define IOMMU_PAGE_SIZE_8K      (1ULL << 13)
 | 
			
		||||
#define IOMMU_PAGE_MASK_8K      (~(IOMMU_PAGE_SIZE_8K - 1))
 | 
			
		||||
#define IOMMU_PAGE_SIZE_64K     (1ULL << 16)
 | 
			
		||||
#define IOMMU_PAGE_MASK_64K     (~(IOMMU_PAGE_SIZE_64K - 1))
 | 
			
		||||
 | 
			
		||||
#define IOMMU_NREGS             3
 | 
			
		||||
 | 
			
		||||
#define IOMMU_CTRL              0x0
 | 
			
		||||
#define IOMMU_CTRL_TBW_SIZE     (1ULL << 2)
 | 
			
		||||
#define IOMMU_CTRL_MMU_EN       (1ULL)
 | 
			
		||||
 | 
			
		||||
#define IOMMU_CTRL_TSB_SHIFT    16
 | 
			
		||||
 | 
			
		||||
#define IOMMU_BASE              0x8
 | 
			
		||||
 | 
			
		||||
#define IOMMU_TTE_DATA_V        (1ULL << 63)
 | 
			
		||||
#define IOMMU_TTE_DATA_SIZE     (1ULL << 61)
 | 
			
		||||
#define IOMMU_TTE_DATA_W        (1ULL << 1)
 | 
			
		||||
 | 
			
		||||
#define IOMMU_TTE_PHYS_MASK_8K  0x1ffffffe000ULL
 | 
			
		||||
#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL
 | 
			
		||||
 | 
			
		||||
#define IOMMU_TSB_8K_OFFSET_MASK_8M    0x00000000007fe000ULL
 | 
			
		||||
#define IOMMU_TSB_8K_OFFSET_MASK_16M   0x0000000000ffe000ULL
 | 
			
		||||
#define IOMMU_TSB_8K_OFFSET_MASK_32M   0x0000000001ffe000ULL
 | 
			
		||||
#define IOMMU_TSB_8K_OFFSET_MASK_64M   0x0000000003ffe000ULL
 | 
			
		||||
#define IOMMU_TSB_8K_OFFSET_MASK_128M  0x0000000007ffe000ULL
 | 
			
		||||
#define IOMMU_TSB_8K_OFFSET_MASK_256M  0x000000000fffe000ULL
 | 
			
		||||
#define IOMMU_TSB_8K_OFFSET_MASK_512M  0x000000001fffe000ULL
 | 
			
		||||
#define IOMMU_TSB_8K_OFFSET_MASK_1G    0x000000003fffe000ULL
 | 
			
		||||
 | 
			
		||||
#define IOMMU_TSB_64K_OFFSET_MASK_64M  0x0000000003ff0000ULL
 | 
			
		||||
#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL
 | 
			
		||||
#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL
 | 
			
		||||
#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL
 | 
			
		||||
#define IOMMU_TSB_64K_OFFSET_MASK_1G   0x000000003fff0000ULL
 | 
			
		||||
#define IOMMU_TSB_64K_OFFSET_MASK_2G   0x000000007fff0000ULL
 | 
			
		||||
 | 
			
		||||
typedef struct IOMMUState {
 | 
			
		||||
    AddressSpace iommu_as;
 | 
			
		||||
    MemoryRegion iommu;
 | 
			
		||||
 | 
			
		||||
    uint64_t regs[IOMMU_NREGS];
 | 
			
		||||
} IOMMUState;
 | 
			
		||||
 | 
			
		||||
#define TYPE_APB "pbm"
 | 
			
		||||
 | 
			
		||||
#define APB_DEVICE(obj) \
 | 
			
		||||
@@ -83,7 +138,7 @@ typedef struct APBState {
 | 
			
		||||
    MemoryRegion pci_mmio;
 | 
			
		||||
    MemoryRegion pci_ioport;
 | 
			
		||||
    uint64_t pci_irq_in;
 | 
			
		||||
    uint32_t iommu[4];
 | 
			
		||||
    IOMMUState iommu;
 | 
			
		||||
    uint32_t pci_control[16];
 | 
			
		||||
    uint32_t pci_irq_map[8];
 | 
			
		||||
    uint32_t obio_irq_map[32];
 | 
			
		||||
@@ -141,10 +196,217 @@ static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
 | 
			
		||||
    s->irq_request = NO_IRQ_REQUEST;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 | 
			
		||||
{
 | 
			
		||||
    IOMMUState *is = opaque;
 | 
			
		||||
 | 
			
		||||
    return &is->iommu_as;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr)
 | 
			
		||||
{
 | 
			
		||||
    IOMMUState *is = container_of(iommu, IOMMUState, iommu);
 | 
			
		||||
    hwaddr baseaddr, offset;
 | 
			
		||||
    uint64_t tte;
 | 
			
		||||
    uint32_t tsbsize;
 | 
			
		||||
    IOMMUTLBEntry ret = {
 | 
			
		||||
        .target_as = &address_space_memory,
 | 
			
		||||
        .iova = 0,
 | 
			
		||||
        .translated_addr = 0,
 | 
			
		||||
        .addr_mask = ~(hwaddr)0,
 | 
			
		||||
        .perm = IOMMU_NONE,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (!(is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_MMU_EN)) {
 | 
			
		||||
        /* IOMMU disabled, passthrough using standard 8K page */
 | 
			
		||||
        ret.iova = addr & IOMMU_PAGE_MASK_8K;
 | 
			
		||||
        ret.translated_addr = addr;
 | 
			
		||||
        ret.addr_mask = IOMMU_PAGE_MASK_8K;
 | 
			
		||||
        ret.perm = IOMMU_RW;
 | 
			
		||||
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    baseaddr = is->regs[IOMMU_BASE >> 3];
 | 
			
		||||
    tsbsize = (is->regs[IOMMU_CTRL >> 3] >> IOMMU_CTRL_TSB_SHIFT) & 0x7;
 | 
			
		||||
 | 
			
		||||
    if (is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_TBW_SIZE) {
 | 
			
		||||
        /* 64K */
 | 
			
		||||
        switch (tsbsize) {
 | 
			
		||||
        case 0:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_64M) >> 13;
 | 
			
		||||
            break;
 | 
			
		||||
        case 1:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_128M) >> 13;
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_256M) >> 13;
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_512M) >> 13;
 | 
			
		||||
            break;
 | 
			
		||||
        case 4:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_1G) >> 13;
 | 
			
		||||
            break;
 | 
			
		||||
        case 5:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_2G) >> 13;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            /* Not implemented, error */
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        /* 8K */
 | 
			
		||||
        switch (tsbsize) {
 | 
			
		||||
        case 0:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_8M) >> 10;
 | 
			
		||||
            break;
 | 
			
		||||
        case 1:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_16M) >> 10;
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_32M) >> 10;
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_64M) >> 10;
 | 
			
		||||
            break;
 | 
			
		||||
        case 4:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_128M) >> 10;
 | 
			
		||||
            break;
 | 
			
		||||
        case 5:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_256M) >> 10;
 | 
			
		||||
            break;
 | 
			
		||||
        case 6:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_512M) >> 10;
 | 
			
		||||
            break;
 | 
			
		||||
        case 7:
 | 
			
		||||
            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_1G) >> 10;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tte = ldq_be_phys(&address_space_memory, baseaddr + offset);
 | 
			
		||||
 | 
			
		||||
    if (!(tte & IOMMU_TTE_DATA_V)) {
 | 
			
		||||
        /* Invalid mapping */
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tte & IOMMU_TTE_DATA_W) {
 | 
			
		||||
        /* Writeable */
 | 
			
		||||
        ret.perm = IOMMU_RW;
 | 
			
		||||
    } else {
 | 
			
		||||
        ret.perm = IOMMU_RO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Extract phys */
 | 
			
		||||
    if (tte & IOMMU_TTE_DATA_SIZE) {
 | 
			
		||||
        /* 64K */
 | 
			
		||||
        ret.iova = addr & IOMMU_PAGE_MASK_64K;
 | 
			
		||||
        ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_64K;
 | 
			
		||||
        ret.addr_mask = (IOMMU_PAGE_SIZE_64K - 1);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* 8K */
 | 
			
		||||
        ret.iova = addr & IOMMU_PAGE_MASK_8K;
 | 
			
		||||
        ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_8K;
 | 
			
		||||
        ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MemoryRegionIOMMUOps pbm_iommu_ops = {
 | 
			
		||||
    .translate = pbm_translate_iommu,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void iommu_config_write(void *opaque, hwaddr addr,
 | 
			
		||||
                               uint64_t val, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    IOMMUState *is = opaque;
 | 
			
		||||
 | 
			
		||||
    IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64
 | 
			
		||||
                  " size: %d\n", addr, val, size);
 | 
			
		||||
 | 
			
		||||
    switch (addr) {
 | 
			
		||||
    case IOMMU_CTRL:
 | 
			
		||||
        if (size == 4) {
 | 
			
		||||
            is->regs[IOMMU_CTRL >> 3] &= 0xffffffffULL;
 | 
			
		||||
            is->regs[IOMMU_CTRL >> 3] |= val << 32;
 | 
			
		||||
        } else {
 | 
			
		||||
            is->regs[IOMMU_CTRL] = val;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case IOMMU_CTRL + 0x4:
 | 
			
		||||
        is->regs[IOMMU_CTRL >> 3] &= 0xffffffff00000000ULL;
 | 
			
		||||
        is->regs[IOMMU_CTRL >> 3] |= val & 0xffffffffULL;
 | 
			
		||||
        break;
 | 
			
		||||
    case IOMMU_BASE:
 | 
			
		||||
        if (size == 4) {
 | 
			
		||||
            is->regs[IOMMU_BASE >> 3] &= 0xffffffffULL;
 | 
			
		||||
            is->regs[IOMMU_BASE >> 3] |= val << 32;
 | 
			
		||||
        } else {
 | 
			
		||||
            is->regs[IOMMU_BASE] = val;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case IOMMU_BASE + 0x4:
 | 
			
		||||
        is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL;
 | 
			
		||||
        is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        qemu_log_mask(LOG_UNIMP,
 | 
			
		||||
                  "apb iommu: Unimplemented register write "
 | 
			
		||||
                  "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
 | 
			
		||||
                  addr, size, val);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    IOMMUState *is = opaque;
 | 
			
		||||
    uint64_t val;
 | 
			
		||||
 | 
			
		||||
    switch (addr) {
 | 
			
		||||
    case IOMMU_CTRL:
 | 
			
		||||
        if (size == 4) {
 | 
			
		||||
            val = is->regs[IOMMU_CTRL >> 3] >> 32;
 | 
			
		||||
        } else {
 | 
			
		||||
            val = is->regs[IOMMU_CTRL >> 3];
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case IOMMU_CTRL + 0x4:
 | 
			
		||||
        val = is->regs[IOMMU_CTRL >> 3] & 0xffffffffULL;
 | 
			
		||||
        break;
 | 
			
		||||
    case IOMMU_BASE:
 | 
			
		||||
        if (size == 4) {
 | 
			
		||||
            val = is->regs[IOMMU_BASE >> 3] >> 32;
 | 
			
		||||
        } else {
 | 
			
		||||
            val = is->regs[IOMMU_BASE >> 3];
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case IOMMU_BASE + 0x4:
 | 
			
		||||
        val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        qemu_log_mask(LOG_UNIMP,
 | 
			
		||||
                      "apb iommu: Unimplemented register read "
 | 
			
		||||
                      "reg 0x%" HWADDR_PRIx " size 0x%x\n",
 | 
			
		||||
                      addr, size);
 | 
			
		||||
        val = 0;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64
 | 
			
		||||
                  " size: %d\n", addr, val, size);
 | 
			
		||||
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void apb_config_writel (void *opaque, hwaddr addr,
 | 
			
		||||
                               uint64_t val, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    APBState *s = opaque;
 | 
			
		||||
    IOMMUState *is = &s->iommu;
 | 
			
		||||
 | 
			
		||||
    APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
 | 
			
		||||
 | 
			
		||||
@@ -152,10 +414,8 @@ static void apb_config_writel (void *opaque, hwaddr addr,
 | 
			
		||||
    case 0x30 ... 0x4f: /* DMA error registers */
 | 
			
		||||
        /* XXX: not implemented yet */
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x200 ... 0x20b: /* IOMMU */
 | 
			
		||||
        s->iommu[(addr & 0xf) >> 2] = val;
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x20c ... 0x3ff: /* IOMMU flush */
 | 
			
		||||
    case 0x200 ... 0x217: /* IOMMU */
 | 
			
		||||
        iommu_config_write(is, (addr & 0xf), val, size);
 | 
			
		||||
        break;
 | 
			
		||||
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
 | 
			
		||||
        if (addr & 4) {
 | 
			
		||||
@@ -228,6 +488,7 @@ static uint64_t apb_config_readl (void *opaque,
 | 
			
		||||
                                  hwaddr addr, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    APBState *s = opaque;
 | 
			
		||||
    IOMMUState *is = &s->iommu;
 | 
			
		||||
    uint32_t val;
 | 
			
		||||
 | 
			
		||||
    switch (addr & 0xffff) {
 | 
			
		||||
@@ -235,11 +496,8 @@ static uint64_t apb_config_readl (void *opaque,
 | 
			
		||||
        val = 0;
 | 
			
		||||
        /* XXX: not implemented yet */
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x200 ... 0x20b: /* IOMMU */
 | 
			
		||||
        val = s->iommu[(addr & 0xf) >> 2];
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x20c ... 0x3ff: /* IOMMU flush */
 | 
			
		||||
        val = 0;
 | 
			
		||||
    case 0x200 ... 0x217: /* IOMMU */
 | 
			
		||||
        val = iommu_config_read(is, (addr & 0xf), size);
 | 
			
		||||
        break;
 | 
			
		||||
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
 | 
			
		||||
        if (addr & 4) {
 | 
			
		||||
@@ -390,6 +648,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
 | 
			
		||||
    SysBusDevice *s;
 | 
			
		||||
    PCIHostState *phb;
 | 
			
		||||
    APBState *d;
 | 
			
		||||
    IOMMUState *is;
 | 
			
		||||
    PCIDevice *pci_dev;
 | 
			
		||||
    PCIBridge *br;
 | 
			
		||||
 | 
			
		||||
@@ -420,6 +679,15 @@ PCIBus *pci_apb_init(hwaddr special_base,
 | 
			
		||||
 | 
			
		||||
    pci_create_simple(phb->bus, 0, "pbm-pci");
 | 
			
		||||
 | 
			
		||||
    /* APB IOMMU */
 | 
			
		||||
    is = &d->iommu;
 | 
			
		||||
    memset(is, 0, sizeof(IOMMUState));
 | 
			
		||||
 | 
			
		||||
    memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
 | 
			
		||||
                             "iommu-apb", UINT64_MAX);
 | 
			
		||||
    address_space_init(&is->iommu_as, &is->iommu, "pbm-as");
 | 
			
		||||
    pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
 | 
			
		||||
 | 
			
		||||
    /* APB secondary busses */
 | 
			
		||||
    pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
 | 
			
		||||
                                   "pbm-bridge");
 | 
			
		||||
 
 | 
			
		||||
@@ -47,10 +47,6 @@ static void q35_host_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
 | 
			
		||||
    sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
 | 
			
		||||
 | 
			
		||||
    if (pcie_host_init(PCIE_HOST_BRIDGE(s)) < 0) {
 | 
			
		||||
        error_setg(errp, "failed to initialize pcie host");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    pci->bus = pci_bus_new(DEVICE(s), "pcie.0",
 | 
			
		||||
                           s->mch.pci_address_space, s->mch.address_space_io,
 | 
			
		||||
                           0, TYPE_PCIE_BUS);
 | 
			
		||||
 
 | 
			
		||||
@@ -83,11 +83,11 @@ static const MemoryRegionOps pcie_mmcfg_ops = {
 | 
			
		||||
    .endianness = DEVICE_NATIVE_ENDIAN,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int pcie_host_init(PCIExpressHost *e)
 | 
			
		||||
static void pcie_host_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
 | 
			
		||||
    PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pcie_host_mmcfg_unmap(PCIExpressHost *e)
 | 
			
		||||
@@ -128,6 +128,7 @@ static const TypeInfo pcie_host_type_info = {
 | 
			
		||||
    .parent = TYPE_PCI_HOST_BRIDGE,
 | 
			
		||||
    .abstract = true,
 | 
			
		||||
    .instance_size = sizeof(PCIExpressHost),
 | 
			
		||||
    .instance_init = pcie_host_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void pcie_host_register_types(void)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										150
									
								
								hw/s390x/css.c
									
									
									
									
									
								
							
							
						
						
									
										150
									
								
								hw/s390x/css.c
									
									
									
									
									
								
							@@ -128,13 +128,11 @@ uint16_t css_build_subchannel_id(SubchDev *sch)
 | 
			
		||||
 | 
			
		||||
static void css_inject_io_interrupt(SubchDev *sch)
 | 
			
		||||
{
 | 
			
		||||
    S390CPU *cpu = s390_cpu_addr2state(0);
 | 
			
		||||
    uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
 | 
			
		||||
 | 
			
		||||
    trace_css_io_interrupt(sch->cssid, sch->ssid, sch->schid,
 | 
			
		||||
                           sch->curr_status.pmcw.intparm, isc, "");
 | 
			
		||||
    s390_io_interrupt(cpu,
 | 
			
		||||
                      css_build_subchannel_id(sch),
 | 
			
		||||
    s390_io_interrupt(css_build_subchannel_id(sch),
 | 
			
		||||
                      sch->schid,
 | 
			
		||||
                      sch->curr_status.pmcw.intparm,
 | 
			
		||||
                      isc << 27);
 | 
			
		||||
@@ -147,7 +145,6 @@ void css_conditional_io_interrupt(SubchDev *sch)
 | 
			
		||||
     * with alert status.
 | 
			
		||||
     */
 | 
			
		||||
    if (!(sch->curr_status.scsw.ctrl & SCSW_STCTL_STATUS_PEND)) {
 | 
			
		||||
        S390CPU *cpu = s390_cpu_addr2state(0);
 | 
			
		||||
        uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
 | 
			
		||||
 | 
			
		||||
        trace_css_io_interrupt(sch->cssid, sch->ssid, sch->schid,
 | 
			
		||||
@@ -157,8 +154,7 @@ void css_conditional_io_interrupt(SubchDev *sch)
 | 
			
		||||
        sch->curr_status.scsw.ctrl |=
 | 
			
		||||
            SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
 | 
			
		||||
        /* Inject an I/O interrupt. */
 | 
			
		||||
        s390_io_interrupt(cpu,
 | 
			
		||||
                          css_build_subchannel_id(sch),
 | 
			
		||||
        s390_io_interrupt(css_build_subchannel_id(sch),
 | 
			
		||||
                          sch->schid,
 | 
			
		||||
                          sch->curr_status.pmcw.intparm,
 | 
			
		||||
                          isc << 27);
 | 
			
		||||
@@ -167,11 +163,10 @@ void css_conditional_io_interrupt(SubchDev *sch)
 | 
			
		||||
 | 
			
		||||
void css_adapter_interrupt(uint8_t isc)
 | 
			
		||||
{
 | 
			
		||||
    S390CPU *cpu = s390_cpu_addr2state(0);
 | 
			
		||||
    uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI;
 | 
			
		||||
 | 
			
		||||
    trace_css_adapter_interrupt(isc);
 | 
			
		||||
    s390_io_interrupt(cpu, 0, 0, 0, io_int_word);
 | 
			
		||||
    s390_io_interrupt(0, 0, 0, io_int_word);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sch_handle_clear_func(SubchDev *sch)
 | 
			
		||||
@@ -779,9 +774,11 @@ out:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void copy_irb_to_guest(IRB *dest, const IRB *src)
 | 
			
		||||
static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    uint16_t stctl = src->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
 | 
			
		||||
    uint16_t actl = src->scsw.ctrl & SCSW_CTRL_MASK_ACTL;
 | 
			
		||||
 | 
			
		||||
    copy_scsw_to_guest(&dest->scsw, &src->scsw);
 | 
			
		||||
 | 
			
		||||
@@ -791,8 +788,22 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src)
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
 | 
			
		||||
        dest->ecw[i] = cpu_to_be32(src->ecw[i]);
 | 
			
		||||
    }
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
 | 
			
		||||
        dest->emw[i] = cpu_to_be32(src->emw[i]);
 | 
			
		||||
    /* extended measurements enabled? */
 | 
			
		||||
    if ((src->scsw.flags & SCSW_FLAGS_MASK_ESWF) ||
 | 
			
		||||
        !(pmcw->flags & PMCW_FLAGS_MASK_TF) ||
 | 
			
		||||
        !(pmcw->chars & PMCW_CHARS_MASK_XMWME)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    /* extended measurements pending? */
 | 
			
		||||
    if (!(stctl & SCSW_STCTL_STATUS_PEND)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if ((stctl & SCSW_STCTL_PRIMARY) ||
 | 
			
		||||
        (stctl == SCSW_STCTL_SECONDARY) ||
 | 
			
		||||
        ((stctl & SCSW_STCTL_INTERMEDIATE) && (actl & SCSW_ACTL_SUSP))) {
 | 
			
		||||
        for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
 | 
			
		||||
            dest->emw[i] = cpu_to_be32(src->emw[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -838,7 +849,7 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /* Store the irb to the guest. */
 | 
			
		||||
    copy_irb_to_guest(target_irb, &irb);
 | 
			
		||||
    copy_irb_to_guest(target_irb, &irb, p);
 | 
			
		||||
 | 
			
		||||
    /* Clear conditions on subchannel, if applicable. */
 | 
			
		||||
    if (stctl & SCSW_STCTL_STATUS_PEND) {
 | 
			
		||||
@@ -1215,11 +1226,9 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
 | 
			
		||||
    QTAILQ_INSERT_TAIL(&channel_subsys->pending_crws, crw_cont, sibling);
 | 
			
		||||
 | 
			
		||||
    if (channel_subsys->do_crw_mchk) {
 | 
			
		||||
        S390CPU *cpu = s390_cpu_addr2state(0);
 | 
			
		||||
 | 
			
		||||
        channel_subsys->do_crw_mchk = false;
 | 
			
		||||
        /* Inject crw pending machine check. */
 | 
			
		||||
        s390_crw_mchk(cpu);
 | 
			
		||||
        s390_crw_mchk();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1277,6 +1286,117 @@ int css_enable_mss(void)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void subch_device_save(SubchDev *s, QEMUFile *f)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    qemu_put_byte(f, s->cssid);
 | 
			
		||||
    qemu_put_byte(f, s->ssid);
 | 
			
		||||
    qemu_put_be16(f, s->schid);
 | 
			
		||||
    qemu_put_be16(f, s->devno);
 | 
			
		||||
    qemu_put_byte(f, s->thinint_active);
 | 
			
		||||
    /* SCHIB */
 | 
			
		||||
    /*     PMCW */
 | 
			
		||||
    qemu_put_be32(f, s->curr_status.pmcw.intparm);
 | 
			
		||||
    qemu_put_be16(f, s->curr_status.pmcw.flags);
 | 
			
		||||
    qemu_put_be16(f, s->curr_status.pmcw.devno);
 | 
			
		||||
    qemu_put_byte(f, s->curr_status.pmcw.lpm);
 | 
			
		||||
    qemu_put_byte(f, s->curr_status.pmcw.pnom);
 | 
			
		||||
    qemu_put_byte(f, s->curr_status.pmcw.lpum);
 | 
			
		||||
    qemu_put_byte(f, s->curr_status.pmcw.pim);
 | 
			
		||||
    qemu_put_be16(f, s->curr_status.pmcw.mbi);
 | 
			
		||||
    qemu_put_byte(f, s->curr_status.pmcw.pom);
 | 
			
		||||
    qemu_put_byte(f, s->curr_status.pmcw.pam);
 | 
			
		||||
    qemu_put_buffer(f, s->curr_status.pmcw.chpid, 8);
 | 
			
		||||
    qemu_put_be32(f, s->curr_status.pmcw.chars);
 | 
			
		||||
    /*     SCSW */
 | 
			
		||||
    qemu_put_be16(f, s->curr_status.scsw.flags);
 | 
			
		||||
    qemu_put_be16(f, s->curr_status.scsw.ctrl);
 | 
			
		||||
    qemu_put_be32(f, s->curr_status.scsw.cpa);
 | 
			
		||||
    qemu_put_byte(f, s->curr_status.scsw.dstat);
 | 
			
		||||
    qemu_put_byte(f, s->curr_status.scsw.cstat);
 | 
			
		||||
    qemu_put_be16(f, s->curr_status.scsw.count);
 | 
			
		||||
    qemu_put_be64(f, s->curr_status.mba);
 | 
			
		||||
    qemu_put_buffer(f, s->curr_status.mda, 4);
 | 
			
		||||
    /* end SCHIB */
 | 
			
		||||
    qemu_put_buffer(f, s->sense_data, 32);
 | 
			
		||||
    qemu_put_be64(f, s->channel_prog);
 | 
			
		||||
    /* last cmd */
 | 
			
		||||
    qemu_put_byte(f, s->last_cmd.cmd_code);
 | 
			
		||||
    qemu_put_byte(f, s->last_cmd.flags);
 | 
			
		||||
    qemu_put_be16(f, s->last_cmd.count);
 | 
			
		||||
    qemu_put_be32(f, s->last_cmd.cda);
 | 
			
		||||
    qemu_put_byte(f, s->last_cmd_valid);
 | 
			
		||||
    qemu_put_byte(f, s->id.reserved);
 | 
			
		||||
    qemu_put_be16(f, s->id.cu_type);
 | 
			
		||||
    qemu_put_byte(f, s->id.cu_model);
 | 
			
		||||
    qemu_put_be16(f, s->id.dev_type);
 | 
			
		||||
    qemu_put_byte(f, s->id.dev_model);
 | 
			
		||||
    qemu_put_byte(f, s->id.unused);
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(s->id.ciw); i++) {
 | 
			
		||||
        qemu_put_byte(f, s->id.ciw[i].type);
 | 
			
		||||
        qemu_put_byte(f, s->id.ciw[i].command);
 | 
			
		||||
        qemu_put_be16(f, s->id.ciw[i].count);
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int subch_device_load(SubchDev *s, QEMUFile *f)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    s->cssid = qemu_get_byte(f);
 | 
			
		||||
    s->ssid = qemu_get_byte(f);
 | 
			
		||||
    s->schid = qemu_get_be16(f);
 | 
			
		||||
    s->devno = qemu_get_be16(f);
 | 
			
		||||
    s->thinint_active = qemu_get_byte(f);
 | 
			
		||||
    /* SCHIB */
 | 
			
		||||
    /*     PMCW */
 | 
			
		||||
    s->curr_status.pmcw.intparm = qemu_get_be32(f);
 | 
			
		||||
    s->curr_status.pmcw.flags = qemu_get_be16(f);
 | 
			
		||||
    s->curr_status.pmcw.devno = qemu_get_be16(f);
 | 
			
		||||
    s->curr_status.pmcw.lpm = qemu_get_byte(f);
 | 
			
		||||
    s->curr_status.pmcw.pnom  = qemu_get_byte(f);
 | 
			
		||||
    s->curr_status.pmcw.lpum = qemu_get_byte(f);
 | 
			
		||||
    s->curr_status.pmcw.pim = qemu_get_byte(f);
 | 
			
		||||
    s->curr_status.pmcw.mbi = qemu_get_be16(f);
 | 
			
		||||
    s->curr_status.pmcw.pom = qemu_get_byte(f);
 | 
			
		||||
    s->curr_status.pmcw.pam = qemu_get_byte(f);
 | 
			
		||||
    qemu_get_buffer(f, s->curr_status.pmcw.chpid, 8);
 | 
			
		||||
    s->curr_status.pmcw.chars = qemu_get_be32(f);
 | 
			
		||||
    /*     SCSW */
 | 
			
		||||
    s->curr_status.scsw.flags = qemu_get_be16(f);
 | 
			
		||||
    s->curr_status.scsw.ctrl = qemu_get_be16(f);
 | 
			
		||||
    s->curr_status.scsw.cpa = qemu_get_be32(f);
 | 
			
		||||
    s->curr_status.scsw.dstat = qemu_get_byte(f);
 | 
			
		||||
    s->curr_status.scsw.cstat = qemu_get_byte(f);
 | 
			
		||||
    s->curr_status.scsw.count = qemu_get_be16(f);
 | 
			
		||||
    s->curr_status.mba = qemu_get_be64(f);
 | 
			
		||||
    qemu_get_buffer(f, s->curr_status.mda, 4);
 | 
			
		||||
    /* end SCHIB */
 | 
			
		||||
    qemu_get_buffer(f, s->sense_data, 32);
 | 
			
		||||
    s->channel_prog = qemu_get_be64(f);
 | 
			
		||||
    /* last cmd */
 | 
			
		||||
    s->last_cmd.cmd_code = qemu_get_byte(f);
 | 
			
		||||
    s->last_cmd.flags = qemu_get_byte(f);
 | 
			
		||||
    s->last_cmd.count = qemu_get_be16(f);
 | 
			
		||||
    s->last_cmd.cda = qemu_get_be32(f);
 | 
			
		||||
    s->last_cmd_valid = qemu_get_byte(f);
 | 
			
		||||
    s->id.reserved = qemu_get_byte(f);
 | 
			
		||||
    s->id.cu_type = qemu_get_be16(f);
 | 
			
		||||
    s->id.cu_model = qemu_get_byte(f);
 | 
			
		||||
    s->id.dev_type = qemu_get_be16(f);
 | 
			
		||||
    s->id.dev_model = qemu_get_byte(f);
 | 
			
		||||
    s->id.unused = qemu_get_byte(f);
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(s->id.ciw); i++) {
 | 
			
		||||
        s->id.ciw[i].type = qemu_get_byte(f);
 | 
			
		||||
        s->id.ciw[i].command = qemu_get_byte(f);
 | 
			
		||||
        s->id.ciw[i].count = qemu_get_be16(f);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void css_init(void)
 | 
			
		||||
{
 | 
			
		||||
    channel_subsys = g_malloc0(sizeof(*channel_subsys));
 | 
			
		||||
 
 | 
			
		||||
@@ -85,6 +85,8 @@ struct SubchDev {
 | 
			
		||||
 | 
			
		||||
typedef SubchDev *(*css_subch_cb_func)(uint8_t m, uint8_t cssid, uint8_t ssid,
 | 
			
		||||
                                       uint16_t schid);
 | 
			
		||||
void subch_device_save(SubchDev *s, QEMUFile *f);
 | 
			
		||||
int subch_device_load(SubchDev *s, QEMUFile *f);
 | 
			
		||||
int css_create_css_image(uint8_t cssid, bool default_image);
 | 
			
		||||
bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno);
 | 
			
		||||
void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
 | 
			
		||||
 
 | 
			
		||||
@@ -45,8 +45,6 @@
 | 
			
		||||
    do { } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define VIRTIO_EXT_CODE   0x2603
 | 
			
		||||
 | 
			
		||||
static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size,
 | 
			
		||||
                                VirtIOS390Device *dev);
 | 
			
		||||
 | 
			
		||||
@@ -113,15 +111,6 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
 | 
			
		||||
    return bus;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token)
 | 
			
		||||
{
 | 
			
		||||
    if (kvm_enabled()) {
 | 
			
		||||
        kvm_s390_virtio_irq(cpu, config_change, token);
 | 
			
		||||
    } else {
 | 
			
		||||
        cpu_inject_ext(cpu, VIRTIO_EXT_CODE, config_change, token);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOS390Bus *bus;
 | 
			
		||||
@@ -144,8 +133,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
 | 
			
		||||
    s390_virtio_device_sync(dev);
 | 
			
		||||
    s390_virtio_reset_idx(dev);
 | 
			
		||||
    if (dev->qdev.hotplugged) {
 | 
			
		||||
        S390CPU *cpu = s390_cpu_addr2state(0);
 | 
			
		||||
        s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
 | 
			
		||||
        s390_virtio_irq(VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
@@ -489,9 +477,8 @@ static void virtio_s390_notify(DeviceState *d, uint16_t vector)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOS390Device *dev = to_virtio_s390_device_fast(d);
 | 
			
		||||
    uint64_t token = s390_virtio_device_vq_token(dev, vector);
 | 
			
		||||
    S390CPU *cpu = s390_cpu_addr2state(0);
 | 
			
		||||
 | 
			
		||||
    s390_virtio_irq(cpu, 0, token);
 | 
			
		||||
    s390_virtio_irq(0, token);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned virtio_s390_get_features(DeviceState *d)
 | 
			
		||||
 
 | 
			
		||||
@@ -1275,6 +1275,97 @@ irqroute_error:
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_ccw_save_queue(DeviceState *d, int n, QEMUFile *f)
 | 
			
		||||
{
 | 
			
		||||
    VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
 | 
			
		||||
    VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
 | 
			
		||||
 | 
			
		||||
    qemu_put_be16(f, virtio_queue_vector(vdev, n));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f)
 | 
			
		||||
{
 | 
			
		||||
    VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
 | 
			
		||||
    VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
 | 
			
		||||
    uint16_t vector;
 | 
			
		||||
 | 
			
		||||
    qemu_get_be16s(f, &vector);
 | 
			
		||||
    virtio_queue_set_vector(vdev, n , vector);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
 | 
			
		||||
{
 | 
			
		||||
    VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
 | 
			
		||||
    SubchDev *s = dev->sch;
 | 
			
		||||
 | 
			
		||||
    subch_device_save(s, f);
 | 
			
		||||
    if (dev->indicators != NULL) {
 | 
			
		||||
        qemu_put_be32(f, dev->indicators->len);
 | 
			
		||||
        qemu_put_be64(f, dev->indicators->addr);
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_put_be32(f, 0);
 | 
			
		||||
        qemu_put_be64(f, 0UL);
 | 
			
		||||
    }
 | 
			
		||||
    if (dev->indicators2 != NULL) {
 | 
			
		||||
        qemu_put_be32(f, dev->indicators2->len);
 | 
			
		||||
        qemu_put_be64(f, dev->indicators2->addr);
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_put_be32(f, 0);
 | 
			
		||||
        qemu_put_be64(f, 0UL);
 | 
			
		||||
    }
 | 
			
		||||
    if (dev->summary_indicator != NULL) {
 | 
			
		||||
        qemu_put_be32(f, dev->summary_indicator->len);
 | 
			
		||||
        qemu_put_be64(f, dev->summary_indicator->addr);
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_put_be32(f, 0);
 | 
			
		||||
        qemu_put_be64(f, 0UL);
 | 
			
		||||
    }
 | 
			
		||||
    qemu_put_be64(f, dev->routes.adapter.ind_offset);
 | 
			
		||||
    qemu_put_byte(f, dev->thinint_isc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
 | 
			
		||||
{
 | 
			
		||||
    VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
 | 
			
		||||
    SubchDev *s = dev->sch;
 | 
			
		||||
    int len;
 | 
			
		||||
 | 
			
		||||
    s->driver_data = dev;
 | 
			
		||||
    subch_device_load(s, f);
 | 
			
		||||
    len = qemu_get_be32(f);
 | 
			
		||||
    if (len != 0) {
 | 
			
		||||
        dev->indicators = get_indicator(qemu_get_be64(f), len);
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_get_be64(f);
 | 
			
		||||
        dev->indicators = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    len = qemu_get_be32(f);
 | 
			
		||||
    if (len != 0) {
 | 
			
		||||
        dev->indicators2 = get_indicator(qemu_get_be64(f), len);
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_get_be64(f);
 | 
			
		||||
        dev->indicators2 = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    len = qemu_get_be32(f);
 | 
			
		||||
    if (len != 0) {
 | 
			
		||||
        dev->summary_indicator = get_indicator(qemu_get_be64(f), len);
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_get_be64(f);
 | 
			
		||||
        dev->summary_indicator = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    dev->routes.adapter.ind_offset = qemu_get_be64(f);
 | 
			
		||||
    dev->thinint_isc = qemu_get_byte(f);
 | 
			
		||||
    if (s->thinint_active) {
 | 
			
		||||
        return css_register_io_adapter(CSS_IO_ADAPTER_VIRTIO,
 | 
			
		||||
                                       dev->thinint_isc, true, false,
 | 
			
		||||
                                       &dev->routes.adapter.adapter_id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**************** Virtio-ccw Bus Device Descriptions *******************/
 | 
			
		||||
 | 
			
		||||
static Property virtio_ccw_net_properties[] = {
 | 
			
		||||
@@ -1597,6 +1688,10 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
    k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
 | 
			
		||||
    k->set_host_notifier = virtio_ccw_set_host_notifier;
 | 
			
		||||
    k->set_guest_notifiers = virtio_ccw_set_guest_notifiers;
 | 
			
		||||
    k->save_queue = virtio_ccw_save_queue;
 | 
			
		||||
    k->load_queue = virtio_ccw_load_queue;
 | 
			
		||||
    k->save_config = virtio_ccw_save_config;
 | 
			
		||||
    k->load_config = virtio_ccw_load_config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo virtio_ccw_bus_info = {
 | 
			
		||||
 
 | 
			
		||||
@@ -164,8 +164,8 @@ static void vhost_scsi_set_config(VirtIODevice *vdev,
 | 
			
		||||
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
 | 
			
		||||
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
 | 
			
		||||
 | 
			
		||||
    if ((uint32_t) ldl_raw(&scsiconf->sense_size) != vs->sense_size ||
 | 
			
		||||
        (uint32_t) ldl_raw(&scsiconf->cdb_size) != vs->cdb_size) {
 | 
			
		||||
    if ((uint32_t) ldl_p(&scsiconf->sense_size) != vs->sense_size ||
 | 
			
		||||
        (uint32_t) ldl_p(&scsiconf->cdb_size) != vs->cdb_size) {
 | 
			
		||||
        error_report("vhost-scsi does not support changing the sense data and CDB sizes");
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -425,16 +425,16 @@ static void virtio_scsi_get_config(VirtIODevice *vdev,
 | 
			
		||||
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
 | 
			
		||||
    VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(vdev);
 | 
			
		||||
 | 
			
		||||
    stl_raw(&scsiconf->num_queues, s->conf.num_queues);
 | 
			
		||||
    stl_raw(&scsiconf->seg_max, 128 - 2);
 | 
			
		||||
    stl_raw(&scsiconf->max_sectors, s->conf.max_sectors);
 | 
			
		||||
    stl_raw(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
 | 
			
		||||
    stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
 | 
			
		||||
    stl_raw(&scsiconf->sense_size, s->sense_size);
 | 
			
		||||
    stl_raw(&scsiconf->cdb_size, s->cdb_size);
 | 
			
		||||
    stw_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
 | 
			
		||||
    stw_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
 | 
			
		||||
    stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
 | 
			
		||||
    stl_p(&scsiconf->num_queues, s->conf.num_queues);
 | 
			
		||||
    stl_p(&scsiconf->seg_max, 128 - 2);
 | 
			
		||||
    stl_p(&scsiconf->max_sectors, s->conf.max_sectors);
 | 
			
		||||
    stl_p(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
 | 
			
		||||
    stl_p(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
 | 
			
		||||
    stl_p(&scsiconf->sense_size, s->sense_size);
 | 
			
		||||
    stl_p(&scsiconf->cdb_size, s->cdb_size);
 | 
			
		||||
    stw_p(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
 | 
			
		||||
    stw_p(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
 | 
			
		||||
    stl_p(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_scsi_set_config(VirtIODevice *vdev,
 | 
			
		||||
@@ -443,14 +443,14 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
 | 
			
		||||
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
 | 
			
		||||
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
 | 
			
		||||
 | 
			
		||||
    if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
 | 
			
		||||
        (uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
 | 
			
		||||
    if ((uint32_t) ldl_p(&scsiconf->sense_size) >= 65536 ||
 | 
			
		||||
        (uint32_t) ldl_p(&scsiconf->cdb_size) >= 256) {
 | 
			
		||||
        error_report("bad data written to virtio-scsi configuration space");
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vs->sense_size = ldl_raw(&scsiconf->sense_size);
 | 
			
		||||
    vs->cdb_size = ldl_raw(&scsiconf->cdb_size);
 | 
			
		||||
    vs->sense_size = ldl_p(&scsiconf->sense_size);
 | 
			
		||||
    vs->cdb_size = ldl_p(&scsiconf->cdb_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								hw/sd/sd.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								hw/sd/sd.c
									
									
									
									
									
								
							@@ -151,17 +151,6 @@ static const sd_cmd_type_t sd_cmd_type[64] = {
 | 
			
		||||
    sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const sd_cmd_type_t sd_acmd_type[64] = {
 | 
			
		||||
    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac,   sd_none,
 | 
			
		||||
    sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none,
 | 
			
		||||
    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_ac,
 | 
			
		||||
    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
 | 
			
		||||
    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
 | 
			
		||||
    sd_none, sd_bcr,  sd_ac,   sd_none, sd_none, sd_none, sd_none, sd_none,
 | 
			
		||||
    sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none, sd_none, sd_none,
 | 
			
		||||
    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const int sd_cmd_class[64] = {
 | 
			
		||||
    0,  0,  0,  0,  0,  9, 10,  0,  0,  0,  0,  1,  0,  0,  0,  0,
 | 
			
		||||
    2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,
 | 
			
		||||
 
 | 
			
		||||
@@ -543,14 +543,14 @@ static void tcx_init(hwaddr addr, int vram_size, int width,
 | 
			
		||||
    s = SYS_BUS_DEVICE(dev);
 | 
			
		||||
    /* FCode ROM */
 | 
			
		||||
    sysbus_mmio_map(s, 0, addr);
 | 
			
		||||
    /* 8-bit plane */
 | 
			
		||||
    sysbus_mmio_map(s, 1, addr + 0x00800000ULL);
 | 
			
		||||
    /* DAC */
 | 
			
		||||
    sysbus_mmio_map(s, 2, addr + 0x00200000ULL);
 | 
			
		||||
    sysbus_mmio_map(s, 1, addr + 0x00200000ULL);
 | 
			
		||||
    /* TEC (dummy) */
 | 
			
		||||
    sysbus_mmio_map(s, 3, addr + 0x00700000ULL);
 | 
			
		||||
    sysbus_mmio_map(s, 2, addr + 0x00700000ULL);
 | 
			
		||||
    /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
 | 
			
		||||
    sysbus_mmio_map(s, 4, addr + 0x00301000ULL);
 | 
			
		||||
    sysbus_mmio_map(s, 3, addr + 0x00301000ULL);
 | 
			
		||||
    /* 8-bit plane */
 | 
			
		||||
    sysbus_mmio_map(s, 4, addr + 0x00800000ULL);
 | 
			
		||||
    if (depth == 24) {
 | 
			
		||||
        /* 24-bit plane */
 | 
			
		||||
        sysbus_mmio_map(s, 5, addr + 0x02000000ULL);
 | 
			
		||||
 
 | 
			
		||||
@@ -204,14 +204,11 @@ static void timer_hit(void *opaque)
 | 
			
		||||
    timer_update_irq(t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int xilinx_timer_init(SysBusDevice *dev)
 | 
			
		||||
static void xilinx_timer_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    struct timerblock *t = XILINX_TIMER(dev);
 | 
			
		||||
    unsigned int i;
 | 
			
		||||
 | 
			
		||||
    /* All timers share a single irq line.  */
 | 
			
		||||
    sysbus_init_irq(dev, &t->irq);
 | 
			
		||||
 | 
			
		||||
    /* Init all the ptimers.  */
 | 
			
		||||
    t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t));
 | 
			
		||||
    for (i = 0; i < num_timers(t); i++) {
 | 
			
		||||
@@ -226,8 +223,15 @@ static int xilinx_timer_init(SysBusDevice *dev)
 | 
			
		||||
 | 
			
		||||
    memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
 | 
			
		||||
                          R_MAX * 4 * num_timers(t));
 | 
			
		||||
    sysbus_init_mmio(dev, &t->mmio);
 | 
			
		||||
    return 0;
 | 
			
		||||
    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &t->mmio);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void xilinx_timer_init(Object *obj)
 | 
			
		||||
{
 | 
			
		||||
    struct timerblock *t = XILINX_TIMER(obj);
 | 
			
		||||
 | 
			
		||||
    /* All timers share a single irq line.  */
 | 
			
		||||
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &t->irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property xilinx_timer_properties[] = {
 | 
			
		||||
@@ -240,9 +244,8 @@ static Property xilinx_timer_properties[] = {
 | 
			
		||||
static void xilinx_timer_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    k->init = xilinx_timer_init;
 | 
			
		||||
    dc->realize = xilinx_timer_realize;
 | 
			
		||||
    dc->props = xilinx_timer_properties;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -250,6 +253,7 @@ static const TypeInfo xilinx_timer_info = {
 | 
			
		||||
    .name          = TYPE_XILINX_TIMER,
 | 
			
		||||
    .parent        = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(struct timerblock),
 | 
			
		||||
    .instance_init = xilinx_timer_init,
 | 
			
		||||
    .class_init    = xilinx_timer_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,6 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
 | 
			
		||||
 | 
			
		||||
    for (;from < to; ++from) {
 | 
			
		||||
        vhost_log_chunk_t log;
 | 
			
		||||
        int bit;
 | 
			
		||||
        /* We first check with non-atomic: much cheaper,
 | 
			
		||||
         * and we expect non-dirty to be the common case. */
 | 
			
		||||
        if (!*from) {
 | 
			
		||||
@@ -51,12 +50,11 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
 | 
			
		||||
        /* Data must be read atomically. We don't really need barrier semantics
 | 
			
		||||
         * but it's easier to use atomic_* than roll our own. */
 | 
			
		||||
        log = atomic_xchg(from, 0);
 | 
			
		||||
        while ((bit = sizeof(log) > sizeof(int) ?
 | 
			
		||||
                ffsll(log) : ffs(log))) {
 | 
			
		||||
        while (log) {
 | 
			
		||||
            int bit = ctzl(log);
 | 
			
		||||
            hwaddr page_addr;
 | 
			
		||||
            hwaddr section_offset;
 | 
			
		||||
            hwaddr mr_offset;
 | 
			
		||||
            bit -= 1;
 | 
			
		||||
            page_addr = addr + bit * VHOST_LOG_PAGE;
 | 
			
		||||
            section_offset = page_addr - section->offset_within_address_space;
 | 
			
		||||
            mr_offset = section_offset + section->offset_within_region;
 | 
			
		||||
 
 | 
			
		||||
@@ -112,11 +112,6 @@ static void balloon_stats_get_all(Object *obj, struct Visitor *v,
 | 
			
		||||
    VirtIOBalloon *s = opaque;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (!s->stats_last_update) {
 | 
			
		||||
        error_setg(errp, "guest hasn't updated any stats yet");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    visit_start_struct(v, NULL, "guest-stats", name, 0, &err);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        goto out;
 | 
			
		||||
@@ -378,6 +373,8 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
 | 
			
		||||
    s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
 | 
			
		||||
 | 
			
		||||
    reset_stats(s);
 | 
			
		||||
 | 
			
		||||
    register_savevm(dev, "virtio-balloon", -1, 1,
 | 
			
		||||
                    virtio_balloon_save, virtio_balloon_load, s);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -440,7 +440,7 @@ void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
 | 
			
		||||
        len = sg[i].iov_len;
 | 
			
		||||
        sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
 | 
			
		||||
        if (sg[i].iov_base == NULL || len != sg[i].iov_len) {
 | 
			
		||||
            error_report("virtio: trying to map MMIO memory");
 | 
			
		||||
            error_report("virtio: error trying to map MMIO memory");
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -481,15 +481,6 @@ void bdrv_op_block_all(BlockDriverState *bs, Error *reason);
 | 
			
		||||
void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason);
 | 
			
		||||
bool bdrv_op_blocker_is_empty(BlockDriverState *bs);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_LINUX_AIO
 | 
			
		||||
int raw_get_aio_fd(BlockDriverState *bs);
 | 
			
		||||
#else
 | 
			
		||||
static inline int raw_get_aio_fd(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    return -ENOTSUP;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum BlockAcctType {
 | 
			
		||||
    BDRV_ACCT_READ,
 | 
			
		||||
    BDRV_ACCT_WRITE,
 | 
			
		||||
@@ -574,4 +565,22 @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag);
 | 
			
		||||
int bdrv_debug_resume(BlockDriverState *bs, const char *tag);
 | 
			
		||||
bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * bdrv_get_aio_context:
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: the currently bound #AioContext
 | 
			
		||||
 */
 | 
			
		||||
AioContext *bdrv_get_aio_context(BlockDriverState *bs);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * bdrv_set_aio_context:
 | 
			
		||||
 *
 | 
			
		||||
 * Changes the #AioContext used for fd handlers, timers, and BHs by this
 | 
			
		||||
 * BlockDriverState and all its children.
 | 
			
		||||
 *
 | 
			
		||||
 * This function must be called from the old #AioContext or with a lock held so
 | 
			
		||||
 * the old #AioContext is not executing.
 | 
			
		||||
 */
 | 
			
		||||
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -247,6 +247,19 @@ struct BlockDriver {
 | 
			
		||||
     */
 | 
			
		||||
    int (*bdrv_has_zero_init)(BlockDriverState *bs);
 | 
			
		||||
 | 
			
		||||
    /* Remove fd handlers, timers, and other event loop callbacks so the event
 | 
			
		||||
     * loop is no longer in use.  Called with no in-flight requests and in
 | 
			
		||||
     * depth-first traversal order with parents before child nodes.
 | 
			
		||||
     */
 | 
			
		||||
    void (*bdrv_detach_aio_context)(BlockDriverState *bs);
 | 
			
		||||
 | 
			
		||||
    /* Add fd handlers, timers, and other event loop callbacks so I/O requests
 | 
			
		||||
     * can be processed again.  Called with no in-flight requests and in
 | 
			
		||||
     * depth-first traversal order with child nodes before parent nodes.
 | 
			
		||||
     */
 | 
			
		||||
    void (*bdrv_attach_aio_context)(BlockDriverState *bs,
 | 
			
		||||
                                    AioContext *new_context);
 | 
			
		||||
 | 
			
		||||
    QLIST_ENTRY(BlockDriver) list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -297,6 +310,8 @@ struct BlockDriverState {
 | 
			
		||||
    const BlockDevOps *dev_ops;
 | 
			
		||||
    void *dev_opaque;
 | 
			
		||||
 | 
			
		||||
    AioContext *aio_context; /* event loop used for fd handlers, timers, etc */
 | 
			
		||||
 | 
			
		||||
    char filename[1024];
 | 
			
		||||
    char backing_file[1024]; /* if non zero, the image is a diff of
 | 
			
		||||
                                this file image */
 | 
			
		||||
@@ -390,11 +405,25 @@ void bdrv_add_before_write_notifier(BlockDriverState *bs,
 | 
			
		||||
                                    NotifierWithReturn *notifier);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * bdrv_get_aio_context:
 | 
			
		||||
 * bdrv_detach_aio_context:
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: the currently bound #AioContext
 | 
			
		||||
 * May be called from .bdrv_detach_aio_context() to detach children from the
 | 
			
		||||
 * current #AioContext.  This is only needed by block drivers that manage their
 | 
			
		||||
 * own children.  Both ->file and ->backing_hd are automatically handled and
 | 
			
		||||
 * block drivers should not call this function on them explicitly.
 | 
			
		||||
 */
 | 
			
		||||
AioContext *bdrv_get_aio_context(BlockDriverState *bs);
 | 
			
		||||
void bdrv_detach_aio_context(BlockDriverState *bs);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * bdrv_attach_aio_context:
 | 
			
		||||
 *
 | 
			
		||||
 * May be called from .bdrv_attach_aio_context() to attach children to the new
 | 
			
		||||
 * #AioContext.  This is only needed by block drivers that manage their own
 | 
			
		||||
 * children.  Both ->file and ->backing_hd are automatically handled and block
 | 
			
		||||
 * drivers should not call this function on them explicitly.
 | 
			
		||||
 */
 | 
			
		||||
void bdrv_attach_aio_context(BlockDriverState *bs,
 | 
			
		||||
                             AioContext *new_context);
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
int is_windows_drive(const char *filename);
 | 
			
		||||
 
 | 
			
		||||
@@ -198,127 +198,8 @@ extern unsigned long reserved_va;
 | 
			
		||||
#define RESERVED_VA 0ul
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
 | 
			
		||||
#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
 | 
			
		||||
 | 
			
		||||
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
 | 
			
		||||
#define h2g_valid(x) 1
 | 
			
		||||
#else
 | 
			
		||||
#define h2g_valid(x) ({ \
 | 
			
		||||
    unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
 | 
			
		||||
    (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
 | 
			
		||||
    (!RESERVED_VA || (__guest < RESERVED_VA)); \
 | 
			
		||||
})
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define h2g_nocheck(x) ({ \
 | 
			
		||||
    unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
 | 
			
		||||
    (abi_ulong)__ret; \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define h2g(x) ({ \
 | 
			
		||||
    /* Check if given address fits target address space */ \
 | 
			
		||||
    assert(h2g_valid(x)); \
 | 
			
		||||
    h2g_nocheck(x); \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define saddr(x) g2h(x)
 | 
			
		||||
#define laddr(x) g2h(x)
 | 
			
		||||
 | 
			
		||||
#else /* !CONFIG_USER_ONLY */
 | 
			
		||||
/* NOTE: we use double casts if pointers and target_ulong have
 | 
			
		||||
   different sizes */
 | 
			
		||||
#define saddr(x) (uint8_t *)(intptr_t)(x)
 | 
			
		||||
#define laddr(x) (uint8_t *)(intptr_t)(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define ldub_raw(p) ldub_p(laddr((p)))
 | 
			
		||||
#define ldsb_raw(p) ldsb_p(laddr((p)))
 | 
			
		||||
#define lduw_raw(p) lduw_p(laddr((p)))
 | 
			
		||||
#define ldsw_raw(p) ldsw_p(laddr((p)))
 | 
			
		||||
#define ldl_raw(p) ldl_p(laddr((p)))
 | 
			
		||||
#define ldq_raw(p) ldq_p(laddr((p)))
 | 
			
		||||
#define ldfl_raw(p) ldfl_p(laddr((p)))
 | 
			
		||||
#define ldfq_raw(p) ldfq_p(laddr((p)))
 | 
			
		||||
#define stb_raw(p, v) stb_p(saddr((p)), v)
 | 
			
		||||
#define stw_raw(p, v) stw_p(saddr((p)), v)
 | 
			
		||||
#define stl_raw(p, v) stl_p(saddr((p)), v)
 | 
			
		||||
#define stq_raw(p, v) stq_p(saddr((p)), v)
 | 
			
		||||
#define stfl_raw(p, v) stfl_p(saddr((p)), v)
 | 
			
		||||
#define stfq_raw(p, v) stfq_p(saddr((p)), v)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_USER_ONLY)
 | 
			
		||||
 | 
			
		||||
/* if user mode, no other memory access functions */
 | 
			
		||||
#define ldub(p) ldub_raw(p)
 | 
			
		||||
#define ldsb(p) ldsb_raw(p)
 | 
			
		||||
#define lduw(p) lduw_raw(p)
 | 
			
		||||
#define ldsw(p) ldsw_raw(p)
 | 
			
		||||
#define ldl(p) ldl_raw(p)
 | 
			
		||||
#define ldq(p) ldq_raw(p)
 | 
			
		||||
#define ldfl(p) ldfl_raw(p)
 | 
			
		||||
#define ldfq(p) ldfq_raw(p)
 | 
			
		||||
#define stb(p, v) stb_raw(p, v)
 | 
			
		||||
#define stw(p, v) stw_raw(p, v)
 | 
			
		||||
#define stl(p, v) stl_raw(p, v)
 | 
			
		||||
#define stq(p, v) stq_raw(p, v)
 | 
			
		||||
#define stfl(p, v) stfl_raw(p, v)
 | 
			
		||||
#define stfq(p, v) stfq_raw(p, v)
 | 
			
		||||
 | 
			
		||||
#define cpu_ldub_code(env1, p) ldub_raw(p)
 | 
			
		||||
#define cpu_ldsb_code(env1, p) ldsb_raw(p)
 | 
			
		||||
#define cpu_lduw_code(env1, p) lduw_raw(p)
 | 
			
		||||
#define cpu_ldsw_code(env1, p) ldsw_raw(p)
 | 
			
		||||
#define cpu_ldl_code(env1, p) ldl_raw(p)
 | 
			
		||||
#define cpu_ldq_code(env1, p) ldq_raw(p)
 | 
			
		||||
 | 
			
		||||
#define cpu_ldub_data(env, addr) ldub_raw(addr)
 | 
			
		||||
#define cpu_lduw_data(env, addr) lduw_raw(addr)
 | 
			
		||||
#define cpu_ldsw_data(env, addr) ldsw_raw(addr)
 | 
			
		||||
#define cpu_ldl_data(env, addr) ldl_raw(addr)
 | 
			
		||||
#define cpu_ldq_data(env, addr) ldq_raw(addr)
 | 
			
		||||
 | 
			
		||||
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
 | 
			
		||||
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
 | 
			
		||||
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
 | 
			
		||||
#define cpu_stq_data(env, addr, data) stq_raw(addr, data)
 | 
			
		||||
 | 
			
		||||
#define cpu_ldub_kernel(env, addr) ldub_raw(addr)
 | 
			
		||||
#define cpu_lduw_kernel(env, addr) lduw_raw(addr)
 | 
			
		||||
#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr)
 | 
			
		||||
#define cpu_ldl_kernel(env, addr) ldl_raw(addr)
 | 
			
		||||
#define cpu_ldq_kernel(env, addr) ldq_raw(addr)
 | 
			
		||||
 | 
			
		||||
#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data)
 | 
			
		||||
#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data)
 | 
			
		||||
#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data)
 | 
			
		||||
#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data)
 | 
			
		||||
 | 
			
		||||
#define ldub_kernel(p) ldub_raw(p)
 | 
			
		||||
#define ldsb_kernel(p) ldsb_raw(p)
 | 
			
		||||
#define lduw_kernel(p) lduw_raw(p)
 | 
			
		||||
#define ldsw_kernel(p) ldsw_raw(p)
 | 
			
		||||
#define ldl_kernel(p) ldl_raw(p)
 | 
			
		||||
#define ldq_kernel(p) ldq_raw(p)
 | 
			
		||||
#define ldfl_kernel(p) ldfl_raw(p)
 | 
			
		||||
#define ldfq_kernel(p) ldfq_raw(p)
 | 
			
		||||
#define stb_kernel(p, v) stb_raw(p, v)
 | 
			
		||||
#define stw_kernel(p, v) stw_raw(p, v)
 | 
			
		||||
#define stl_kernel(p, v) stl_raw(p, v)
 | 
			
		||||
#define stq_kernel(p, v) stq_raw(p, v)
 | 
			
		||||
#define stfl_kernel(p, v) stfl_raw(p, v)
 | 
			
		||||
#define stfq_kernel(p, vt) stfq_raw(p, v)
 | 
			
		||||
 | 
			
		||||
#define cpu_ldub_data(env, addr) ldub_raw(addr)
 | 
			
		||||
#define cpu_lduw_data(env, addr) lduw_raw(addr)
 | 
			
		||||
#define cpu_ldl_data(env, addr) ldl_raw(addr)
 | 
			
		||||
 | 
			
		||||
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
 | 
			
		||||
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
 | 
			
		||||
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
 | 
			
		||||
#endif /* defined(CONFIG_USER_ONLY) */
 | 
			
		||||
 | 
			
		||||
/* page related stuff */
 | 
			
		||||
 | 
			
		||||
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										400
									
								
								include/exec/cpu_ldst.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										400
									
								
								include/exec/cpu_ldst.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,400 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Software MMU support
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Generate inline load/store functions for all MMU modes (typically
 | 
			
		||||
 * at least _user and _kernel) as well as _data versions, for all data
 | 
			
		||||
 * sizes.
 | 
			
		||||
 *
 | 
			
		||||
 * Used by target op helpers.
 | 
			
		||||
 *
 | 
			
		||||
 * MMU mode suffixes are defined in target cpu.h.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef CPU_LDST_H
 | 
			
		||||
#define CPU_LDST_H
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_USER_ONLY)
 | 
			
		||||
/* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
 | 
			
		||||
#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
 | 
			
		||||
 | 
			
		||||
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
 | 
			
		||||
#define h2g_valid(x) 1
 | 
			
		||||
#else
 | 
			
		||||
#define h2g_valid(x) ({ \
 | 
			
		||||
    unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
 | 
			
		||||
    (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
 | 
			
		||||
    (!RESERVED_VA || (__guest < RESERVED_VA)); \
 | 
			
		||||
})
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define h2g_nocheck(x) ({ \
 | 
			
		||||
    unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
 | 
			
		||||
    (abi_ulong)__ret; \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define h2g(x) ({ \
 | 
			
		||||
    /* Check if given address fits target address space */ \
 | 
			
		||||
    assert(h2g_valid(x)); \
 | 
			
		||||
    h2g_nocheck(x); \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define saddr(x) g2h(x)
 | 
			
		||||
#define laddr(x) g2h(x)
 | 
			
		||||
 | 
			
		||||
#else /* !CONFIG_USER_ONLY */
 | 
			
		||||
/* NOTE: we use double casts if pointers and target_ulong have
 | 
			
		||||
   different sizes */
 | 
			
		||||
#define saddr(x) (uint8_t *)(intptr_t)(x)
 | 
			
		||||
#define laddr(x) (uint8_t *)(intptr_t)(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define ldub_raw(p) ldub_p(laddr((p)))
 | 
			
		||||
#define ldsb_raw(p) ldsb_p(laddr((p)))
 | 
			
		||||
#define lduw_raw(p) lduw_p(laddr((p)))
 | 
			
		||||
#define ldsw_raw(p) ldsw_p(laddr((p)))
 | 
			
		||||
#define ldl_raw(p) ldl_p(laddr((p)))
 | 
			
		||||
#define ldq_raw(p) ldq_p(laddr((p)))
 | 
			
		||||
#define ldfl_raw(p) ldfl_p(laddr((p)))
 | 
			
		||||
#define ldfq_raw(p) ldfq_p(laddr((p)))
 | 
			
		||||
#define stb_raw(p, v) stb_p(saddr((p)), v)
 | 
			
		||||
#define stw_raw(p, v) stw_p(saddr((p)), v)
 | 
			
		||||
#define stl_raw(p, v) stl_p(saddr((p)), v)
 | 
			
		||||
#define stq_raw(p, v) stq_p(saddr((p)), v)
 | 
			
		||||
#define stfl_raw(p, v) stfl_p(saddr((p)), v)
 | 
			
		||||
#define stfq_raw(p, v) stfq_p(saddr((p)), v)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_USER_ONLY)
 | 
			
		||||
 | 
			
		||||
/* if user mode, no other memory access functions */
 | 
			
		||||
#define ldub(p) ldub_raw(p)
 | 
			
		||||
#define ldsb(p) ldsb_raw(p)
 | 
			
		||||
#define lduw(p) lduw_raw(p)
 | 
			
		||||
#define ldsw(p) ldsw_raw(p)
 | 
			
		||||
#define ldl(p) ldl_raw(p)
 | 
			
		||||
#define ldq(p) ldq_raw(p)
 | 
			
		||||
#define ldfl(p) ldfl_raw(p)
 | 
			
		||||
#define ldfq(p) ldfq_raw(p)
 | 
			
		||||
#define stb(p, v) stb_raw(p, v)
 | 
			
		||||
#define stw(p, v) stw_raw(p, v)
 | 
			
		||||
#define stl(p, v) stl_raw(p, v)
 | 
			
		||||
#define stq(p, v) stq_raw(p, v)
 | 
			
		||||
#define stfl(p, v) stfl_raw(p, v)
 | 
			
		||||
#define stfq(p, v) stfq_raw(p, v)
 | 
			
		||||
 | 
			
		||||
#define cpu_ldub_code(env1, p) ldub_raw(p)
 | 
			
		||||
#define cpu_ldsb_code(env1, p) ldsb_raw(p)
 | 
			
		||||
#define cpu_lduw_code(env1, p) lduw_raw(p)
 | 
			
		||||
#define cpu_ldsw_code(env1, p) ldsw_raw(p)
 | 
			
		||||
#define cpu_ldl_code(env1, p) ldl_raw(p)
 | 
			
		||||
#define cpu_ldq_code(env1, p) ldq_raw(p)
 | 
			
		||||
 | 
			
		||||
#define cpu_ldub_data(env, addr) ldub_raw(addr)
 | 
			
		||||
#define cpu_lduw_data(env, addr) lduw_raw(addr)
 | 
			
		||||
#define cpu_ldsw_data(env, addr) ldsw_raw(addr)
 | 
			
		||||
#define cpu_ldl_data(env, addr) ldl_raw(addr)
 | 
			
		||||
#define cpu_ldq_data(env, addr) ldq_raw(addr)
 | 
			
		||||
 | 
			
		||||
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
 | 
			
		||||
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
 | 
			
		||||
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
 | 
			
		||||
#define cpu_stq_data(env, addr, data) stq_raw(addr, data)
 | 
			
		||||
 | 
			
		||||
#define cpu_ldub_kernel(env, addr) ldub_raw(addr)
 | 
			
		||||
#define cpu_lduw_kernel(env, addr) lduw_raw(addr)
 | 
			
		||||
#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr)
 | 
			
		||||
#define cpu_ldl_kernel(env, addr) ldl_raw(addr)
 | 
			
		||||
#define cpu_ldq_kernel(env, addr) ldq_raw(addr)
 | 
			
		||||
 | 
			
		||||
#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data)
 | 
			
		||||
#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data)
 | 
			
		||||
#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data)
 | 
			
		||||
#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data)
 | 
			
		||||
 | 
			
		||||
#define ldub_kernel(p) ldub_raw(p)
 | 
			
		||||
#define ldsb_kernel(p) ldsb_raw(p)
 | 
			
		||||
#define lduw_kernel(p) lduw_raw(p)
 | 
			
		||||
#define ldsw_kernel(p) ldsw_raw(p)
 | 
			
		||||
#define ldl_kernel(p) ldl_raw(p)
 | 
			
		||||
#define ldq_kernel(p) ldq_raw(p)
 | 
			
		||||
#define ldfl_kernel(p) ldfl_raw(p)
 | 
			
		||||
#define ldfq_kernel(p) ldfq_raw(p)
 | 
			
		||||
#define stb_kernel(p, v) stb_raw(p, v)
 | 
			
		||||
#define stw_kernel(p, v) stw_raw(p, v)
 | 
			
		||||
#define stl_kernel(p, v) stl_raw(p, v)
 | 
			
		||||
#define stq_kernel(p, v) stq_raw(p, v)
 | 
			
		||||
#define stfl_kernel(p, v) stfl_raw(p, v)
 | 
			
		||||
#define stfq_kernel(p, vt) stfq_raw(p, v)
 | 
			
		||||
 | 
			
		||||
#define cpu_ldub_data(env, addr) ldub_raw(addr)
 | 
			
		||||
#define cpu_lduw_data(env, addr) lduw_raw(addr)
 | 
			
		||||
#define cpu_ldl_data(env, addr) ldl_raw(addr)
 | 
			
		||||
 | 
			
		||||
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
 | 
			
		||||
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
 | 
			
		||||
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
/* XXX: find something cleaner.
 | 
			
		||||
 * Furthermore, this is false for 64 bits targets
 | 
			
		||||
 */
 | 
			
		||||
#define ldul_user       ldl_user
 | 
			
		||||
#define ldul_kernel     ldl_kernel
 | 
			
		||||
#define ldul_hypv       ldl_hypv
 | 
			
		||||
#define ldul_executive  ldl_executive
 | 
			
		||||
#define ldul_supervisor ldl_supervisor
 | 
			
		||||
 | 
			
		||||
/* The memory helpers for tcg-generated code need tcg_target_long etc.  */
 | 
			
		||||
#include "tcg.h"
 | 
			
		||||
 | 
			
		||||
uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
 | 
			
		||||
void helper_stb_mmu(CPUArchState *env, target_ulong addr,
 | 
			
		||||
                    uint8_t val, int mmu_idx);
 | 
			
		||||
void helper_stw_mmu(CPUArchState *env, target_ulong addr,
 | 
			
		||||
                    uint16_t val, int mmu_idx);
 | 
			
		||||
void helper_stl_mmu(CPUArchState *env, target_ulong addr,
 | 
			
		||||
                    uint32_t val, int mmu_idx);
 | 
			
		||||
void helper_stq_mmu(CPUArchState *env, target_ulong addr,
 | 
			
		||||
                    uint64_t val, int mmu_idx);
 | 
			
		||||
 | 
			
		||||
uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX 0
 | 
			
		||||
#define MEMSUFFIX MMU_MODE0_SUFFIX
 | 
			
		||||
#define DATA_SIZE 1
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 2
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 4
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 8
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX 1
 | 
			
		||||
#define MEMSUFFIX MMU_MODE1_SUFFIX
 | 
			
		||||
#define DATA_SIZE 1
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 2
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 4
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 8
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
 | 
			
		||||
#if (NB_MMU_MODES >= 3)
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX 2
 | 
			
		||||
#define MEMSUFFIX MMU_MODE2_SUFFIX
 | 
			
		||||
#define DATA_SIZE 1
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 2
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 4
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 8
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
#endif /* (NB_MMU_MODES >= 3) */
 | 
			
		||||
 | 
			
		||||
#if (NB_MMU_MODES >= 4)
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX 3
 | 
			
		||||
#define MEMSUFFIX MMU_MODE3_SUFFIX
 | 
			
		||||
#define DATA_SIZE 1
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 2
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 4
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 8
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
#endif /* (NB_MMU_MODES >= 4) */
 | 
			
		||||
 | 
			
		||||
#if (NB_MMU_MODES >= 5)
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX 4
 | 
			
		||||
#define MEMSUFFIX MMU_MODE4_SUFFIX
 | 
			
		||||
#define DATA_SIZE 1
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 2
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 4
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 8
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
#endif /* (NB_MMU_MODES >= 5) */
 | 
			
		||||
 | 
			
		||||
#if (NB_MMU_MODES >= 6)
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX 5
 | 
			
		||||
#define MEMSUFFIX MMU_MODE5_SUFFIX
 | 
			
		||||
#define DATA_SIZE 1
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 2
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 4
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 8
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
#endif /* (NB_MMU_MODES >= 6) */
 | 
			
		||||
 | 
			
		||||
#if (NB_MMU_MODES > 6)
 | 
			
		||||
#error "NB_MMU_MODES > 6 is not supported for now"
 | 
			
		||||
#endif /* (NB_MMU_MODES > 6) */
 | 
			
		||||
 | 
			
		||||
/* these access are slower, they must be as rare as possible */
 | 
			
		||||
#define CPU_MMU_INDEX (cpu_mmu_index(env))
 | 
			
		||||
#define MEMSUFFIX _data
 | 
			
		||||
#define DATA_SIZE 1
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 2
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 4
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 8
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
 | 
			
		||||
#define ldub(p) ldub_data(p)
 | 
			
		||||
#define ldsb(p) ldsb_data(p)
 | 
			
		||||
#define lduw(p) lduw_data(p)
 | 
			
		||||
#define ldsw(p) ldsw_data(p)
 | 
			
		||||
#define ldl(p) ldl_data(p)
 | 
			
		||||
#define ldq(p) ldq_data(p)
 | 
			
		||||
 | 
			
		||||
#define stb(p, v) stb_data(p, v)
 | 
			
		||||
#define stw(p, v) stw_data(p, v)
 | 
			
		||||
#define stl(p, v) stl_data(p, v)
 | 
			
		||||
#define stq(p, v) stq_data(p, v)
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX (cpu_mmu_index(env))
 | 
			
		||||
#define MEMSUFFIX _code
 | 
			
		||||
#define SOFTMMU_CODE_ACCESS
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 1
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 2
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 4
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#define DATA_SIZE 8
 | 
			
		||||
#include "exec/cpu_ldst_template.h"
 | 
			
		||||
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MEMSUFFIX
 | 
			
		||||
#undef SOFTMMU_CODE_ACCESS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * tlb_vaddr_to_host:
 | 
			
		||||
 * @env: CPUArchState
 | 
			
		||||
 * @addr: guest virtual address to look up
 | 
			
		||||
 * @access_type: 0 for read, 1 for write, 2 for execute
 | 
			
		||||
 * @mmu_idx: MMU index to use for lookup
 | 
			
		||||
 *
 | 
			
		||||
 * Look up the specified guest virtual index in the TCG softmmu TLB.
 | 
			
		||||
 * If the TLB contains a host virtual address suitable for direct RAM
 | 
			
		||||
 * access, then return it. Otherwise (TLB miss, TLB entry is for an
 | 
			
		||||
 * I/O access, etc) return NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * This is the equivalent of the initial fast-path code used by
 | 
			
		||||
 * TCG backends for guest load and store accesses.
 | 
			
		||||
 */
 | 
			
		||||
static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
 | 
			
		||||
                                      int access_type, int mmu_idx)
 | 
			
		||||
{
 | 
			
		||||
    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 | 
			
		||||
    CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
 | 
			
		||||
    target_ulong tlb_addr;
 | 
			
		||||
    uintptr_t haddr;
 | 
			
		||||
 | 
			
		||||
    switch (access_type) {
 | 
			
		||||
    case 0:
 | 
			
		||||
        tlb_addr = tlbentry->addr_read;
 | 
			
		||||
        break;
 | 
			
		||||
    case 1:
 | 
			
		||||
        tlb_addr = tlbentry->addr_write;
 | 
			
		||||
        break;
 | 
			
		||||
    case 2:
 | 
			
		||||
        tlb_addr = tlbentry->addr_code;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        g_assert_not_reached();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((addr & TARGET_PAGE_MASK)
 | 
			
		||||
        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
 | 
			
		||||
        /* TLB entry is for a different page */
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tlb_addr & ~TARGET_PAGE_MASK) {
 | 
			
		||||
        /* IO access */
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    haddr = addr + env->tlb_table[mmu_idx][index].addend;
 | 
			
		||||
    return (void *)haddr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* defined(CONFIG_USER_ONLY) */
 | 
			
		||||
 | 
			
		||||
#endif /* CPU_LDST_H */
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
 * 32 and 64 bit cases, also generate floating point functions with
 | 
			
		||||
 * the same size.
 | 
			
		||||
 *
 | 
			
		||||
 * Not used directly but included from softmmu_exec.h and exec-all.h.
 | 
			
		||||
 * Not used directly but included from cpu_ldst.h.
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (c) 2003 Fabrice Bellard
 | 
			
		||||
 *
 | 
			
		||||
@@ -47,35 +47,18 @@
 | 
			
		||||
#error unsupported data size
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ACCESS_TYPE < (NB_MMU_MODES)
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX ACCESS_TYPE
 | 
			
		||||
#define MMUSUFFIX _mmu
 | 
			
		||||
 | 
			
		||||
#elif ACCESS_TYPE == (NB_MMU_MODES)
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX (cpu_mmu_index(env))
 | 
			
		||||
#define MMUSUFFIX _mmu
 | 
			
		||||
 | 
			
		||||
#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
 | 
			
		||||
 | 
			
		||||
#define CPU_MMU_INDEX (cpu_mmu_index(env))
 | 
			
		||||
#define MMUSUFFIX _cmmu
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#error invalid ACCESS_TYPE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DATA_SIZE == 8
 | 
			
		||||
#define RES_TYPE uint64_t
 | 
			
		||||
#else
 | 
			
		||||
#define RES_TYPE uint32_t
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ACCESS_TYPE == (NB_MMU_MODES + 1)
 | 
			
		||||
#ifdef SOFTMMU_CODE_ACCESS
 | 
			
		||||
#define ADDR_READ addr_code
 | 
			
		||||
#define MMUSUFFIX _cmmu
 | 
			
		||||
#else
 | 
			
		||||
#define ADDR_READ addr_read
 | 
			
		||||
#define MMUSUFFIX _mmu
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* generic load/store macros */
 | 
			
		||||
@@ -124,7 +107,7 @@ glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
 | 
			
		||||
#ifndef SOFTMMU_CODE_ACCESS
 | 
			
		||||
 | 
			
		||||
/* generic store macro */
 | 
			
		||||
 | 
			
		||||
@@ -148,9 +131,7 @@ glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
 | 
			
		||||
 | 
			
		||||
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
 | 
			
		||||
 | 
			
		||||
#if DATA_SIZE == 8
 | 
			
		||||
static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env,
 | 
			
		||||
@@ -200,7 +181,7 @@ static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env,
 | 
			
		||||
}
 | 
			
		||||
#endif /* DATA_SIZE == 4 */
 | 
			
		||||
 | 
			
		||||
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
 | 
			
		||||
#endif /* !SOFTMMU_CODE_ACCESS */
 | 
			
		||||
 | 
			
		||||
#undef RES_TYPE
 | 
			
		||||
#undef DATA_TYPE
 | 
			
		||||
@@ -208,6 +189,5 @@ static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env,
 | 
			
		||||
#undef SUFFIX
 | 
			
		||||
#undef USUFFIX
 | 
			
		||||
#undef DATA_SIZE
 | 
			
		||||
#undef CPU_MMU_INDEX
 | 
			
		||||
#undef MMUSUFFIX
 | 
			
		||||
#undef ADDR_READ
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user