diff options
189 files changed, 4640 insertions, 3177 deletions
@@ -209,6 +209,7 @@ clean: rm -Rf .libs rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d rm -f qemu-img-cmds.h + rm -f trace/*.o trace/*.d rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp rm -f trace-dtrace.h trace-dtrace.h-timestamp @@ -365,9 +366,8 @@ tar: rm -rf /tmp/$(FILE) SYSTEM_TARGETS=$(filter %-softmmu,$(TARGET_DIRS)) -SYSTEM_PROGS=$(patsubst qemu-system-i386,qemu, \ - $(patsubst %-softmmu,qemu-system-%, \ - $(SYSTEM_TARGETS))) +SYSTEM_PROGS=$(patsubst %-softmmu,qemu-system-%, \ + $(SYSTEM_TARGETS)) USER_TARGETS=$(filter %-user,$(TARGET_DIRS)) USER_PROGS=$(patsubst %-bsd-user,qemu-%, \ diff --git a/Makefile.hw b/Makefile.hw index 63eb7e40be..659e441992 100644 --- a/Makefile.hw +++ b/Makefile.hw @@ -10,7 +10,6 @@ include $(SRC_PATH)/rules.mak $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw) QEMU_CFLAGS+=-I.. -QEMU_CFLAGS += $(GLIB_CFLAGS) include $(SRC_PATH)/Makefile.objs diff --git a/Makefile.objs b/Makefile.objs index d1f3e5dae5..26b885bfeb 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -372,18 +372,24 @@ trace-dtrace.lo: trace-dtrace.dtrace $(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC dtrace -o $@ -G -s $<, " lt GEN trace-dtrace.o") endif -simpletrace.o: simpletrace.c $(GENERATED_HEADERS) +trace/simple.o: trace/simple.c $(GENERATED_HEADERS) -ifeq ($(TRACE_BACKEND),dtrace) -trace-obj-y = trace-dtrace.o -else +trace-obj-$(CONFIG_TRACE_DTRACE) += trace-dtrace.o +ifneq ($(TRACE_BACKEND),dtrace) trace-obj-y = trace.o -ifeq ($(TRACE_BACKEND),simple) -trace-obj-y += simpletrace.o -user-obj-y += qemu-timer-common.o -endif endif +trace-nested-$(CONFIG_TRACE_DEFAULT) += default.o + +trace-nested-$(CONFIG_TRACE_SIMPLE) += simple.o +trace-obj-$(CONFIG_TRACE_SIMPLE) += qemu-timer-common.o + +trace-nested-$(CONFIG_TRACE_STDERR) += stderr.o + +trace-nested-y += control.o + +trace-obj-y += $(addprefix trace/, $(trace-nested-y)) + ###################################################################### # smartcard diff --git a/Makefile.target b/Makefile.target index c9957ae63a..0787758ad6 100644 --- a/Makefile.target +++ b/Makefile.target @@ -27,12 +27,8 @@ ifdef CONFIG_USER_ONLY QEMU_PROG=qemu-$(TARGET_ARCH2) else # system emulator name -ifeq ($(TARGET_ARCH), i386) -QEMU_PROG=qemu$(EXESUF) -else QEMU_PROG=qemu-system-$(TARGET_ARCH2)$(EXESUF) endif -endif PROGS=$(QEMU_PROG) STPFILES= @@ -44,7 +40,7 @@ endif config-target.h: config-target.h-timestamp config-target.h-timestamp: config-target.mak -ifdef CONFIG_SYSTEMTAP_TRACE +ifdef CONFIG_TRACE_SYSTEMTAP stap: $(QEMU_PROG).stp ifdef CONFIG_USER_ONLY @@ -195,6 +191,7 @@ obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virt obj-y += vhost_net.o obj-$(CONFIG_VHOST_NET) += vhost.o obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o +obj-y += rwhandler.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o obj-$(CONFIG_NO_KVM) += kvm-stub.o obj-y += memory.o @@ -386,16 +383,18 @@ obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y)) endif # CONFIG_SOFTMMU ifndef CONFIG_LINUX_USER +ifndef CONFIG_BSD_USER # libcacard needs qemu-thread support, and besides is only needed by devices -# so not requires with linux-user targets +# so not requires with linux-user / bsd-user targets obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y)) +endif # CONFIG_BSD_USER endif # CONFIG_LINUX_USER obj-y += $(addprefix ../, $(trace-obj-y)) obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o $(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) - $(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) + $(call LINK,$^) gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh @@ -411,7 +410,7 @@ clean: rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c -ifdef CONFIG_SYSTEMTAP_TRACE +ifdef CONFIG_TRACE_SYSTEMTAP rm -f *.stp endif @@ -422,7 +421,7 @@ ifneq ($(STRIP),) $(STRIP) $(patsubst %,"$(DESTDIR)$(bindir)/%",$(PROGS)) endif endif -ifdef CONFIG_SYSTEMTAP_TRACE +ifdef CONFIG_TRACE_SYSTEMTAP $(INSTALL_DIR) "$(DESTDIR)$(datadir)/../systemtap/tapset" $(INSTALL_DATA) $(QEMU_PROG).stp "$(DESTDIR)$(datadir)/../systemtap/tapset" endif @@ -151,7 +151,7 @@ struct external_lineno { #define E_FILNMLEN 14 /* # characters in a file name */ #define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ -struct __attribute__((packed)) external_syment +struct QEMU_PACKED external_syment { union { char e_name[E_SYMNMLEN]; @@ -71,23 +71,23 @@ SECTIONS .data1 : { *(.data1) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { @@ -437,6 +437,33 @@ static int refresh_total_sectors(BlockDriverState *bs, int64_t hint) return 0; } +/** + * Set open flags for a given cache mode + * + * Return 0 on success, -1 if the cache mode was invalid. + */ +int bdrv_parse_cache_flags(const char *mode, int *flags) +{ + *flags &= ~BDRV_O_CACHE_MASK; + + if (!strcmp(mode, "off") || !strcmp(mode, "none")) { + *flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; + } else if (!strcmp(mode, "directsync")) { + *flags |= BDRV_O_NOCACHE; + } else if (!strcmp(mode, "writeback")) { + *flags |= BDRV_O_CACHE_WB; + } else if (!strcmp(mode, "unsafe")) { + *flags |= BDRV_O_CACHE_WB; + *flags |= BDRV_O_NO_FLUSH; + } else if (!strcmp(mode, "writethrough")) { + /* this is the default */ + } else { + return -1; + } + + return 0; +} + /* * Common part for opening disk images and files */ @@ -1163,8 +1190,8 @@ int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, return ret; } - /* No flush needed for cache=writethrough, it uses O_DSYNC */ - if ((bs->open_flags & BDRV_O_CACHE_MASK) != 0) { + /* No flush needed for cache modes that use O_DSYNC */ + if ((bs->open_flags & BDRV_O_CACHE_WB) != 0) { bdrv_flush(bs); } @@ -1300,7 +1327,7 @@ struct partition { uint8_t end_cyl; /* end cylinder */ uint32_t start_sect; /* starting sector counting from 0 */ uint32_t nr_sects; /* nr of sectors in partition */ -} __attribute__((packed)); +} QEMU_PACKED; /* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ static int guess_disk_lchs(BlockDriverState *bs, @@ -1888,11 +1915,19 @@ static void bdrv_stats_iter(QObject *data, void *opaque) " wr_bytes=%" PRId64 " rd_operations=%" PRId64 " wr_operations=%" PRId64 + " flush_operations=%" PRId64 + " wr_total_time_ns=%" PRId64 + " rd_total_time_ns=%" PRId64 + " flush_total_time_ns=%" PRId64 "\n", qdict_get_int(qdict, "rd_bytes"), qdict_get_int(qdict, "wr_bytes"), qdict_get_int(qdict, "rd_operations"), - qdict_get_int(qdict, "wr_operations")); + qdict_get_int(qdict, "wr_operations"), + qdict_get_int(qdict, "flush_operations"), + qdict_get_int(qdict, "wr_total_time_ns"), + qdict_get_int(qdict, "rd_total_time_ns"), + qdict_get_int(qdict, "flush_total_time_ns")); } void bdrv_stats_print(Monitor *mon, const QObject *data) @@ -1910,12 +1945,22 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs) "'wr_bytes': %" PRId64 "," "'rd_operations': %" PRId64 "," "'wr_operations': %" PRId64 "," - "'wr_highest_offset': %" PRId64 + "'wr_highest_offset': %" PRId64 "," + "'flush_operations': %" PRId64 "," + "'wr_total_time_ns': %" PRId64 "," + "'rd_total_time_ns': %" PRId64 "," + "'flush_total_time_ns': %" PRId64 "} }", - bs->rd_bytes, bs->wr_bytes, - bs->rd_ops, bs->wr_ops, + bs->nr_bytes[BDRV_ACCT_READ], + bs->nr_bytes[BDRV_ACCT_WRITE], + bs->nr_ops[BDRV_ACCT_READ], + bs->nr_ops[BDRV_ACCT_WRITE], bs->wr_highest_sector * - (uint64_t)BDRV_SECTOR_SIZE); + (uint64_t)BDRV_SECTOR_SIZE, + bs->nr_ops[BDRV_ACCT_FLUSH], + bs->total_time_ns[BDRV_ACCT_WRITE], + bs->total_time_ns[BDRV_ACCT_READ], + bs->total_time_ns[BDRV_ACCT_FLUSH]); dict = qobject_to_qdict(res); if (*bs->device_name) { @@ -2229,7 +2274,6 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) return buf; } - /**************************************************************/ /* async I/Os */ @@ -2238,7 +2282,6 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, BlockDriverCompletionFunc *cb, void *opaque) { BlockDriver *drv = bs->drv; - BlockDriverAIOCB *ret; trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque); @@ -2247,16 +2290,8 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, if (bdrv_check_request(bs, sector_num, nb_sectors)) return NULL; - ret = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors, - cb, opaque); - - if (ret) { - /* Update stats even though technically transfer has not happened. */ - bs->rd_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE; - bs->rd_ops++; - } - - return ret; + return drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors, + cb, opaque); } typedef struct BlockCompleteData { @@ -2323,9 +2358,6 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, cb, opaque); if (ret) { - /* Update stats even though technically transfer has not happened. */ - bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE; - bs->wr_ops ++; if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { bs->wr_highest_sector = sector_num + nb_sectors - 1; } @@ -3133,6 +3165,27 @@ int bdrv_in_use(BlockDriverState *bs) return bs->in_use; } +void +bdrv_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, int64_t bytes, + enum BlockAcctType type) +{ + assert(type < BDRV_MAX_IOTYPE); + + cookie->bytes = bytes; + cookie->start_time_ns = get_clock(); + cookie->type = type; +} + +void +bdrv_acct_done(BlockDriverState *bs, BlockAcctCookie *cookie) +{ + assert(cookie->type < BDRV_MAX_IOTYPE); + + bs->nr_bytes[cookie->type] += cookie->bytes; + bs->nr_ops[cookie->type]++; + bs->total_time_ns[cookie->type] += get_clock() - cookie->start_time_ns; +} + int bdrv_img_create(const char *filename, const char *fmt, const char *base_filename, const char *base_fmt, char *options, uint64_t img_size, int flags) @@ -69,6 +69,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options); BlockDriverState *bdrv_new(const char *device_name); void bdrv_make_anon(BlockDriverState *bs); void bdrv_delete(BlockDriverState *bs); +int bdrv_parse_cache_flags(const char *mode, int *flags); int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); int bdrv_open(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv); @@ -254,6 +255,23 @@ int64_t bdrv_get_dirty_count(BlockDriverState *bs); void bdrv_set_in_use(BlockDriverState *bs, int in_use); int bdrv_in_use(BlockDriverState *bs); +enum BlockAcctType { + BDRV_ACCT_READ, + BDRV_ACCT_WRITE, + BDRV_ACCT_FLUSH, + BDRV_MAX_IOTYPE, +}; + +typedef struct BlockAcctCookie { + int64_t bytes; + int64_t start_time_ns; + enum BlockAcctType type; +} BlockAcctCookie; + +void bdrv_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, + int64_t bytes, enum BlockAcctType type); +void bdrv_acct_done(BlockDriverState *bs, BlockAcctCookie *cookie); + typedef enum { BLKDBG_L1_UPDATE, @@ -306,3 +324,4 @@ typedef enum { void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event); #endif + diff --git a/block/curl.c b/block/curl.c index 5c157bc609..f3f61cc8a1 100644 --- a/block/curl.c +++ b/block/curl.c @@ -229,6 +229,23 @@ static void curl_multi_do(void *arg) { CURLState *state = NULL; curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state); + + /* ACBs for successful messages get completed in curl_read_cb */ + if (msg->data.result != CURLE_OK) { + int i; + for (i = 0; i < CURL_NUM_ACB; i++) { + CURLAIOCB *acb = state->acb[i]; + + if (acb == NULL) { + continue; + } + + acb->common.cb(acb->common.opaque, -EIO); + qemu_aio_release(acb); + state->acb[i] = NULL; + } + } + curl_clean_state(state); break; } @@ -277,7 +294,8 @@ static CURLState *curl_init_state(BDRVCURLState *s) curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg); - + curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1); + #ifdef DEBUG_VERBOSE curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1); #endif diff --git a/block/parallels.c b/block/parallels.c index 37d151dcb5..c64103ddbb 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -43,7 +43,7 @@ struct parallels_header { uint32_t catalog_entries; uint32_t nb_sectors; char padding[24]; -} __attribute__((packed)); +} QEMU_PACKED; typedef struct BDRVParallelsState { diff --git a/block/qcow.c b/block/qcow.c index e155d3c002..c8bfecc1cb 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -159,6 +159,8 @@ static int qcow_open(BlockDriverState *bs, int flags) goto fail; bs->backing_file[len] = '\0'; } + + qemu_co_mutex_init(&s->lock); return 0; fail: @@ -190,24 +192,6 @@ static int qcow_set_key(BlockDriverState *bs, const char *key) return -1; if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0) return -1; -#if 0 - /* test */ - { - uint8_t in[16]; - uint8_t out[16]; - uint8_t tmp[16]; - for(i=0;i<16;i++) - in[i] = i; - AES_encrypt(in, tmp, &s->aes_encrypt_key); - AES_decrypt(tmp, out, &s->aes_decrypt_key); - for(i = 0; i < 16; i++) - printf(" %02x", tmp[i]); - printf("\n"); - for(i = 0; i < 16; i++) - printf(" %02x", out[i]); - printf("\n"); - } -#endif return 0; } @@ -441,296 +425,178 @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset) return 0; } -#if 0 - -static int qcow_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static int qcow_co_readv(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *qiov) { BDRVQcowState *s = bs->opaque; - int ret, index_in_cluster, n; + int index_in_cluster; + int ret = 0, n; uint64_t cluster_offset; + struct iovec hd_iov; + QEMUIOVector hd_qiov; + uint8_t *buf; + void *orig_buf; + + if (qiov->niov > 1) { + buf = orig_buf = qemu_blockalign(bs, qiov->size); + } else { + orig_buf = NULL; + buf = (uint8_t *)qiov->iov->iov_base; + } + + qemu_co_mutex_lock(&s->lock); - while (nb_sectors > 0) { - cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); + while (nb_sectors != 0) { + /* prepare next request */ + cluster_offset = get_cluster_offset(bs, sector_num << 9, + 0, 0, 0, 0); index_in_cluster = sector_num & (s->cluster_sectors - 1); n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) + if (n > nb_sectors) { n = nb_sectors; + } + if (!cluster_offset) { if (bs->backing_hd) { /* read from the base image */ - ret = bdrv_read(bs->backing_hd, sector_num, buf, n); - if (ret < 0) - return -1; + hd_iov.iov_base = (void *)buf; + hd_iov.iov_len = n * 512; + qemu_iovec_init_external(&hd_qiov, &hd_iov, 1); + qemu_co_mutex_unlock(&s->lock); + ret = bdrv_co_readv(bs->backing_hd, sector_num, + n, &hd_qiov); + qemu_co_mutex_lock(&s->lock); + if (ret < 0) { + goto fail; + } } else { + /* Note: in this case, no need to wait */ memset(buf, 0, 512 * n); } } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - if (decompress_cluster(bs, cluster_offset) < 0) - return -1; - memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n); + /* add AIO support for compressed blocks ? */ + if (decompress_cluster(bs, cluster_offset) < 0) { + goto fail; + } + memcpy(buf, + s->cluster_cache + index_in_cluster * 512, 512 * n); } else { - ret = bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512); - if (ret != n * 512) - return -1; + if ((cluster_offset & 511) != 0) { + goto fail; + } + hd_iov.iov_base = (void *)buf; + hd_iov.iov_len = n * 512; + qemu_iovec_init_external(&hd_qiov, &hd_iov, 1); + qemu_co_mutex_unlock(&s->lock); + ret = bdrv_co_readv(bs->file, + (cluster_offset >> 9) + index_in_cluster, + n, &hd_qiov); + qemu_co_mutex_lock(&s->lock); + if (ret < 0) { + break; + } if (s->crypt_method) { - encrypt_sectors(s, sector_num, buf, buf, n, 0, + encrypt_sectors(s, sector_num, buf, buf, + n, 0, &s->aes_decrypt_key); } } + ret = 0; + nb_sectors -= n; sector_num += n; buf += n * 512; } - return 0; -} -#endif -typedef struct QCowAIOCB { - BlockDriverAIOCB common; - int64_t sector_num; - QEMUIOVector *qiov; - uint8_t *buf; - void *orig_buf; - int nb_sectors; - int n; - uint64_t cluster_offset; - uint8_t *cluster_data; - struct iovec hd_iov; - bool is_write; - QEMUBH *bh; - QEMUIOVector hd_qiov; - BlockDriverAIOCB *hd_aiocb; -} QCowAIOCB; - -static void qcow_aio_cancel(BlockDriverAIOCB *blockacb) -{ - QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common); - if (acb->hd_aiocb) - bdrv_aio_cancel(acb->hd_aiocb); - qemu_aio_release(acb); -} - -static AIOPool qcow_aio_pool = { - .aiocb_size = sizeof(QCowAIOCB), - .cancel = qcow_aio_cancel, -}; - -static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - int is_write) -{ - QCowAIOCB *acb; - - acb = qemu_aio_get(&qcow_aio_pool, bs, NULL, NULL); - if (!acb) - return NULL; - acb->hd_aiocb = NULL; - acb->sector_num = sector_num; - acb->qiov = qiov; - acb->is_write = is_write; +done: + qemu_co_mutex_unlock(&s->lock); if (qiov->niov > 1) { - acb->buf = acb->orig_buf = qemu_blockalign(bs, qiov->size); - if (is_write) - qemu_iovec_to_buffer(qiov, acb->buf); - } else { - acb->buf = (uint8_t *)qiov->iov->iov_base; + qemu_iovec_from_buffer(qiov, orig_buf, qiov->size); + qemu_vfree(orig_buf); } - acb->nb_sectors = nb_sectors; - acb->n = 0; - acb->cluster_offset = 0; - return acb; + + return ret; + +fail: + ret = -EIO; + goto done; } -static int qcow_aio_read_cb(void *opaque) +static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *qiov) { - QCowAIOCB *acb = opaque; - BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; int index_in_cluster; - int ret; + uint64_t cluster_offset; + const uint8_t *src_buf; + int ret = 0, n; + uint8_t *cluster_data = NULL; + struct iovec hd_iov; + QEMUIOVector hd_qiov; + uint8_t *buf; + void *orig_buf; - acb->hd_aiocb = NULL; + s->cluster_cache_offset = -1; /* disable compressed cache */ - redo: - /* post process the read buffer */ - if (!acb->cluster_offset) { - /* nothing to do */ - } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { - /* nothing to do */ + if (qiov->niov > 1) { + buf = orig_buf = qemu_blockalign(bs, qiov->size); + qemu_iovec_to_buffer(qiov, buf); } else { - if (s->crypt_method) { - encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, - acb->n, 0, - &s->aes_decrypt_key); - } + orig_buf = NULL; + buf = (uint8_t *)qiov->iov->iov_base; } - acb->nb_sectors -= acb->n; - acb->sector_num += acb->n; - acb->buf += acb->n * 512; + qemu_co_mutex_lock(&s->lock); - if (acb->nb_sectors == 0) { - /* request completed */ - return 0; - } + while (nb_sectors != 0) { - /* prepare next AIO request */ - acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, - 0, 0, 0, 0); - index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); - acb->n = s->cluster_sectors - index_in_cluster; - if (acb->n > acb->nb_sectors) - acb->n = acb->nb_sectors; - - if (!acb->cluster_offset) { - if (bs->backing_hd) { - /* read from the base image */ - acb->hd_iov.iov_base = (void *)acb->buf; - acb->hd_iov.iov_len = acb->n * 512; - qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_readv(bs->backing_hd, acb->sector_num, - acb->n, &acb->hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - return -EIO; - } - } else { - /* Note: in this case, no need to wait */ - memset(acb->buf, 0, 512 * acb->n); - goto redo; + index_in_cluster = sector_num & (s->cluster_sectors - 1); + n = s->cluster_sectors - index_in_cluster; + if (n > nb_sectors) { + n = nb_sectors; } - } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { - /* add AIO support for compressed blocks ? */ - if (decompress_cluster(bs, acb->cluster_offset) < 0) { - return -EIO; + cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0, + index_in_cluster, + index_in_cluster + n); + if (!cluster_offset || (cluster_offset & 511) != 0) { + ret = -EIO; + break; } - memcpy(acb->buf, - s->cluster_cache + index_in_cluster * 512, 512 * acb->n); - goto redo; - } else { - if ((acb->cluster_offset & 511) != 0) { - return -EIO; + if (s->crypt_method) { + if (!cluster_data) { + cluster_data = g_malloc0(s->cluster_size); + } + encrypt_sectors(s, sector_num, cluster_data, buf, + n, 1, &s->aes_encrypt_key); + src_buf = cluster_data; + } else { + src_buf = buf; } - acb->hd_iov.iov_base = (void *)acb->buf; - acb->hd_iov.iov_len = acb->n * 512; - qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); + + hd_iov.iov_base = (void *)src_buf; + hd_iov.iov_len = n * 512; + qemu_iovec_init_external(&hd_qiov, &hd_iov, 1); qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_readv(bs->file, - (acb->cluster_offset >> 9) + index_in_cluster, - acb->n, &acb->hd_qiov); + ret = bdrv_co_writev(bs->file, + (cluster_offset >> 9) + index_in_cluster, + n, &hd_qiov); qemu_co_mutex_lock(&s->lock); if (ret < 0) { - return ret; + break; } - } - - return 1; -} - -static int qcow_co_readv(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb; - int ret; - - acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, 0); - - qemu_co_mutex_lock(&s->lock); - do { - ret = qcow_aio_read_cb(acb); - } while (ret > 0); - qemu_co_mutex_unlock(&s->lock); + ret = 0; - if (acb->qiov->niov > 1) { - qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size); - qemu_vfree(acb->orig_buf); - } - qemu_aio_release(acb); - - return ret; -} - -static int qcow_aio_write_cb(void *opaque) -{ - QCowAIOCB *acb = opaque; - BlockDriverState *bs = acb->common.bs; - BDRVQcowState *s = bs->opaque; - int index_in_cluster; - uint64_t cluster_offset; - const uint8_t *src_buf; - int ret; - - acb->hd_aiocb = NULL; - - acb->nb_sectors -= acb->n; - acb->sector_num += acb->n; - acb->buf += acb->n * 512; - - if (acb->nb_sectors == 0) { - /* request completed */ - return 0; - } - - index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); - acb->n = s->cluster_sectors - index_in_cluster; - if (acb->n > acb->nb_sectors) - acb->n = acb->nb_sectors; - cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, - index_in_cluster, - index_in_cluster + acb->n); - if (!cluster_offset || (cluster_offset & 511) != 0) { - return -EIO; - } - if (s->crypt_method) { - if (!acb->cluster_data) { - acb->cluster_data = g_malloc0(s->cluster_size); - } - encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, - acb->n, 1, &s->aes_encrypt_key); - src_buf = acb->cluster_data; - } else { - src_buf = acb->buf; - } - - acb->hd_iov.iov_base = (void *)src_buf; - acb->hd_iov.iov_len = acb->n * 512; - qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_writev(bs->file, - (cluster_offset >> 9) + index_in_cluster, - acb->n, &acb->hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - return ret; + nb_sectors -= n; + sector_num += n; + buf += n * 512; } - return 1; -} - -static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb; - int ret; - - s->cluster_cache_offset = -1; /* disable compressed cache */ - - acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, 1); - - qemu_co_mutex_lock(&s->lock); - do { - ret = qcow_aio_write_cb(acb); - } while (ret > 0); qemu_co_mutex_unlock(&s->lock); - if (acb->qiov->niov > 1) { - qemu_vfree(acb->orig_buf); + if (qiov->niov > 1) { + qemu_vfree(orig_buf); } - qemu_aio_release(acb); + free(cluster_data); return ret; } diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 9269ddaefd..e06be64876 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -53,7 +53,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size) } #ifdef DEBUG_ALLOC2 - printf("grow l1_table from %d to %d\n", s->l1_size, new_l1_size); + fprintf(stderr, "grow l1_table from %d to %d\n", s->l1_size, new_l1_size); #endif new_l1_size2 = sizeof(uint64_t) * new_l1_size; @@ -381,10 +381,10 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect, * For a given offset of the disk image, find the cluster offset in * qcow2 file. The offset is stored in *cluster_offset. * - * on entry, *num is the number of contiguous clusters we'd like to + * on entry, *num is the number of contiguous sectors we'd like to * access following offset. * - * on exit, *num is the number of contiguous clusters we can read. + * on exit, *num is the number of contiguous sectors we can read. * * Return 0, if the offset is found * Return -errno, otherwise. diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 2a915be57a..9605367777 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -422,7 +422,7 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, int ret; #ifdef DEBUG_ALLOC2 - printf("update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n", + fprintf(stderr, "update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n", offset, length, addend); #endif if (length < 0) { @@ -556,7 +556,7 @@ retry: } } #ifdef DEBUG_ALLOC2 - printf("alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n", + fprintf(stderr, "alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n", size, (s->free_cluster_index - nb_clusters) << s->cluster_bits); #endif @@ -680,24 +680,6 @@ void qcow2_free_any_clusters(BlockDriverState *bs, -void qcow2_create_refcount_update(QCowCreateState *s, int64_t offset, - int64_t size) -{ - int refcount; - int64_t start, last, cluster_offset; - uint16_t *p; - - start = offset & ~(s->cluster_size - 1); - last = (offset + size - 1) & ~(s->cluster_size - 1); - for(cluster_offset = start; cluster_offset <= last; - cluster_offset += s->cluster_size) { - p = &s->refcount_block[cluster_offset >> s->cluster_bits]; - refcount = be16_to_cpu(*p); - refcount++; - *p = cpu_to_be16(refcount); - } -} - /* update the refcounts of snapshots and the copied flag */ int qcow2_update_snapshot_refcount(BlockDriverState *bs, int64_t l1_table_offset, int l1_size, int addend) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 3bd2a30d35..bdc33ba94c 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -26,7 +26,7 @@ #include "block_int.h" #include "block/qcow2.h" -typedef struct __attribute__((packed)) QCowSnapshotHeader { +typedef struct QEMU_PACKED QCowSnapshotHeader { /* header is 8 byte aligned */ uint64_t l1_table_offset; @@ -303,7 +303,10 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) if (qcow2_write_snapshots(bs) < 0) goto fail; #ifdef DEBUG_ALLOC - qcow2_check_refcounts(bs); + { + BdrvCheckResult result = {0}; + qcow2_check_refcounts(bs, &result); + } #endif return 0; fail: @@ -353,7 +356,10 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) goto fail; #ifdef DEBUG_ALLOC - qcow2_check_refcounts(bs); + { + BdrvCheckResult result = {0}; + qcow2_check_refcounts(bs, &result); + } #endif return 0; fail: @@ -390,7 +396,10 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) return ret; } #ifdef DEBUG_ALLOC - qcow2_check_refcounts(bs); + { + BdrvCheckResult result = {0}; + qcow2_check_refcounts(bs, &result); + } #endif return 0; } diff --git a/block/qcow2.c b/block/qcow2.c index bfff6cd963..b725d68b1d 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -87,6 +87,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, while (offset < end_offset) { #ifdef DEBUG_EXT + BDRVQcowState *s = bs->opaque; /* Sanity check */ if (offset > s->cluster_size) printf("qcow2_read_extension: suspicious offset %lu\n", offset); @@ -280,7 +281,10 @@ static int qcow2_open(BlockDriverState *bs, int flags) qemu_co_mutex_init(&s->lock); #ifdef DEBUG_ALLOC - qcow2_check_refcounts(bs); + { + BdrvCheckResult result = {0}; + qcow2_check_refcounts(bs, &result); + } #endif return ret; @@ -372,201 +376,127 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, return n1; } -typedef struct QCowAIOCB { - BlockDriverAIOCB common; - int64_t sector_num; - QEMUIOVector *qiov; - int remaining_sectors; - int cur_nr_sectors; /* number of sectors in current iteration */ - uint64_t bytes_done; - uint64_t cluster_offset; - uint8_t *cluster_data; - bool is_write; - QEMUIOVector hd_qiov; - QEMUBH *bh; - QCowL2Meta l2meta; - QLIST_ENTRY(QCowAIOCB) next_depend; -} QCowAIOCB; - -static void qcow2_aio_cancel(BlockDriverAIOCB *blockacb) -{ - QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common); - qemu_aio_release(acb); -} - -static AIOPool qcow2_aio_pool = { - .aiocb_size = sizeof(QCowAIOCB), - .cancel = qcow2_aio_cancel, -}; - -/* - * Returns 0 when the request is completed successfully, 1 when there is still - * a part left to do and -errno in error cases. - */ -static int qcow2_aio_read_cb(QCowAIOCB *acb) +static int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num, + int remaining_sectors, QEMUIOVector *qiov) { - BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; int index_in_cluster, n1; int ret; + int cur_nr_sectors; /* number of sectors in current iteration */ + uint64_t cluster_offset = 0; + uint64_t bytes_done = 0; + QEMUIOVector hd_qiov; + uint8_t *cluster_data = NULL; - /* post process the read buffer */ - if (!acb->cluster_offset) { - /* nothing to do */ - } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { - /* nothing to do */ - } else { - if (s->crypt_method) { - qcow2_encrypt_sectors(s, acb->sector_num, acb->cluster_data, - acb->cluster_data, acb->cur_nr_sectors, 0, &s->aes_decrypt_key); - qemu_iovec_reset(&acb->hd_qiov); - qemu_iovec_copy(&acb->hd_qiov, acb->qiov, acb->bytes_done, - acb->cur_nr_sectors * 512); - qemu_iovec_from_buffer(&acb->hd_qiov, acb->cluster_data, - 512 * acb->cur_nr_sectors); - } - } + qemu_iovec_init(&hd_qiov, qiov->niov); - acb->remaining_sectors -= acb->cur_nr_sectors; - acb->sector_num += acb->cur_nr_sectors; - acb->bytes_done += acb->cur_nr_sectors * 512; + qemu_co_mutex_lock(&s->lock); - if (acb->remaining_sectors == 0) { - /* request completed */ - return 0; - } + while (remaining_sectors != 0) { - /* prepare next AIO request */ - acb->cur_nr_sectors = acb->remaining_sectors; - if (s->crypt_method) { - acb->cur_nr_sectors = MIN(acb->cur_nr_sectors, - QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors); - } + /* prepare next request */ + cur_nr_sectors = remaining_sectors; + if (s->crypt_method) { + cur_nr_sectors = MIN(cur_nr_sectors, + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors); + } - ret = qcow2_get_cluster_offset(bs, acb->sector_num << 9, - &acb->cur_nr_sectors, &acb->cluster_offset); - if (ret < 0) { - return ret; - } + ret = qcow2_get_cluster_offset(bs, sector_num << 9, + &cur_nr_sectors, &cluster_offset); + if (ret < 0) { + goto fail; + } - index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); - - qemu_iovec_reset(&acb->hd_qiov); - qemu_iovec_copy(&acb->hd_qiov, acb->qiov, acb->bytes_done, - acb->cur_nr_sectors * 512); - - if (!acb->cluster_offset) { - - if (bs->backing_hd) { - /* read from the base image */ - n1 = qcow2_backing_read1(bs->backing_hd, &acb->hd_qiov, - acb->sector_num, acb->cur_nr_sectors); - if (n1 > 0) { - BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_readv(bs->backing_hd, acb->sector_num, - n1, &acb->hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - return ret; + index_in_cluster = sector_num & (s->cluster_sectors - 1); + + qemu_iovec_reset(&hd_qiov); + qemu_iovec_copy(&hd_qiov, qiov, bytes_done, + cur_nr_sectors * 512); + + if (!cluster_offset) { + + if (bs->backing_hd) { + /* read from the base image */ + n1 = qcow2_backing_read1(bs->backing_hd, &hd_qiov, + sector_num, cur_nr_sectors); + if (n1 > 0) { + BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); + qemu_co_mutex_unlock(&s->lock); + ret = bdrv_co_readv(bs->backing_hd, sector_num, + n1, &hd_qiov); + qemu_co_mutex_lock(&s->lock); + if (ret < 0) { + goto fail; + } } + } else { + /* Note: in this case, no need to wait */ + qemu_iovec_memset(&hd_qiov, 0, 512 * cur_nr_sectors); + } + } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { + /* add AIO support for compressed blocks ? */ + ret = qcow2_decompress_cluster(bs, cluster_offset); + if (ret < 0) { + goto fail; } - return 1; - } else { - /* Note: in this case, no need to wait */ - qemu_iovec_memset(&acb->hd_qiov, 0, 512 * acb->cur_nr_sectors); - return 1; - } - } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { - /* add AIO support for compressed blocks ? */ - ret = qcow2_decompress_cluster(bs, acb->cluster_offset); - if (ret < 0) { - return ret; - } - qemu_iovec_from_buffer(&acb->hd_qiov, - s->cluster_cache + index_in_cluster * 512, - 512 * acb->cur_nr_sectors); + qemu_iovec_from_buffer(&hd_qiov, + s->cluster_cache + index_in_cluster * 512, + 512 * cur_nr_sectors); + } else { + if ((cluster_offset & 511) != 0) { + ret = -EIO; + goto fail; + } - return 1; - } else { - if ((acb->cluster_offset & 511) != 0) { - return -EIO; - } + if (s->crypt_method) { + /* + * For encrypted images, read everything into a temporary + * contiguous buffer on which the AES functions can work. + */ + if (!cluster_data) { + cluster_data = + g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); + } - if (s->crypt_method) { - /* - * For encrypted images, read everything into a temporary - * contiguous buffer on which the AES functions can work. - */ - if (!acb->cluster_data) { - acb->cluster_data = - g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); + assert(cur_nr_sectors <= + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors); + qemu_iovec_reset(&hd_qiov); + qemu_iovec_add(&hd_qiov, cluster_data, + 512 * cur_nr_sectors); } - assert(acb->cur_nr_sectors <= - QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors); - qemu_iovec_reset(&acb->hd_qiov); - qemu_iovec_add(&acb->hd_qiov, acb->cluster_data, - 512 * acb->cur_nr_sectors); + BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); + qemu_co_mutex_unlock(&s->lock); + ret = bdrv_co_readv(bs->file, + (cluster_offset >> 9) + index_in_cluster, + cur_nr_sectors, &hd_qiov); + qemu_co_mutex_lock(&s->lock); + if (ret < 0) { + goto fail; + } + if (s->crypt_method) { + qcow2_encrypt_sectors(s, sector_num, cluster_data, + cluster_data, cur_nr_sectors, 0, &s->aes_decrypt_key); + qemu_iovec_reset(&hd_qiov); + qemu_iovec_copy(&hd_qiov, qiov, bytes_done, + cur_nr_sectors * 512); + qemu_iovec_from_buffer(&hd_qiov, cluster_data, + 512 * cur_nr_sectors); + } } - BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_readv(bs->file, - (acb->cluster_offset >> 9) + index_in_cluster, - acb->cur_nr_sectors, &acb->hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - return ret; - } + remaining_sectors -= cur_nr_sectors; + sector_num += cur_nr_sectors; + bytes_done += cur_nr_sectors * 512; } + ret = 0; - return 1; -} - -static QCowAIOCB *qcow2_aio_setup(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque, int is_write) -{ - QCowAIOCB *acb; - - acb = qemu_aio_get(&qcow2_aio_pool, bs, cb, opaque); - if (!acb) - return NULL; - acb->sector_num = sector_num; - acb->qiov = qiov; - acb->is_write = is_write; - - qemu_iovec_init(&acb->hd_qiov, qiov->niov); - - acb->bytes_done = 0; - acb->remaining_sectors = nb_sectors; - acb->cur_nr_sectors = 0; - acb->cluster_offset = 0; - acb->l2meta.nb_clusters = 0; - qemu_co_queue_init(&acb->l2meta.dependent_requests); - return acb; -} - -static int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb; - int ret; - - acb = qcow2_aio_setup(bs, sector_num, qiov, nb_sectors, NULL, NULL, 0); - - qemu_co_mutex_lock(&s->lock); - do { - ret = qcow2_aio_read_cb(acb); - } while (ret > 0); +fail: qemu_co_mutex_unlock(&s->lock); - qemu_iovec_destroy(&acb->hd_qiov); - qemu_aio_release(acb); + qemu_iovec_destroy(&hd_qiov); + g_free(cluster_data); return ret; } @@ -586,104 +516,100 @@ static void run_dependent_requests(BDRVQcowState *s, QCowL2Meta *m) } } -/* - * Returns 0 when the request is completed successfully, 1 when there is still - * a part left to do and -errno in error cases. - */ -static int qcow2_aio_write_cb(QCowAIOCB *acb) +static int qcow2_co_writev(BlockDriverState *bs, + int64_t sector_num, + int remaining_sectors, + QEMUIOVector *qiov) { - BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; int index_in_cluster; int n_end; int ret; + int cur_nr_sectors; /* number of sectors in current iteration */ + QCowL2Meta l2meta; + uint64_t cluster_offset; + QEMUIOVector hd_qiov; + uint64_t bytes_done = 0; + uint8_t *cluster_data = NULL; - ret = qcow2_alloc_cluster_link_l2(bs, &acb->l2meta); + l2meta.nb_clusters = 0; + qemu_co_queue_init(&l2meta.dependent_requests); - run_dependent_requests(s, &acb->l2meta); + qemu_iovec_init(&hd_qiov, qiov->niov); - if (ret < 0) { - return ret; - } + s->cluster_cache_offset = -1; /* disable compressed cache */ - acb->remaining_sectors -= acb->cur_nr_sectors; - acb->sector_num += acb->cur_nr_sectors; - acb->bytes_done += acb->cur_nr_sectors * 512; + qemu_co_mutex_lock(&s->lock); - if (acb->remaining_sectors == 0) { - /* request completed */ - return 0; - } + while (remaining_sectors != 0) { - index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); - n_end = index_in_cluster + acb->remaining_sectors; - if (s->crypt_method && - n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) - n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; + index_in_cluster = sector_num & (s->cluster_sectors - 1); + n_end = index_in_cluster + remaining_sectors; + if (s->crypt_method && + n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) { + n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; + } - ret = qcow2_alloc_cluster_offset(bs, acb->sector_num << 9, - index_in_cluster, n_end, &acb->cur_nr_sectors, &acb->l2meta); - if (ret < 0) { - return ret; - } + ret = qcow2_alloc_cluster_offset(bs, sector_num << 9, + index_in_cluster, n_end, &cur_nr_sectors, &l2meta); + if (ret < 0) { + goto fail; + } - acb->cluster_offset = acb->l2meta.cluster_offset; - assert((acb->cluster_offset & 511) == 0); + cluster_offset = l2meta.cluster_offset; + assert((cluster_offset & 511) == 0); - qemu_iovec_reset(&acb->hd_qiov); - qemu_iovec_copy(&acb->hd_qiov, acb->qiov, acb->bytes_done, - acb->cur_nr_sectors * 512); + qemu_iovec_reset(&hd_qiov); + qemu_iovec_copy(&hd_qiov, qiov, bytes_done, + cur_nr_sectors * 512); - if (s->crypt_method) { - if (!acb->cluster_data) { - acb->cluster_data = g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * - s->cluster_size); - } + if (s->crypt_method) { + if (!cluster_data) { + cluster_data = g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * + s->cluster_size); + } - assert(acb->hd_qiov.size <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); - qemu_iovec_to_buffer(&acb->hd_qiov, acb->cluster_data); + assert(hd_qiov.size <= + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); + qemu_iovec_to_buffer(&hd_qiov, cluster_data); - qcow2_encrypt_sectors(s, acb->sector_num, acb->cluster_data, - acb->cluster_data, acb->cur_nr_sectors, 1, &s->aes_encrypt_key); + qcow2_encrypt_sectors(s, sector_num, cluster_data, + cluster_data, cur_nr_sectors, 1, &s->aes_encrypt_key); - qemu_iovec_reset(&acb->hd_qiov); - qemu_iovec_add(&acb->hd_qiov, acb->cluster_data, - acb->cur_nr_sectors * 512); - } + qemu_iovec_reset(&hd_qiov); + qemu_iovec_add(&hd_qiov, cluster_data, + cur_nr_sectors * 512); + } - BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); - qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_writev(bs->file, - (acb->cluster_offset >> 9) + index_in_cluster, - acb->cur_nr_sectors, &acb->hd_qiov); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - return ret; - } + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); + qemu_co_mutex_unlock(&s->lock); + ret = bdrv_co_writev(bs->file, + (cluster_offset >> 9) + index_in_cluster, + cur_nr_sectors, &hd_qiov); + qemu_co_mutex_lock(&s->lock); + if (ret < 0) { + goto fail; + } - return 1; -} + ret = qcow2_alloc_cluster_link_l2(bs, &l2meta); -static int qcow2_co_writev(BlockDriverState *bs, - int64_t sector_num, - int nb_sectors, - QEMUIOVector *qiov) -{ - BDRVQcowState *s = bs->opaque; - QCowAIOCB *acb; - int ret; + run_dependent_requests(s, &l2meta); - acb = qcow2_aio_setup(bs, sector_num, qiov, nb_sectors, NULL, NULL, 1); - s->cluster_cache_offset = -1; /* disable compressed cache */ + if (ret < 0) { + goto fail; + } - qemu_co_mutex_lock(&s->lock); - do { - ret = qcow2_aio_write_cb(acb); - } while (ret > 0); + remaining_sectors -= cur_nr_sectors; + sector_num += cur_nr_sectors; + bytes_done += cur_nr_sectors * 512; + } + ret = 0; + +fail: qemu_co_mutex_unlock(&s->lock); - qemu_iovec_destroy(&acb->hd_qiov); - qemu_aio_release(acb); + qemu_iovec_destroy(&hd_qiov); + g_free(cluster_data); return ret; } diff --git a/block/qcow2.h b/block/qcow2.h index de23abe1a4..c8ca3bc574 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -189,8 +189,6 @@ void qcow2_free_clusters(BlockDriverState *bs, void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t cluster_offset, int nb_clusters); -void qcow2_create_refcount_update(QCowCreateState *s, int64_t offset, - int64_t size); int qcow2_update_snapshot_refcount(BlockDriverState *bs, int64_t l1_table_offset, int l1_size, int addend); diff --git a/block/sheepdog.c b/block/sheepdog.c index 57b6e1aad7..c1f6e07ec1 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -274,7 +274,7 @@ struct SheepdogAIOCB { int ret; enum AIOCBState aiocb_type; - QEMUBH *bh; + Coroutine *coroutine; void (*aio_done_func)(SheepdogAIOCB *); int canceled; @@ -295,6 +295,10 @@ typedef struct BDRVSheepdogState { char *port; int fd; + CoMutex lock; + Coroutine *co_send; + Coroutine *co_recv; + uint32_t aioreq_seq_num; QLIST_HEAD(outstanding_aio_head, AIOReq) outstanding_aio_head; } BDRVSheepdogState; @@ -346,19 +350,16 @@ static const char * sd_strerror(int err) /* * Sheepdog I/O handling: * - * 1. In the sd_aio_readv/writev, read/write requests are added to the - * QEMU Bottom Halves. - * - * 2. In sd_readv_writev_bh_cb, the callbacks of BHs, we send the I/O - * requests to the server and link the requests to the - * outstanding_list in the BDRVSheepdogState. we exits the - * function without waiting for receiving the response. + * 1. In sd_co_rw_vector, we send the I/O requests to the server and + * link the requests to the outstanding_list in the + * BDRVSheepdogState. The function exits without waiting for + * receiving the response. * - * 3. We receive the response in aio_read_response, the fd handler to + * 2. We receive the response in aio_read_response, the fd handler to * the sheepdog connection. If metadata update is needed, we send * the write request to the vdi object in sd_write_done, the write - * completion function. The AIOCB callback is not called until all - * the requests belonging to the AIOCB are finished. + * completion function. We switch back to sd_co_readv/writev after + * all the requests belonging to the AIOCB are finished. */ static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb, @@ -398,7 +399,7 @@ static inline int free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req) static void sd_finish_aiocb(SheepdogAIOCB *acb) { if (!acb->canceled) { - acb->common.cb(acb->common.opaque, acb->ret); + qemu_coroutine_enter(acb->coroutine, NULL); } qemu_aio_release(acb); } @@ -411,7 +412,8 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb) * Sheepdog cannot cancel the requests which are already sent to * the servers, so we just complete the request with -EIO here. */ - acb->common.cb(acb->common.opaque, -EIO); + acb->ret = -EIO; + qemu_coroutine_enter(acb->coroutine, NULL); acb->canceled = 1; } @@ -435,24 +437,12 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov, acb->aio_done_func = NULL; acb->canceled = 0; - acb->bh = NULL; + acb->coroutine = qemu_coroutine_self(); acb->ret = 0; QLIST_INIT(&acb->aioreq_head); return acb; } -static int sd_schedule_bh(QEMUBHFunc *cb, SheepdogAIOCB *acb) -{ - if (acb->bh) { - error_report("bug: %d %d", acb->aiocb_type, acb->aiocb_type); - return -EIO; - } - - acb->bh = qemu_bh_new(cb, acb); - qemu_bh_schedule(acb->bh); - return 0; -} - #ifdef _WIN32 struct msghdr { @@ -635,7 +625,13 @@ static int do_readv_writev(int sockfd, struct iovec *iov, int len, again: ret = do_send_recv(sockfd, iov, len, iov_offset, write); if (ret < 0) { - if (errno == EINTR || errno == EAGAIN) { + if (errno == EINTR) { + goto again; + } + if (errno == EAGAIN) { + if (qemu_in_coroutine()) { + qemu_coroutine_yield(); + } goto again; } error_report("failed to recv a rsp, %s", strerror(errno)); @@ -793,14 +789,14 @@ static void aio_read_response(void *opaque) unsigned long idx; if (QLIST_EMPTY(&s->outstanding_aio_head)) { - return; + goto out; } /* read a header */ ret = do_read(fd, &rsp, sizeof(rsp)); if (ret) { error_report("failed to get the header, %s", strerror(errno)); - return; + goto out; } /* find the right aio_req from the outstanding_aio list */ @@ -811,7 +807,7 @@ static void aio_read_response(void *opaque) } if (!aio_req) { error_report("cannot find aio_req %x", rsp.id); - return; + goto out; } acb = aio_req->aiocb; @@ -847,7 +843,7 @@ static void aio_read_response(void *opaque) aio_req->iov_offset); if (ret) { error_report("failed to get the data, %s", strerror(errno)); - return; + goto out; } break; } @@ -861,10 +857,30 @@ static void aio_read_response(void *opaque) if (!rest) { /* * We've finished all requests which belong to the AIOCB, so - * we can call the callback now. + * we can switch back to sd_co_readv/writev now. */ acb->aio_done_func(acb); } +out: + s->co_recv = NULL; +} + +static void co_read_response(void *opaque) +{ + BDRVSheepdogState *s = opaque; + + if (!s->co_recv) { + s->co_recv = qemu_coroutine_create(aio_read_response); + } + + qemu_coroutine_enter(s->co_recv, opaque); +} + +static void co_write_request(void *opaque) +{ + BDRVSheepdogState *s = opaque; + + qemu_coroutine_enter(s->co_send, NULL); } static int aio_flush_request(void *opaque) @@ -924,7 +940,7 @@ static int get_sheep_fd(BDRVSheepdogState *s) return -1; } - qemu_aio_set_fd_handler(fd, aio_read_response, NULL, aio_flush_request, + qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, NULL, s); return fd; } @@ -1091,6 +1107,10 @@ static int add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, hdr.id = aio_req->id; + 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, + aio_flush_request, NULL, s); set_cork(s->fd, 1); /* send a header */ @@ -1109,6 +1129,9 @@ static int add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, } set_cork(s->fd, 0); + qemu_aio_set_fd_handler(s->fd, co_read_response, NULL, + aio_flush_request, NULL, s); + qemu_co_mutex_unlock(&s->lock); return 0; } @@ -1225,6 +1248,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags) bs->total_sectors = s->inode.vdi_size / SECTOR_SIZE; strncpy(s->name, vdi, sizeof(s->name)); + qemu_co_mutex_init(&s->lock); g_free(buf); return 0; out: @@ -1491,7 +1515,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset) /* * This function is called after writing data objects. If we need to * update metadata, this sends a write request to the vdi object. - * Otherwise, this calls the AIOCB callback. + * Otherwise, this switches back to sd_co_readv/writev. */ static void sd_write_done(SheepdogAIOCB *acb) { @@ -1587,8 +1611,11 @@ out: * waiting the response. The responses are received in the * `aio_read_response' function which is called from the main loop as * a fd handler. + * + * Returns 1 when we need to wait a response, 0 when there is no sent + * request and -errno in error cases. */ -static void sd_readv_writev_bh_cb(void *p) +static int sd_co_rw_vector(void *p) { SheepdogAIOCB *acb = p; int ret = 0; @@ -1600,9 +1627,6 @@ static void sd_readv_writev_bh_cb(void *p) SheepdogInode *inode = &s->inode; AIOReq *aio_req; - qemu_bh_delete(acb->bh); - acb->bh = NULL; - if (acb->aiocb_type == AIOCB_WRITE_UDATA && s->is_snapshot) { /* * In the case we open the snapshot VDI, Sheepdog creates the @@ -1684,42 +1708,47 @@ static void sd_readv_writev_bh_cb(void *p) } out: if (QLIST_EMPTY(&acb->aioreq_head)) { - sd_finish_aiocb(acb); + return acb->ret; } + return 1; } -static BlockDriverAIOCB *sd_aio_writev(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static int sd_co_writev(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *qiov) { SheepdogAIOCB *acb; + int ret; if (bs->growable && sector_num + nb_sectors > bs->total_sectors) { /* TODO: shouldn't block here */ if (sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE) < 0) { - return NULL; + return -EIO; } bs->total_sectors = sector_num + nb_sectors; } - acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, cb, opaque); + acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, NULL, NULL); acb->aio_done_func = sd_write_done; acb->aiocb_type = AIOCB_WRITE_UDATA; - sd_schedule_bh(sd_readv_writev_bh_cb, acb); - return &acb->common; + ret = sd_co_rw_vector(acb); + if (ret <= 0) { + qemu_aio_release(acb); + return ret; + } + + qemu_coroutine_yield(); + + return acb->ret; } -static BlockDriverAIOCB *sd_aio_readv(BlockDriverState *bs, int64_t sector_num, - QEMUIOVector *qiov, int nb_sectors, - BlockDriverCompletionFunc *cb, - void *opaque) +static int sd_co_readv(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *qiov) { SheepdogAIOCB *acb; - int i; + int i, ret; - acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, cb, opaque); + acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, NULL, NULL); acb->aiocb_type = AIOCB_READ_UDATA; acb->aio_done_func = sd_finish_aiocb; @@ -1731,8 +1760,15 @@ static BlockDriverAIOCB *sd_aio_readv(BlockDriverState *bs, int64_t sector_num, memset(qiov->iov[i].iov_base, 0, qiov->iov[i].iov_len); } - sd_schedule_bh(sd_readv_writev_bh_cb, acb); - return &acb->common; + ret = sd_co_rw_vector(acb); + if (ret <= 0) { + qemu_aio_release(acb); + return ret; + } + + qemu_coroutine_yield(); + + return acb->ret; } static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) @@ -2062,8 +2098,8 @@ BlockDriver bdrv_sheepdog = { .bdrv_getlength = sd_getlength, .bdrv_truncate = sd_truncate, - .bdrv_aio_readv = sd_aio_readv, - .bdrv_aio_writev = sd_aio_writev, + .bdrv_co_readv = sd_co_readv, + .bdrv_co_writev = sd_co_writev, .bdrv_snapshot_create = sd_snapshot_create, .bdrv_snapshot_goto = sd_snapshot_goto, diff --git a/block/vmdk.c b/block/vmdk.c index 8da87acef0..5f673e9e25 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -56,7 +56,7 @@ typedef struct { int64_t grain_offset; char filler[1]; char check_bytes[4]; -} __attribute__((packed)) VMDK4Header; +} QEMU_PACKED VMDK4Header; #define L2_CACHE_SIZE 16 diff --git a/block/vvfat.c b/block/vvfat.c index d6a07efcc9..187ac96f25 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -200,7 +200,7 @@ static int array_index(array_t* array, void* pointer) } /* These structures are used to fake a disk and the VFAT filesystem. - * For this reason we need to use __attribute__((packed)). */ + * For this reason we need to use QEMU_PACKED. */ typedef struct bootsector_t { uint8_t jump[3]; @@ -224,7 +224,7 @@ typedef struct bootsector_t { uint8_t signature; uint32_t id; uint8_t volume_label[11]; - } __attribute__((packed)) fat16; + } QEMU_PACKED fat16; struct { uint32_t sectors_per_fat; uint16_t flags; @@ -233,12 +233,12 @@ typedef struct bootsector_t { uint16_t info_sector; uint16_t backup_boot_sector; uint16_t ignored; - } __attribute__((packed)) fat32; + } QEMU_PACKED fat32; } u; uint8_t fat_type[8]; uint8_t ignored[0x1c0]; uint8_t magic[2]; -} __attribute__((packed)) bootsector_t; +} QEMU_PACKED bootsector_t; typedef struct { uint8_t head; @@ -253,7 +253,7 @@ typedef struct partition_t { mbr_chs_t end_CHS; uint32_t start_sector_long; uint32_t length_sector_long; -} __attribute__((packed)) partition_t; +} QEMU_PACKED partition_t; typedef struct mbr_t { uint8_t ignored[0x1b8]; @@ -261,7 +261,7 @@ typedef struct mbr_t { uint8_t ignored2[2]; partition_t partition[4]; uint8_t magic[2]; -} __attribute__((packed)) mbr_t; +} QEMU_PACKED mbr_t; typedef struct direntry_t { uint8_t name[8]; @@ -276,7 +276,7 @@ typedef struct direntry_t { uint16_t mdate; uint16_t begin; uint32_t size; -} __attribute__((packed)) direntry_t; +} QEMU_PACKED direntry_t; /* this structure are used to transparently access the files */ diff --git a/block_int.h b/block_int.h index f6d02b38a7..8a72b804b2 100644 --- a/block_int.h +++ b/block_int.h @@ -28,6 +28,7 @@ #include "qemu-option.h" #include "qemu-queue.h" #include "qemu-coroutine.h" +#include "qemu-timer.h" #define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_COMPAT6 4 @@ -184,10 +185,9 @@ struct BlockDriverState { void *sync_aiocb; /* I/O stats (display with "info blockstats"). */ - uint64_t rd_bytes; - uint64_t wr_bytes; - uint64_t rd_ops; - uint64_t wr_ops; + uint64_t nr_bytes[BDRV_MAX_IOTYPE]; + uint64_t nr_ops[BDRV_MAX_IOTYPE]; + uint64_t total_time_ns[BDRV_MAX_IOTYPE]; uint64_t wr_highest_sector; /* Whether the disk can expand beyond total_sectors */ diff --git a/blockdev.c b/blockdev.c index d272659ab2..2602591bf6 100644 --- a/blockdev.c +++ b/blockdev.c @@ -321,18 +321,9 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) } if ((buf = qemu_opt_get(opts, "cache")) != NULL) { - if (!strcmp(buf, "off") || !strcmp(buf, "none")) { - bdrv_flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; - } else if (!strcmp(buf, "writeback")) { - bdrv_flags |= BDRV_O_CACHE_WB; - } else if (!strcmp(buf, "unsafe")) { - bdrv_flags |= BDRV_O_CACHE_WB; - bdrv_flags |= BDRV_O_NO_FLUSH; - } else if (!strcmp(buf, "writethrough")) { - /* this is the default */ - } else { - error_report("invalid cache option"); - return NULL; + if (bdrv_parse_cache_flags(buf, &bdrv_flags) != 0) { + error_report("invalid cache option"); + return NULL; } } diff --git a/compiler.h b/compiler.h index 9af5dc6c91..a2d5959e4b 100644 --- a/compiler.h +++ b/compiler.h @@ -12,6 +12,12 @@ #define QEMU_WARN_UNUSED_RESULT #endif +#if defined(_WIN32) +# define QEMU_PACKED __attribute__((gcc_struct, packed)) +#else +# define QEMU_PACKED __attribute__((packed)) +#endif + #define QEMU_BUILD_BUG_ON(x) \ typedef char qemu_build_bug_on__##__LINE__[(x)?-1:1]; @@ -165,7 +165,6 @@ darwin_user="no" bsd_user="no" guest_base="" uname_release="" -io_thread="no" mixemu="no" aix="no" blobs="yes" @@ -413,6 +412,7 @@ SunOS) make="${MAKE-gmake}" install="${INSTALL-ginstall}" ld="gld" + smbd="${SMBD-/usr/sfw/sbin/smbd}" needs_libsunmath="no" solarisrev=`uname -r | cut -f2 -d.` # have to select again, because `uname -m` returns i86pc @@ -481,6 +481,7 @@ fi : ${make=${MAKE-make}} : ${install=${INSTALL-install}} : ${python=${PYTHON-python}} +: ${smbd=${SMBD-/usr/sbin/smbd}} if test "$mingw32" = "yes" ; then EXESUF=".exe" @@ -525,6 +526,8 @@ for opt do ;; --python=*) python="$optarg" ;; + --smbd=*) smbd="$optarg" + ;; --extra-cflags=*) ;; --extra-ldflags=*) @@ -723,8 +726,6 @@ for opt do ;; --enable-attr) attr="yes" ;; - --enable-io-thread) io_thread="yes" - ;; --disable-blobs) blobs="no" ;; --with-pkgversion=*) pkgversion=" ($optarg)" @@ -941,6 +942,7 @@ echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" echo " --make=MAKE use specified make [$make]" echo " --install=INSTALL use specified install [$install]" echo " --python=PYTHON use specified python [$python]" +echo " --smbd=SMBD use specified smbd [$smbd]" echo " --static enable static build [$static]" echo " --mandir=PATH install man pages in PATH" echo " --datadir=PATH install firmware in PATH" @@ -2158,12 +2160,6 @@ EOF if compile_prog "" "" ; then signalfd=yes -elif test "$kvm" = "yes" -a "$io_thread" != "yes"; then - echo - echo "ERROR: Host kernel lacks signalfd() support," - echo "but KVM depends on it when the IO thread is disabled." - echo - exit 1 fi # check if eventfd is supported @@ -2666,6 +2662,9 @@ echo "LDFLAGS $LDFLAGS" echo "make $make" echo "install $install" echo "python $python" +if test "$slirp" = "yes" ; then + echo "smbd $smbd" +fi echo "host CPU $cpu" echo "host big endian $bigendian" echo "target list $target_list" @@ -2710,7 +2709,6 @@ echo "NPTL support $nptl" echo "GUEST_BASE $guest_base" echo "PIE user targets $user_pie" echo "vde support $vde" -echo "IO thread $io_thread" echo "Linux AIO support $linux_aio" echo "ATTR/XATTR support $attr" echo "Install blobs $blobs" @@ -2825,6 +2823,7 @@ if test "$profiler" = "yes" ; then fi if test "$slirp" = "yes" ; then echo "CONFIG_SLIRP=y" >> $config_host_mak + echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak QEMU_INCLUDES="-I\$(SRC_PATH)/slirp $QEMU_INCLUDES" fi if test "$vde" = "yes" ; then @@ -2968,9 +2967,6 @@ if test "$xen" = "yes" ; then echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak fi -if test "$io_thread" = "yes" ; then - echo "CONFIG_IOTHREAD=y" >> $config_host_mak -fi if test "$linux_aio" = "yes" ; then echo "CONFIG_LINUX_AIO=y" >> $config_host_mak fi @@ -3064,26 +3060,43 @@ bsd) ;; esac +# use default implementation for tracing backend-specific routines +trace_default=yes echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak -if test "$trace_backend" = "simple"; then - echo "CONFIG_SIMPLE_TRACE=y" >> $config_host_mak +if test "$trace_backend" = "nop"; then + echo "CONFIG_TRACE_NOP=y" >> $config_host_mak fi -# Set the appropriate trace file. if test "$trace_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" = "dtrace" -a "$trace_backend_stap" = "yes" ; then - echo "CONFIG_SYSTEMTAP_TRACE=y" >> $config_host_mak +if test "$trace_backend" = "stderr"; then + echo "CONFIG_TRACE_STDERR=y" >> $config_host_mak + trace_default=no +fi +if test "$trace_backend" = "ust"; then + echo "CONFIG_TRACE_UST=y" >> $config_host_mak +fi +if test "$trace_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 echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak +if test "$trace_default" = "yes"; then + echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak +fi echo "TOOLS=$tools" >> $config_host_mak echo "ROMS=$roms" >> $config_host_mak echo "MAKE=$make" >> $config_host_mak echo "INSTALL=$install" >> $config_host_mak -echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak -echo "INSTALL_DATA=$install -m0644 -p" >> $config_host_mak -echo "INSTALL_PROG=$install -m0755 -p" >> $config_host_mak +echo "INSTALL_DIR=$install -d -m 0755" >> $config_host_mak +echo "INSTALL_DATA=$install -c -m 0644" >> $config_host_mak +echo "INSTALL_PROG=$install -c -m 0755" >> $config_host_mak echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak @@ -3600,7 +3613,7 @@ DIRS="$DIRS pc-bios/spapr-rtas" DIRS="$DIRS roms/seabios roms/vgabios" DIRS="$DIRS fsdev ui" DIRS="$DIRS qapi" -DIRS="$DIRS qga" +DIRS="$DIRS qga trace" FILES="Makefile tests/Makefile" FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit" FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps" @@ -173,12 +173,9 @@ static void cpu_handle_guest_debug(CPUState *env) { gdb_set_stop_cpu(env); qemu_system_debug_request(); -#ifdef CONFIG_IOTHREAD env->stopped = 1; -#endif } -#ifdef CONFIG_IOTHREAD static void cpu_signal(int sig) { if (cpu_single_env) { @@ -186,7 +183,6 @@ static void cpu_signal(int sig) } exit_request = 1; } -#endif #ifdef CONFIG_LINUX static void sigbus_reraise(void) @@ -262,12 +258,6 @@ static void qemu_kvm_eat_signals(CPUState *env) exit(1); } } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS)); - -#ifndef CONFIG_IOTHREAD - if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) { - qemu_notify_event(); - } -#endif } #else /* !CONFIG_LINUX */ @@ -390,7 +380,6 @@ static int qemu_signal_init(void) int sigfd; sigset_t set; -#ifdef CONFIG_IOTHREAD /* SIGUSR2 used by posix-aio-compat.c */ sigemptyset(&set); sigaddset(&set, SIGUSR2); @@ -409,18 +398,6 @@ static int qemu_signal_init(void) sigaddset(&set, SIGIO); sigaddset(&set, SIGALRM); sigaddset(&set, SIGBUS); -#else - sigemptyset(&set); - sigaddset(&set, SIGBUS); - if (kvm_enabled()) { - /* - * We need to process timer signals synchronously to avoid a race - * between exit_request check and KVM vcpu entry. - */ - sigaddset(&set, SIGIO); - sigaddset(&set, SIGALRM); - } -#endif pthread_sigmask(SIG_BLOCK, &set, NULL); sigfd = qemu_signalfd(&set); @@ -447,7 +424,6 @@ static void qemu_kvm_init_cpu_signals(CPUState *env) sigact.sa_handler = dummy_signal; sigaction(SIG_IPI, &sigact, NULL); -#ifdef CONFIG_IOTHREAD pthread_sigmask(SIG_BLOCK, NULL, &set); sigdelset(&set, SIG_IPI); sigdelset(&set, SIGBUS); @@ -456,17 +432,7 @@ static void qemu_kvm_init_cpu_signals(CPUState *env) fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r)); exit(1); } -#else - sigemptyset(&set); - sigaddset(&set, SIG_IPI); - sigaddset(&set, SIGIO); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_BLOCK, &set, NULL); - pthread_sigmask(SIG_BLOCK, NULL, &set); - sigdelset(&set, SIGIO); - sigdelset(&set, SIGALRM); -#endif sigdelset(&set, SIG_IPI); sigdelset(&set, SIGBUS); r = kvm_set_signal_mask(env, &set); @@ -478,7 +444,6 @@ static void qemu_kvm_init_cpu_signals(CPUState *env) static void qemu_tcg_init_cpu_signals(void) { -#ifdef CONFIG_IOTHREAD sigset_t set; struct sigaction sigact; @@ -489,7 +454,6 @@ static void qemu_tcg_init_cpu_signals(void) sigemptyset(&set); sigaddset(&set, SIG_IPI); pthread_sigmask(SIG_UNBLOCK, &set, NULL); -#endif } #else /* _WIN32 */ @@ -535,106 +499,6 @@ static void qemu_tcg_init_cpu_signals(void) } #endif /* _WIN32 */ -#ifndef CONFIG_IOTHREAD -int qemu_init_main_loop(void) -{ - int ret; - - ret = qemu_signal_init(); - if (ret) { - return ret; - } - - qemu_init_sigbus(); - - return qemu_event_init(); -} - -void qemu_main_loop_start(void) -{ -} - -void qemu_init_vcpu(void *_env) -{ - CPUState *env = _env; - int r; - - env->nr_cores = smp_cores; - env->nr_threads = smp_threads; - - if (kvm_enabled()) { - r = kvm_init_vcpu(env); - if (r < 0) { - fprintf(stderr, "kvm_init_vcpu failed: %s\n", strerror(-r)); - exit(1); - } - qemu_kvm_init_cpu_signals(env); - } else { - qemu_tcg_init_cpu_signals(); - } -} - -int qemu_cpu_is_self(void *env) -{ - return 1; -} - -void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) -{ - func(data); -} - -void resume_all_vcpus(void) -{ -} - -void pause_all_vcpus(void) -{ -} - -void qemu_cpu_kick(void *env) -{ -} - -void qemu_cpu_kick_self(void) -{ -#ifndef _WIN32 - assert(cpu_single_env); - - raise(SIG_IPI); -#else - abort(); -#endif -} - -void qemu_notify_event(void) -{ - CPUState *env = cpu_single_env; - - qemu_event_increment (); - if (env) { - cpu_exit(env); - } - if (next_cpu && env != next_cpu) { - cpu_exit(next_cpu); - } - exit_request = 1; -} - -void qemu_mutex_lock_iothread(void) {} -void qemu_mutex_unlock_iothread(void) {} - -void cpu_stop_current(void) -{ -} - -void vm_stop(int reason) -{ - do_vm_stop(reason); -} - -#else /* CONFIG_IOTHREAD */ - QemuMutex qemu_global_mutex; static QemuCond qemu_io_proceeded_cond; static bool iothread_requesting_mutex; @@ -1028,8 +892,6 @@ void vm_stop(int reason) do_vm_stop(reason); } -#endif - static int tcg_cpu_exec(CPUState *env) { int ret; @@ -1084,11 +946,6 @@ bool cpu_exec_all(void) qemu_clock_enable(vm_clock, (env->singlestep_enabled & SSTEP_NOTIMER) == 0); -#ifndef CONFIG_IOTHREAD - if (qemu_alarm_pending()) { - break; - } -#endif if (cpu_can_run(env)) { if (kvm_enabled()) { r = kvm_cpu_exec(env); diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index b7befb5e48..f345866f57 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -229,7 +229,7 @@ in the schema. The following files are generated: $(prefix)qmp-marshal.c: command marshal/dispatch functions for each QMP command defined in the schema. Functions generated by qapi-visit.py are used to - convert QObjects recieved from the wire into + convert QObjects received from the wire into function parameters, and uses the same visitor functions to convert native C return values to QObjects from transmission back diff --git a/docs/tracing.txt b/docs/tracing.txt index c99a0f27cf..4b27ab0c2a 100644 --- a/docs/tracing.txt +++ b/docs/tracing.txt @@ -12,13 +12,14 @@ for debugging, profiling, and observing execution. ./configure --trace-backend=simple make -2. Enable trace events you are interested in: +2. Create a file with the events you want to trace: - $EDITOR trace-events # remove "disable" from events you want + echo bdrv_aio_readv > /tmp/events + echo bdrv_aio_writev >> /tmp/events 3. Run the virtual machine to produce a trace file: - qemu ... # your normal QEMU invocation + qemu -trace events=/tmp/events ... # your normal QEMU invocation 4. Pretty-print the binary trace file: @@ -38,7 +39,7 @@ generate code for the trace events. Trace events are invoked directly from source code like this: #include "trace.h" /* needed for trace event prototype */ - + void *qemu_malloc(size_t size) { void *ptr; @@ -103,10 +104,45 @@ portability macros, ensure they are preceded and followed by double quotes: 4. Name trace events after their function. If there are multiple trace events in one function, append a unique distinguisher at the end of the name. -5. Declare trace events with the "disable" keyword. Some trace events can - produce a lot of output and users are typically only interested in a subset - of trace events. Marking trace events disabled by default saves the user - from having to manually disable noisy trace events. +5. If specific trace events are going to be called a huge number of times, this + might have a noticeable performance impact even when the trace events are + programmatically disabled. In this case you should declare the trace event + with the "disable" property, which will effectively disable it at compile + time (using the "nop" backend). + +== Generic interface and monitor commands == + +You can programmatically query and control the dynamic state of trace events +through a backend-agnostic interface: + +* trace_print_events + +* trace_event_set_state + Enables or disables trace events at runtime inside QEMU. + The function returns "true" if the state of the event has been successfully + changed, or "false" otherwise: + + #include "trace/control.h" + + trace_event_set_state("virtio_irq", true); /* enable */ + [...] + trace_event_set_state("virtio_irq", false); /* disable */ + +Note that some of the backends do not provide an implementation for this +interface, in which case QEMU will just print a warning. + +This functionality is also provided through monitor commands: + +* info trace-events + View available trace events and their state. State 1 means enabled, state 0 + means disabled. + +* trace-event NAME on|off + Enable/disable a given trace event. + +The "-trace events=<file>" command line argument can be used to enable the +events listed in <file> from the very beginning of the program. This file must +contain one event name per line. == Trace backends == @@ -131,6 +167,9 @@ The "nop" backend generates empty trace event functions so that the compiler can optimize out trace events completely. This is the default and imposes no performance penalty. +Note that regardless of the selected trace backend, events with the "disable" +property will be generated with the "nop" backend. + === Stderr === The "stderr" backend sends trace events directly to standard error. This @@ -157,27 +196,9 @@ unless you have specific needs for more advanced backends. flushed and emptied. This means the 'info trace' will display few or no entries if the buffer has just been flushed. -* info trace-events - View available trace events and their state. State 1 means enabled, state 0 - means disabled. - -* trace-event NAME on|off - Enable/disable a given trace event. - * trace-file on|off|flush|set <path> Enable/disable/flush the trace file or set the trace file name. -==== Enabling/disabling trace events programmatically ==== - -The st_change_trace_event_state() function can be used to enable or disable trace -events at runtime inside QEMU: - - #include "trace.h" - - st_change_trace_event_state("virtio_irq", true); /* enable */ - [...] - st_change_trace_event_state("virtio_irq", false); /* disable */ - ==== Analyzing trace files ==== The "simple" backend produces binary trace files that can be formatted with the diff --git a/dyngen-exec.h b/dyngen-exec.h index cc1e4fb09d..8beb7f3344 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -19,15 +19,6 @@ #if !defined(__DYNGEN_EXEC_H__) #define __DYNGEN_EXEC_H__ -#include "qemu-common.h" - -#ifdef __OpenBSD__ -#include <sys/types.h> -#endif - -/* XXX: This may be wrong for 64-bit ILP32 hosts. */ -typedef void * host_reg_t; - #if defined(__i386__) #define AREG0 "ebp" #elif defined(__x86_64__) @@ -66,11 +57,6 @@ typedef void * host_reg_t; register CPUState *env asm(AREG0); -#define xglue(x, y) x ## y -#define glue(x, y) xglue(x, y) -#define stringify(s) tostring(s) -#define tostring(s) #s - /* The return address may point to the start of the next instruction. Subtracting one gets us the call instruction itself. */ #if defined(__s390__) && !defined(__s390x__) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 7951a0e869..2b2008502c 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -5965,20 +5965,20 @@ int float128_unordered_quiet( float128 a, float128 b STATUS_PARAM ) } /* misc functions */ -float32 uint32_to_float32( unsigned int a STATUS_PARAM ) +float32 uint32_to_float32( uint32 a STATUS_PARAM ) { return int64_to_float32(a STATUS_VAR); } -float64 uint32_to_float64( unsigned int a STATUS_PARAM ) +float64 uint32_to_float64( uint32 a STATUS_PARAM ) { return int64_to_float64(a STATUS_VAR); } -unsigned int float32_to_uint32( float32 a STATUS_PARAM ) +uint32 float32_to_uint32( float32 a STATUS_PARAM ) { int64_t v; - unsigned int res; + uint32 res; v = float32_to_int64(a STATUS_VAR); if (v < 0) { @@ -5993,10 +5993,10 @@ unsigned int float32_to_uint32( float32 a STATUS_PARAM ) return res; } -unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM ) +uint32 float32_to_uint32_round_to_zero( float32 a STATUS_PARAM ) { int64_t v; - unsigned int res; + uint32 res; v = float32_to_int64_round_to_zero(a STATUS_VAR); if (v < 0) { @@ -6011,10 +6011,10 @@ unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM ) return res; } -unsigned int float32_to_uint16_round_to_zero( float32 a STATUS_PARAM ) +uint16 float32_to_uint16_round_to_zero( float32 a STATUS_PARAM ) { int64_t v; - unsigned int res; + uint16 res; v = float32_to_int64_round_to_zero(a STATUS_VAR); if (v < 0) { @@ -6029,10 +6029,10 @@ unsigned int float32_to_uint16_round_to_zero( float32 a STATUS_PARAM ) return res; } -unsigned int float64_to_uint32( float64 a STATUS_PARAM ) +uint32 float64_to_uint32( float64 a STATUS_PARAM ) { int64_t v; - unsigned int res; + uint32 res; v = float64_to_int64(a STATUS_VAR); if (v < 0) { @@ -6047,10 +6047,10 @@ unsigned int float64_to_uint32( float64 a STATUS_PARAM ) return res; } -unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM ) +uint32 float64_to_uint32_round_to_zero( float64 a STATUS_PARAM ) { int64_t v; - unsigned int res; + uint32 res; v = float64_to_int64_round_to_zero(a STATUS_VAR); if (v < 0) { @@ -6065,10 +6065,10 @@ unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM ) return res; } -unsigned int float64_to_uint16_round_to_zero( float64 a STATUS_PARAM ) +uint16 float64_to_uint16_round_to_zero( float64 a STATUS_PARAM ) { int64_t v; - unsigned int res; + uint16 res; v = float64_to_int64_round_to_zero(a STATUS_VAR); if (v < 0) { diff --git a/fpu/softfloat.h b/fpu/softfloat.h index 3bb7d8fa6d..618ddee569 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -216,8 +216,8 @@ void float_raise( int8 flags STATUS_PARAM); *----------------------------------------------------------------------------*/ float32 int32_to_float32( int32 STATUS_PARAM ); float64 int32_to_float64( int32 STATUS_PARAM ); -float32 uint32_to_float32( unsigned int STATUS_PARAM ); -float64 uint32_to_float64( unsigned int STATUS_PARAM ); +float32 uint32_to_float32( uint32 STATUS_PARAM ); +float64 uint32_to_float64( uint32 STATUS_PARAM ); floatx80 int32_to_floatx80( int32 STATUS_PARAM ); float128 int32_to_float128( int32 STATUS_PARAM ); float32 int64_to_float32( int64 STATUS_PARAM ); @@ -249,7 +249,7 @@ extern const float16 float16_default_nan; | Software IEC/IEEE single-precision conversion routines. *----------------------------------------------------------------------------*/ int16 float32_to_int16_round_to_zero( float32 STATUS_PARAM ); -unsigned int float32_to_uint16_round_to_zero( float32 STATUS_PARAM ); +uint16 float32_to_uint16_round_to_zero( float32 STATUS_PARAM ); int32 float32_to_int32( float32 STATUS_PARAM ); int32 float32_to_int32_round_to_zero( float32 STATUS_PARAM ); uint32 float32_to_uint32( float32 STATUS_PARAM ); @@ -352,7 +352,7 @@ extern const float32 float32_default_nan; | Software IEC/IEEE double-precision conversion routines. *----------------------------------------------------------------------------*/ int16 float64_to_int16_round_to_zero( float64 STATUS_PARAM ); -unsigned int float64_to_uint16_round_to_zero( float64 STATUS_PARAM ); +uint16 float64_to_uint16_round_to_zero( float64 STATUS_PARAM ); int32 float64_to_int32( float64 STATUS_PARAM ); int32 float64_to_int32_round_to_zero( float64 STATUS_PARAM ); uint32 float64_to_uint32( float64 STATUS_PARAM ); diff --git a/hmp-commands.hx b/hmp-commands.hx index 0ccfb2867f..9e1cca8e3d 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -180,13 +180,12 @@ STEXI Output logs to @var{filename}. ETEXI -#ifdef CONFIG_SIMPLE_TRACE { .name = "trace-event", .args_type = "name:s,option:b", .params = "name on|off", .help = "changes status of a specific trace event", - .mhandler.cmd = do_change_trace_event_state, + .mhandler.cmd = do_trace_event_set_state, }, STEXI @@ -195,6 +194,7 @@ STEXI changes status of a trace event ETEXI +#if defined(CONFIG_SIMPLE_TRACE) { .name = "trace-file", .args_type = "op:s?,arg:F?", @@ -1354,14 +1354,17 @@ show roms @end table ETEXI -#ifdef CONFIG_SIMPLE_TRACE +#ifdef CONFIG_TRACE_SIMPLE STEXI @item info trace show contents of trace buffer +ETEXI +#endif + +STEXI @item info trace-events show available trace events and their state ETEXI -#endif STEXI @end table @@ -75,36 +75,34 @@ SECTIONS .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } .PARISC.unwind : { *(.PARISC.unwind) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN(0x10000) + (. & (0x10000 - 1)); /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 28fe1ff3a3..9d1b508e16 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -327,7 +327,7 @@ struct virtio_9p_config uint16_t tag_len; /* Variable size tag name */ uint8_t tag[0]; -} __attribute__((packed)); +} QEMU_PACKED; typedef struct V9fsMkState { V9fsPDU *pdu; @@ -32,7 +32,7 @@ struct acpi_table_header { uint32_t oem_revision; /* OEM revision number */ char asl_compiler_id[4]; /* ASL compiler vendor ID */ uint32_t asl_compiler_revision; /* ASL compiler revision number */ -} __attribute__((packed)); +} QEMU_PACKED; #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header) #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t) /* size of the extra prefix */ diff --git a/hw/an5206.c b/hw/an5206.c index 481ae60449..04ca420a90 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -12,7 +12,6 @@ #include "boards.h" #include "loader.h" #include "elf.h" -#include "exec-memory.h" #define KERNEL_LOAD_ADDR 0x10000 #define AN5206_MBAR_ADDR 0x10000000 @@ -38,9 +37,6 @@ static void an5206_init(ram_addr_t ram_size, int kernel_size; uint64_t elf_entry; target_phys_addr_t entry; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); - MemoryRegion *sram = g_new(MemoryRegion, 1); if (!cpu_model) cpu_model = "m5206"; @@ -56,12 +52,12 @@ static void an5206_init(ram_addr_t ram_size, env->rambar0 = AN5206_RAMBAR_ADDR | 1; /* DRAM at address zero */ - memory_region_init_ram(ram, NULL, "an5206.ram", ram_size); - memory_region_add_subregion(address_space_mem, 0, ram); + cpu_register_physical_memory(0, ram_size, + qemu_ram_alloc(NULL, "an5206.ram", ram_size) | IO_MEM_RAM); /* Internal SRAM. */ - memory_region_init_ram(sram, NULL, "an5206.sram", 512); - memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram); + cpu_register_physical_memory(AN5206_RAMBAR_ADDR, 512, + qemu_ram_alloc(NULL, "an5206.sram", 512) | IO_MEM_RAM); mcf5206_init(AN5206_MBAR_ADDR, env); diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 6ee2068128..c232946280 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -71,6 +71,7 @@ typedef struct APBState { PCIBus *bus; MemoryRegion apb_config; MemoryRegion pci_config; + MemoryRegion pci_mmio; MemoryRegion pci_ioport; uint32_t iommu[4]; uint32_t pci_control[16]; @@ -336,12 +337,14 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, sysbus_mmio_map(s, 2, special_base + 0x2000000ULL); d = FROM_SYSBUS(APBState, s); + memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); + memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); + d->bus = pci_register_bus(&d->busdev.qdev, "pci", - pci_apb_set_irq, pci_pbm_map_irq, d, - get_system_memory(), - get_system_io(), - 0, 32); - pci_bus_set_mem_base(d->bus, mem_base); + pci_apb_set_irq, pci_pbm_map_irq, d, + &d->pci_mmio, + get_system_io(), + 0, 32); for (i = 0; i < 32; i++) { sysbus_connect_irq(s, i, pic[i]); diff --git a/hw/arm-misc.h b/hw/arm-misc.h index af403a159a..f8a747289b 100644 --- a/hw/arm-misc.h +++ b/hw/arm-misc.h @@ -11,16 +11,13 @@ #ifndef ARM_MISC_H #define ARM_MISC_H 1 -#include "memory.h" - /* The CPU is also modeled as an interrupt controller. */ #define ARM_PIC_CPU_IRQ 0 #define ARM_PIC_CPU_FIQ 1 qemu_irq *arm_pic_init_cpu(CPUState *env); /* armv7m.c */ -qemu_irq *armv7m_init(MemoryRegion *address_space_mem, - int flash_size, int sram_size, +qemu_irq *armv7m_init(int flash_size, int sram_size, const char *kernel_filename, const char *cpu_model); /* arm_boot.c */ diff --git a/hw/armv7m.c b/hw/armv7m.c index 28d41b82a6..a932f16a44 100644 --- a/hw/armv7m.c +++ b/hw/armv7m.c @@ -156,8 +156,7 @@ static void armv7m_reset(void *opaque) flash_size and sram_size are in kb. Returns the NVIC array. */ -qemu_irq *armv7m_init(MemoryRegion *address_space_mem, - int flash_size, int sram_size, +qemu_irq *armv7m_init(int flash_size, int sram_size, const char *kernel_filename, const char *cpu_model) { CPUState *env; @@ -170,9 +169,6 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, uint64_t lowaddr; int i; int big_endian; - MemoryRegion *sram = g_new(MemoryRegion, 1); - MemoryRegion *flash = g_new(MemoryRegion, 1); - MemoryRegion *hack = g_new(MemoryRegion, 1); flash_size *= 1024; sram_size *= 1024; @@ -198,11 +194,12 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, #endif /* Flash programming is done via the SCU, so pretend it is ROM. */ - memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size); - memory_region_set_readonly(flash, true); - memory_region_add_subregion(address_space_mem, 0, flash); - memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size); - memory_region_add_subregion(address_space_mem, 0x20000000, sram); + cpu_register_physical_memory(0, flash_size, + qemu_ram_alloc(NULL, "armv7m.flash", + flash_size) | IO_MEM_ROM); + cpu_register_physical_memory(0x20000000, sram_size, + qemu_ram_alloc(NULL, "armv7m.sram", + sram_size) | IO_MEM_RAM); armv7m_bitband_init(); nvic = qdev_create(NULL, "armv7m_nvic"); @@ -235,8 +232,9 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, /* Hack to map an additional page of ram at the top of the address space. This stops qemu complaining about executing code outside RAM when returning from an exception. */ - memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000); - memory_region_add_subregion(address_space_mem, 0xfffff000, hack); + cpu_register_physical_memory(0xfffff000, 0x1000, + qemu_ram_alloc(NULL, "armv7m.hack", + 0x1000) | IO_MEM_RAM); qemu_register_reset(armv7m_reset, env); return pic; diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index 73eb39d43b..06200e257a 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -31,7 +31,6 @@ #include "elf.h" #include "cris-boot.h" #include "blockdev.h" -#include "exec-memory.h" #define D(x) #define DNAND(x) @@ -260,9 +259,8 @@ void axisdev88_init (ram_addr_t ram_size, int i; int nand_regs; int gpio_regs; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *phys_ram = g_new(MemoryRegion, 1); - MemoryRegion *phys_intmem = g_new(MemoryRegion, 1); + ram_addr_t phys_ram; + ram_addr_t phys_intmem; /* init CPUs */ if (cpu_model == NULL) { @@ -271,13 +269,15 @@ void axisdev88_init (ram_addr_t ram_size, env = cpu_init(cpu_model); /* allocate RAM */ - memory_region_init_ram(phys_ram, NULL, "axisdev88.ram", ram_size); - memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram); + phys_ram = qemu_ram_alloc(NULL, "axisdev88.ram", ram_size); + cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM); /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the internal memory. */ - memory_region_init_ram(phys_intmem, NULL, "axisdev88.chipram", INTMEM_SIZE); - memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem); + phys_intmem = qemu_ram_alloc(NULL, "axisdev88.chipram", INTMEM_SIZE); + cpu_register_physical_memory(0x38000000, INTMEM_SIZE, + phys_intmem | IO_MEM_RAM); + /* Attach a NAND flash to CS1. */ nand = drive_get(IF_MTD, 0, 0); @@ -26,7 +26,7 @@ /* BD Address */ typedef struct { uint8_t b[6]; -} __attribute__((packed)) bdaddr_t; +} QEMU_PACKED bdaddr_t; #define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}}) #define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}) @@ -446,13 +446,13 @@ typedef struct { uint8_t lap[3]; uint8_t length; /* 1.28s units */ uint8_t num_rsp; -} __attribute__ ((packed)) inquiry_cp; +} QEMU_PACKED inquiry_cp; #define INQUIRY_CP_SIZE 5 typedef struct { uint8_t status; bdaddr_t bdaddr; -} __attribute__ ((packed)) status_bdaddr_rp; +} QEMU_PACKED status_bdaddr_rp; #define STATUS_BDADDR_RP_SIZE 7 #define OCF_INQUIRY_CANCEL 0x0002 @@ -464,7 +464,7 @@ typedef struct { uint8_t lap[3]; uint8_t length; /* 1.28s units */ uint8_t num_rsp; -} __attribute__ ((packed)) periodic_inquiry_cp; +} QEMU_PACKED periodic_inquiry_cp; #define PERIODIC_INQUIRY_CP_SIZE 9 #define OCF_EXIT_PERIODIC_INQUIRY 0x0004 @@ -477,55 +477,55 @@ typedef struct { uint8_t pscan_mode; uint16_t clock_offset; uint8_t role_switch; -} __attribute__ ((packed)) create_conn_cp; +} QEMU_PACKED create_conn_cp; #define CREATE_CONN_CP_SIZE 13 #define OCF_DISCONNECT 0x0006 typedef struct { uint16_t handle; uint8_t reason; -} __attribute__ ((packed)) disconnect_cp; +} QEMU_PACKED disconnect_cp; #define DISCONNECT_CP_SIZE 3 #define OCF_ADD_SCO 0x0007 typedef struct { uint16_t handle; uint16_t pkt_type; -} __attribute__ ((packed)) add_sco_cp; +} QEMU_PACKED add_sco_cp; #define ADD_SCO_CP_SIZE 4 #define OCF_CREATE_CONN_CANCEL 0x0008 typedef struct { uint8_t status; bdaddr_t bdaddr; -} __attribute__ ((packed)) create_conn_cancel_cp; +} QEMU_PACKED create_conn_cancel_cp; #define CREATE_CONN_CANCEL_CP_SIZE 6 typedef struct { uint8_t status; bdaddr_t bdaddr; -} __attribute__ ((packed)) create_conn_cancel_rp; +} QEMU_PACKED create_conn_cancel_rp; #define CREATE_CONN_CANCEL_RP_SIZE 7 #define OCF_ACCEPT_CONN_REQ 0x0009 typedef struct { bdaddr_t bdaddr; uint8_t role; -} __attribute__ ((packed)) accept_conn_req_cp; +} QEMU_PACKED accept_conn_req_cp; #define ACCEPT_CONN_REQ_CP_SIZE 7 #define OCF_REJECT_CONN_REQ 0x000A typedef struct { bdaddr_t bdaddr; uint8_t reason; -} __attribute__ ((packed)) reject_conn_req_cp; +} QEMU_PACKED reject_conn_req_cp; #define REJECT_CONN_REQ_CP_SIZE 7 #define OCF_LINK_KEY_REPLY 0x000B typedef struct { bdaddr_t bdaddr; uint8_t link_key[16]; -} __attribute__ ((packed)) link_key_reply_cp; +} QEMU_PACKED link_key_reply_cp; #define LINK_KEY_REPLY_CP_SIZE 22 #define OCF_LINK_KEY_NEG_REPLY 0x000C @@ -535,7 +535,7 @@ typedef struct { bdaddr_t bdaddr; uint8_t pin_len; uint8_t pin_code[16]; -} __attribute__ ((packed)) pin_code_reply_cp; +} QEMU_PACKED pin_code_reply_cp; #define PIN_CODE_REPLY_CP_SIZE 23 #define OCF_PIN_CODE_NEG_REPLY 0x000E @@ -544,32 +544,32 @@ typedef struct { typedef struct { uint16_t handle; uint16_t pkt_type; -} __attribute__ ((packed)) set_conn_ptype_cp; +} QEMU_PACKED set_conn_ptype_cp; #define SET_CONN_PTYPE_CP_SIZE 4 #define OCF_AUTH_REQUESTED 0x0011 typedef struct { uint16_t handle; -} __attribute__ ((packed)) auth_requested_cp; +} QEMU_PACKED auth_requested_cp; #define AUTH_REQUESTED_CP_SIZE 2 #define OCF_SET_CONN_ENCRYPT 0x0013 typedef struct { uint16_t handle; uint8_t encrypt; -} __attribute__ ((packed)) set_conn_encrypt_cp; +} QEMU_PACKED set_conn_encrypt_cp; #define SET_CONN_ENCRYPT_CP_SIZE 3 #define OCF_CHANGE_CONN_LINK_KEY 0x0015 typedef struct { uint16_t handle; -} __attribute__ ((packed)) change_conn_link_key_cp; +} QEMU_PACKED change_conn_link_key_cp; #define CHANGE_CONN_LINK_KEY_CP_SIZE 2 #define OCF_MASTER_LINK_KEY 0x0017 typedef struct { uint8_t key_flag; -} __attribute__ ((packed)) master_link_key_cp; +} QEMU_PACKED master_link_key_cp; #define MASTER_LINK_KEY_CP_SIZE 1 #define OCF_REMOTE_NAME_REQ 0x0019 @@ -578,50 +578,50 @@ typedef struct { uint8_t pscan_rep_mode; uint8_t pscan_mode; uint16_t clock_offset; -} __attribute__ ((packed)) remote_name_req_cp; +} QEMU_PACKED remote_name_req_cp; #define REMOTE_NAME_REQ_CP_SIZE 10 #define OCF_REMOTE_NAME_REQ_CANCEL 0x001A typedef struct { bdaddr_t bdaddr; -} __attribute__ ((packed)) remote_name_req_cancel_cp; +} QEMU_PACKED remote_name_req_cancel_cp; #define REMOTE_NAME_REQ_CANCEL_CP_SIZE 6 typedef struct { uint8_t status; bdaddr_t bdaddr; -} __attribute__ ((packed)) remote_name_req_cancel_rp; +} QEMU_PACKED remote_name_req_cancel_rp; #define REMOTE_NAME_REQ_CANCEL_RP_SIZE 7 #define OCF_READ_REMOTE_FEATURES 0x001B typedef struct { uint16_t handle; -} __attribute__ ((packed)) read_remote_features_cp; +} QEMU_PACKED read_remote_features_cp; #define READ_REMOTE_FEATURES_CP_SIZE 2 #define OCF_READ_REMOTE_EXT_FEATURES 0x001C typedef struct { uint16_t handle; uint8_t page_num; -} __attribute__ ((packed)) read_remote_ext_features_cp; +} QEMU_PACKED read_remote_ext_features_cp; #define READ_REMOTE_EXT_FEATURES_CP_SIZE 3 #define OCF_READ_REMOTE_VERSION 0x001D typedef struct { uint16_t handle; -} __attribute__ ((packed)) read_remote_version_cp; +} QEMU_PACKED read_remote_version_cp; #define READ_REMOTE_VERSION_CP_SIZE 2 #define OCF_READ_CLOCK_OFFSET 0x001F typedef struct { uint16_t handle; -} __attribute__ ((packed)) read_clock_offset_cp; +} QEMU_PACKED read_clock_offset_cp; #define READ_CLOCK_OFFSET_CP_SIZE 2 #define OCF_READ_LMP_HANDLE 0x0020 typedef struct { uint16_t handle; -} __attribute__ ((packed)) read_lmp_handle_cp; +} QEMU_PACKED read_lmp_handle_cp; #define READ_LMP_HANDLE_CP_SIZE 2 typedef struct { @@ -629,7 +629,7 @@ typedef struct { uint16_t handle; uint8_t lmp_handle; uint32_t reserved; -} __attribute__ ((packed)) read_lmp_handle_rp; +} QEMU_PACKED read_lmp_handle_rp; #define READ_LMP_HANDLE_RP_SIZE 8 #define OCF_SETUP_SYNC_CONN 0x0028 @@ -641,7 +641,7 @@ typedef struct { uint16_t voice_setting; uint8_t retrans_effort; uint16_t pkt_type; -} __attribute__ ((packed)) setup_sync_conn_cp; +} QEMU_PACKED setup_sync_conn_cp; #define SETUP_SYNC_CONN_CP_SIZE 17 #define OCF_ACCEPT_SYNC_CONN_REQ 0x0029 @@ -653,14 +653,14 @@ typedef struct { uint16_t voice_setting; uint8_t retrans_effort; uint16_t pkt_type; -} __attribute__ ((packed)) accept_sync_conn_req_cp; +} QEMU_PACKED accept_sync_conn_req_cp; #define ACCEPT_SYNC_CONN_REQ_CP_SIZE 21 #define OCF_REJECT_SYNC_CONN_REQ 0x002A typedef struct { bdaddr_t bdaddr; uint8_t reason; -} __attribute__ ((packed)) reject_sync_conn_req_cp; +} QEMU_PACKED reject_sync_conn_req_cp; #define REJECT_SYNC_CONN_REQ_CP_SIZE 7 /* Link Policy */ @@ -671,7 +671,7 @@ typedef struct { uint16_t handle; uint16_t max_interval; uint16_t min_interval; -} __attribute__ ((packed)) hold_mode_cp; +} QEMU_PACKED hold_mode_cp; #define HOLD_MODE_CP_SIZE 6 #define OCF_SNIFF_MODE 0x0003 @@ -681,13 +681,13 @@ typedef struct { uint16_t min_interval; uint16_t attempt; uint16_t timeout; -} __attribute__ ((packed)) sniff_mode_cp; +} QEMU_PACKED sniff_mode_cp; #define SNIFF_MODE_CP_SIZE 10 #define OCF_EXIT_SNIFF_MODE 0x0004 typedef struct { uint16_t handle; -} __attribute__ ((packed)) exit_sniff_mode_cp; +} QEMU_PACKED exit_sniff_mode_cp; #define EXIT_SNIFF_MODE_CP_SIZE 2 #define OCF_PARK_MODE 0x0005 @@ -695,13 +695,13 @@ typedef struct { uint16_t handle; uint16_t max_interval; uint16_t min_interval; -} __attribute__ ((packed)) park_mode_cp; +} QEMU_PACKED park_mode_cp; #define PARK_MODE_CP_SIZE 6 #define OCF_EXIT_PARK_MODE 0x0006 typedef struct { uint16_t handle; -} __attribute__ ((packed)) exit_park_mode_cp; +} QEMU_PACKED exit_park_mode_cp; #define EXIT_PARK_MODE_CP_SIZE 2 #define OCF_QOS_SETUP 0x0007 @@ -711,56 +711,56 @@ typedef struct { uint32_t peak_bandwidth; /* Byte per seconds */ uint32_t latency; /* Microseconds */ uint32_t delay_variation; /* Microseconds */ -} __attribute__ ((packed)) hci_qos; +} QEMU_PACKED hci_qos; #define HCI_QOS_CP_SIZE 17 typedef struct { uint16_t handle; uint8_t flags; /* Reserved */ hci_qos qos; -} __attribute__ ((packed)) qos_setup_cp; +} QEMU_PACKED qos_setup_cp; #define QOS_SETUP_CP_SIZE (3 + HCI_QOS_CP_SIZE) #define OCF_ROLE_DISCOVERY 0x0009 typedef struct { uint16_t handle; -} __attribute__ ((packed)) role_discovery_cp; +} QEMU_PACKED role_discovery_cp; #define ROLE_DISCOVERY_CP_SIZE 2 typedef struct { uint8_t status; uint16_t handle; uint8_t role; -} __attribute__ ((packed)) role_discovery_rp; +} QEMU_PACKED role_discovery_rp; #define ROLE_DISCOVERY_RP_SIZE 4 #define OCF_SWITCH_ROLE 0x000B typedef struct { bdaddr_t bdaddr; uint8_t role; -} __attribute__ ((packed)) switch_role_cp; +} QEMU_PACKED switch_role_cp; #define SWITCH_ROLE_CP_SIZE 7 #define OCF_READ_LINK_POLICY 0x000C typedef struct { uint16_t handle; -} __attribute__ ((packed)) read_link_policy_cp; +} QEMU_PACKED read_link_policy_cp; #define READ_LINK_POLICY_CP_SIZE 2 typedef struct { uint8_t status; uint16_t handle; uint16_t policy; -} __attribute__ ((packed)) read_link_policy_rp; +} QEMU_PACKED read_link_policy_rp; #define READ_LINK_POLICY_RP_SIZE 5 #define OCF_WRITE_LINK_POLICY 0x000D typedef struct { uint16_t handle; uint16_t policy; -} __attribute__ ((packed)) write_link_policy_cp; +} QEMU_PACKED write_link_policy_cp; #define WRITE_LINK_POLICY_CP_SIZE 4 typedef struct { uint8_t status; uint16_t handle; -} __attribute__ ((packed)) write_link_policy_rp; +} QEMU_PACKED write_link_policy_rp; #define WRITE_LINK_POLICY_RP_SIZE 3 #define OCF_READ_DEFAULT_LINK_POLICY 0x000E @@ -776,7 +776,7 @@ typedef struct { uint16_t max_local_latency; uint16_t min_remote_timeout; uint16_t min_local_timeout; -} __attribute__ ((packed)) sniff_subrate_cp; +} QEMU_PACKED sniff_subrate_cp; #define SNIFF_SUBRATE_CP_SIZE 10 /* Host Controller and Baseband */ @@ -785,7 +785,7 @@ typedef struct { #define OCF_SET_EVENT_MASK 0x0001 typedef struct { uint8_t mask[8]; -} __attribute__ ((packed)) set_event_mask_cp; +} QEMU_PACKED set_event_mask_cp; #define SET_EVENT_MASK_CP_SIZE 8 #define OCF_RESET 0x0003 @@ -795,7 +795,7 @@ typedef struct { uint8_t flt_type; uint8_t cond_type; uint8_t condition[0]; -} __attribute__ ((packed)) set_event_flt_cp; +} QEMU_PACKED set_event_flt_cp; #define SET_EVENT_FLT_CP_SIZE 2 enum bt_filter_type { @@ -821,26 +821,26 @@ enum conn_setup_cond { #define OCF_FLUSH 0x0008 typedef struct { uint16_t handle; -} __attribute__ ((packed)) flush_cp; +} QEMU_PACKED flush_cp; #define FLUSH_CP_SIZE 2 typedef struct { uint8_t status; uint16_t handle; -} __attribute__ ((packed)) flush_rp; +} QEMU_PACKED flush_rp; #define FLUSH_RP_SIZE 3 #define OCF_READ_PIN_TYPE 0x0009 typedef struct { uint8_t status; uint8_t pin_type; -} __attribute__ ((packed)) read_pin_type_rp; +} QEMU_PACKED read_pin_type_rp; #define READ_PIN_TYPE_RP_SIZE 2 #define OCF_WRITE_PIN_TYPE 0x000A typedef struct { uint8_t pin_type; -} __attribute__ ((packed)) write_pin_type_cp; +} QEMU_PACKED write_pin_type_cp; #define WRITE_PIN_TYPE_CP_SIZE 1 #define OCF_CREATE_NEW_UNIT_KEY 0x000B @@ -849,89 +849,89 @@ typedef struct { typedef struct { bdaddr_t bdaddr; uint8_t read_all; -} __attribute__ ((packed)) read_stored_link_key_cp; +} QEMU_PACKED read_stored_link_key_cp; #define READ_STORED_LINK_KEY_CP_SIZE 7 typedef struct { uint8_t status; uint16_t max_keys; uint16_t num_keys; -} __attribute__ ((packed)) read_stored_link_key_rp; +} QEMU_PACKED read_stored_link_key_rp; #define READ_STORED_LINK_KEY_RP_SIZE 5 #define OCF_WRITE_STORED_LINK_KEY 0x0011 typedef struct { uint8_t num_keys; /* variable length part */ -} __attribute__ ((packed)) write_stored_link_key_cp; +} QEMU_PACKED write_stored_link_key_cp; #define WRITE_STORED_LINK_KEY_CP_SIZE 1 typedef struct { uint8_t status; uint8_t num_keys; -} __attribute__ ((packed)) write_stored_link_key_rp; +} QEMU_PACKED write_stored_link_key_rp; #define READ_WRITE_LINK_KEY_RP_SIZE 2 #define OCF_DELETE_STORED_LINK_KEY 0x0012 typedef struct { bdaddr_t bdaddr; uint8_t delete_all; -} __attribute__ ((packed)) delete_stored_link_key_cp; +} QEMU_PACKED delete_stored_link_key_cp; #define DELETE_STORED_LINK_KEY_CP_SIZE 7 typedef struct { uint8_t status; uint16_t num_keys; -} __attribute__ ((packed)) delete_stored_link_key_rp; +} QEMU_PACKED delete_stored_link_key_rp; #define DELETE_STORED_LINK_KEY_RP_SIZE 3 #define OCF_CHANGE_LOCAL_NAME 0x0013 typedef struct { char name[248]; -} __attribute__ ((packed)) change_local_name_cp; +} QEMU_PACKED change_local_name_cp; #define CHANGE_LOCAL_NAME_CP_SIZE 248 #define OCF_READ_LOCAL_NAME 0x0014 typedef struct { uint8_t status; char name[248]; -} __attribute__ ((packed)) read_local_name_rp; +} QEMU_PACKED read_local_name_rp; #define READ_LOCAL_NAME_RP_SIZE 249 #define OCF_READ_CONN_ACCEPT_TIMEOUT 0x0015 typedef struct { uint8_t status; uint16_t timeout; -} __attribute__ ((packed)) read_conn_accept_timeout_rp; +} QEMU_PACKED read_conn_accept_timeout_rp; #define READ_CONN_ACCEPT_TIMEOUT_RP_SIZE 3 #define OCF_WRITE_CONN_ACCEPT_TIMEOUT 0x0016 typedef struct { uint16_t timeout; -} __attribute__ ((packed)) write_conn_accept_timeout_cp; +} QEMU_PACKED write_conn_accept_timeout_cp; #define WRITE_CONN_ACCEPT_TIMEOUT_CP_SIZE 2 #define OCF_READ_PAGE_TIMEOUT 0x0017 typedef struct { uint8_t status; uint16_t timeout; -} __attribute__ ((packed)) read_page_timeout_rp; +} QEMU_PACKED read_page_timeout_rp; #define READ_PAGE_TIMEOUT_RP_SIZE 3 #define OCF_WRITE_PAGE_TIMEOUT 0x0018 typedef struct { uint16_t timeout; -} __attribute__ ((packed)) write_page_timeout_cp; +} QEMU_PACKED write_page_timeout_cp; #define WRITE_PAGE_TIMEOUT_CP_SIZE 2 #define OCF_READ_SCAN_ENABLE 0x0019 typedef struct { uint8_t status; uint8_t enable; -} __attribute__ ((packed)) read_scan_enable_rp; +} QEMU_PACKED read_scan_enable_rp; #define READ_SCAN_ENABLE_RP_SIZE 2 #define OCF_WRITE_SCAN_ENABLE 0x001A typedef struct { uint8_t scan_enable; -} __attribute__ ((packed)) write_scan_enable_cp; +} QEMU_PACKED write_scan_enable_cp; #define WRITE_SCAN_ENABLE_CP_SIZE 1 enum scan_enable_bits { @@ -945,14 +945,14 @@ typedef struct { uint8_t status; uint16_t interval; uint16_t window; -} __attribute__ ((packed)) read_page_activity_rp; +} QEMU_PACKED read_page_activity_rp; #define READ_PAGE_ACTIVITY_RP_SIZE 5 #define OCF_WRITE_PAGE_ACTIVITY 0x001C typedef struct { uint16_t interval; uint16_t window; -} __attribute__ ((packed)) write_page_activity_cp; +} QEMU_PACKED write_page_activity_cp; #define WRITE_PAGE_ACTIVITY_CP_SIZE 4 #define OCF_READ_INQ_ACTIVITY 0x001D @@ -960,14 +960,14 @@ typedef struct { uint8_t status; uint16_t interval; uint16_t window; -} __attribute__ ((packed)) read_inq_activity_rp; +} QEMU_PACKED read_inq_activity_rp; #define READ_INQ_ACTIVITY_RP_SIZE 5 #define OCF_WRITE_INQ_ACTIVITY 0x001E typedef struct { uint16_t interval; uint16_t window; -} __attribute__ ((packed)) write_inq_activity_cp; +} QEMU_PACKED write_inq_activity_cp; #define WRITE_INQ_ACTIVITY_CP_SIZE 4 #define OCF_READ_AUTH_ENABLE 0x001F @@ -989,26 +989,26 @@ typedef struct { typedef struct { uint8_t status; uint8_t dev_class[3]; -} __attribute__ ((packed)) read_class_of_dev_rp; +} QEMU_PACKED read_class_of_dev_rp; #define READ_CLASS_OF_DEV_RP_SIZE 4 #define OCF_WRITE_CLASS_OF_DEV 0x0024 typedef struct { uint8_t dev_class[3]; -} __attribute__ ((packed)) write_class_of_dev_cp; +} QEMU_PACKED write_class_of_dev_cp; #define WRITE_CLASS_OF_DEV_CP_SIZE 3 #define OCF_READ_VOICE_SETTING 0x0025 typedef struct { uint8_t status; uint16_t voice_setting; -} __attribute__ ((packed)) read_voice_setting_rp; +} QEMU_PACKED read_voice_setting_rp; #define READ_VOICE_SETTING_RP_SIZE 3 #define OCF_WRITE_VOICE_SETTING 0x0026 typedef struct { uint16_t voice_setting; -} __attribute__ ((packed)) write_voice_setting_cp; +} QEMU_PACKED write_voice_setting_cp; #define WRITE_VOICE_SETTING_CP_SIZE 2 #define OCF_READ_AUTOMATIC_FLUSH_TIMEOUT 0x0027 @@ -1027,13 +1027,13 @@ typedef struct { typedef struct { uint16_t handle; uint8_t type; -} __attribute__ ((packed)) read_transmit_power_level_cp; +} QEMU_PACKED read_transmit_power_level_cp; #define READ_TRANSMIT_POWER_LEVEL_CP_SIZE 3 typedef struct { uint8_t status; uint16_t handle; int8_t level; -} __attribute__ ((packed)) read_transmit_power_level_rp; +} QEMU_PACKED read_transmit_power_level_rp; #define READ_TRANSMIT_POWER_LEVEL_RP_SIZE 4 #define OCF_HOST_BUFFER_SIZE 0x0033 @@ -1042,7 +1042,7 @@ typedef struct { uint8_t sco_mtu; uint16_t acl_max_pkt; uint16_t sco_max_pkt; -} __attribute__ ((packed)) host_buffer_size_cp; +} QEMU_PACKED host_buffer_size_cp; #define HOST_BUFFER_SIZE_CP_SIZE 7 #define OCF_HOST_NUMBER_OF_COMPLETED_PACKETS 0x0035 @@ -1052,19 +1052,19 @@ typedef struct { uint8_t status; uint16_t handle; uint16_t link_sup_to; -} __attribute__ ((packed)) read_link_supervision_timeout_rp; +} QEMU_PACKED read_link_supervision_timeout_rp; #define READ_LINK_SUPERVISION_TIMEOUT_RP_SIZE 5 #define OCF_WRITE_LINK_SUPERVISION_TIMEOUT 0x0037 typedef struct { uint16_t handle; uint16_t link_sup_to; -} __attribute__ ((packed)) write_link_supervision_timeout_cp; +} QEMU_PACKED write_link_supervision_timeout_cp; #define WRITE_LINK_SUPERVISION_TIMEOUT_CP_SIZE 4 typedef struct { uint8_t status; uint16_t handle; -} __attribute__ ((packed)) write_link_supervision_timeout_rp; +} QEMU_PACKED write_link_supervision_timeout_rp; #define WRITE_LINK_SUPERVISION_TIMEOUT_RP_SIZE 3 #define OCF_READ_NUM_SUPPORTED_IAC 0x0038 @@ -1075,14 +1075,14 @@ typedef struct { uint8_t status; uint8_t num_current_iac; uint8_t lap[MAX_IAC_LAP][3]; -} __attribute__ ((packed)) read_current_iac_lap_rp; +} QEMU_PACKED read_current_iac_lap_rp; #define READ_CURRENT_IAC_LAP_RP_SIZE 2+3*MAX_IAC_LAP #define OCF_WRITE_CURRENT_IAC_LAP 0x003A typedef struct { uint8_t num_current_iac; uint8_t lap[MAX_IAC_LAP][3]; -} __attribute__ ((packed)) write_current_iac_lap_cp; +} QEMU_PACKED write_current_iac_lap_cp; #define WRITE_CURRENT_IAC_LAP_CP_SIZE 1+3*MAX_IAC_LAP #define OCF_READ_PAGE_SCAN_PERIOD_MODE 0x003B @@ -1096,45 +1096,45 @@ typedef struct { #define OCF_SET_AFH_CLASSIFICATION 0x003F typedef struct { uint8_t map[10]; -} __attribute__ ((packed)) set_afh_classification_cp; +} QEMU_PACKED set_afh_classification_cp; #define SET_AFH_CLASSIFICATION_CP_SIZE 10 typedef struct { uint8_t status; -} __attribute__ ((packed)) set_afh_classification_rp; +} QEMU_PACKED set_afh_classification_rp; #define SET_AFH_CLASSIFICATION_RP_SIZE 1 #define OCF_READ_INQUIRY_SCAN_TYPE 0x0042 typedef struct { uint8_t status; uint8_t type; -} __attribute__ ((packed)) read_inquiry_scan_type_rp; +} QEMU_PACKED read_inquiry_scan_type_rp; #define READ_INQUIRY_SCAN_TYPE_RP_SIZE 2 #define OCF_WRITE_INQUIRY_SCAN_TYPE 0x0043 typedef struct { uint8_t type; -} __attribute__ ((packed)) write_inquiry_scan_type_cp; +} QEMU_PACKED write_inquiry_scan_type_cp; #define WRITE_INQUIRY_SCAN_TYPE_CP_SIZE 1 typedef struct { uint8_t status; -} __attribute__ ((packed)) write_inquiry_scan_type_rp; +} QEMU_PACKED write_inquiry_scan_type_rp; #define WRITE_INQUIRY_SCAN_TYPE_RP_SIZE 1 #define OCF_READ_INQUIRY_MODE 0x0044 typedef struct { uint8_t status; uint8_t mode; -} __attribute__ ((packed)) read_inquiry_mode_rp; +} QEMU_PACKED read_inquiry_mode_rp; #define READ_INQUIRY_MODE_RP_SIZE 2 #define OCF_WRITE_INQUIRY_MODE 0x0045 typedef struct { uint8_t mode; -} __attribute__ ((packed)) write_inquiry_mode_cp; +} QEMU_PACKED write_inquiry_mode_cp; #define WRITE_INQUIRY_MODE_CP_SIZE 1 typedef struct { uint8_t status; -} __attribute__ ((packed)) write_inquiry_mode_rp; +} QEMU_PACKED write_inquiry_mode_rp; #define WRITE_INQUIRY_MODE_RP_SIZE 1 #define OCF_READ_PAGE_SCAN_TYPE 0x0046 @@ -1145,17 +1145,17 @@ typedef struct { typedef struct { uint8_t status; uint8_t mode; -} __attribute__ ((packed)) read_afh_mode_rp; +} QEMU_PACKED read_afh_mode_rp; #define READ_AFH_MODE_RP_SIZE 2 #define OCF_WRITE_AFH_MODE 0x0049 typedef struct { uint8_t mode; -} __attribute__ ((packed)) write_afh_mode_cp; +} QEMU_PACKED write_afh_mode_cp; #define WRITE_AFH_MODE_CP_SIZE 1 typedef struct { uint8_t status; -} __attribute__ ((packed)) write_afh_mode_rp; +} QEMU_PACKED write_afh_mode_rp; #define WRITE_AFH_MODE_RP_SIZE 1 #define OCF_READ_EXT_INQUIRY_RESPONSE 0x0051 @@ -1163,18 +1163,18 @@ typedef struct { uint8_t status; uint8_t fec; uint8_t data[240]; -} __attribute__ ((packed)) read_ext_inquiry_response_rp; +} QEMU_PACKED read_ext_inquiry_response_rp; #define READ_EXT_INQUIRY_RESPONSE_RP_SIZE 242 #define OCF_WRITE_EXT_INQUIRY_RESPONSE 0x0052 typedef struct { uint8_t fec; uint8_t data[240]; -} __attribute__ ((packed)) write_ext_inquiry_response_cp; +} QEMU_PACKED write_ext_inquiry_response_cp; #define WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE 241 typedef struct { uint8_t status; -} __attribute__ ((packed)) write_ext_inquiry_response_rp; +} QEMU_PACKED write_ext_inquiry_response_rp; #define WRITE_EXT_INQUIRY_RESPONSE_RP_SIZE 1 /* Informational Parameters */ @@ -1188,34 +1188,34 @@ typedef struct { uint8_t lmp_ver; uint16_t manufacturer; uint16_t lmp_subver; -} __attribute__ ((packed)) read_local_version_rp; +} QEMU_PACKED read_local_version_rp; #define READ_LOCAL_VERSION_RP_SIZE 9 #define OCF_READ_LOCAL_COMMANDS 0x0002 typedef struct { uint8_t status; uint8_t commands[64]; -} __attribute__ ((packed)) read_local_commands_rp; +} QEMU_PACKED read_local_commands_rp; #define READ_LOCAL_COMMANDS_RP_SIZE 65 #define OCF_READ_LOCAL_FEATURES 0x0003 typedef struct { uint8_t status; uint8_t features[8]; -} __attribute__ ((packed)) read_local_features_rp; +} QEMU_PACKED read_local_features_rp; #define READ_LOCAL_FEATURES_RP_SIZE 9 #define OCF_READ_LOCAL_EXT_FEATURES 0x0004 typedef struct { uint8_t page_num; -} __attribute__ ((packed)) read_local_ext_features_cp; +} QEMU_PACKED read_local_ext_features_cp; #define READ_LOCAL_EXT_FEATURES_CP_SIZE 1 typedef struct { uint8_t status; uint8_t page_num; uint8_t max_page_num; uint8_t features[8]; -} __attribute__ ((packed)) read_local_ext_features_rp; +} QEMU_PACKED read_local_ext_features_rp; #define READ_LOCAL_EXT_FEATURES_RP_SIZE 11 #define OCF_READ_BUFFER_SIZE 0x0005 @@ -1225,21 +1225,21 @@ typedef struct { uint8_t sco_mtu; uint16_t acl_max_pkt; uint16_t sco_max_pkt; -} __attribute__ ((packed)) read_buffer_size_rp; +} QEMU_PACKED read_buffer_size_rp; #define READ_BUFFER_SIZE_RP_SIZE 8 #define OCF_READ_COUNTRY_CODE 0x0007 typedef struct { uint8_t status; uint8_t country_code; -} __attribute__ ((packed)) read_country_code_rp; +} QEMU_PACKED read_country_code_rp; #define READ_COUNTRY_CODE_RP_SIZE 2 #define OCF_READ_BD_ADDR 0x0009 typedef struct { uint8_t status; bdaddr_t bdaddr; -} __attribute__ ((packed)) read_bd_addr_rp; +} QEMU_PACKED read_bd_addr_rp; #define READ_BD_ADDR_RP_SIZE 7 /* Status params */ @@ -1250,27 +1250,27 @@ typedef struct { uint8_t status; uint16_t handle; uint8_t counter; -} __attribute__ ((packed)) read_failed_contact_counter_rp; +} QEMU_PACKED read_failed_contact_counter_rp; #define READ_FAILED_CONTACT_COUNTER_RP_SIZE 4 #define OCF_RESET_FAILED_CONTACT_COUNTER 0x0002 typedef struct { uint8_t status; uint16_t handle; -} __attribute__ ((packed)) reset_failed_contact_counter_rp; +} QEMU_PACKED reset_failed_contact_counter_rp; #define RESET_FAILED_CONTACT_COUNTER_RP_SIZE 4 #define OCF_READ_LINK_QUALITY 0x0003 typedef struct { uint16_t handle; -} __attribute__ ((packed)) read_link_quality_cp; +} QEMU_PACKED read_link_quality_cp; #define READ_LINK_QUALITY_CP_SIZE 4 typedef struct { uint8_t status; uint16_t handle; uint8_t link_quality; -} __attribute__ ((packed)) read_link_quality_rp; +} QEMU_PACKED read_link_quality_rp; #define READ_LINK_QUALITY_RP_SIZE 4 #define OCF_READ_RSSI 0x0005 @@ -1278,7 +1278,7 @@ typedef struct { uint8_t status; uint16_t handle; int8_t rssi; -} __attribute__ ((packed)) read_rssi_rp; +} QEMU_PACKED read_rssi_rp; #define READ_RSSI_RP_SIZE 4 #define OCF_READ_AFH_MAP 0x0006 @@ -1287,21 +1287,21 @@ typedef struct { uint16_t handle; uint8_t mode; uint8_t map[10]; -} __attribute__ ((packed)) read_afh_map_rp; +} QEMU_PACKED read_afh_map_rp; #define READ_AFH_MAP_RP_SIZE 14 #define OCF_READ_CLOCK 0x0007 typedef struct { uint16_t handle; uint8_t which_clock; -} __attribute__ ((packed)) read_clock_cp; +} QEMU_PACKED read_clock_cp; #define READ_CLOCK_CP_SIZE 3 typedef struct { uint8_t status; uint16_t handle; uint32_t clock; uint16_t accuracy; -} __attribute__ ((packed)) read_clock_rp; +} QEMU_PACKED read_clock_rp; #define READ_CLOCK_RP_SIZE 9 /* Testing commands */ @@ -1323,7 +1323,7 @@ typedef struct { uint8_t pscan_mode; uint8_t dev_class[3]; uint16_t clock_offset; -} __attribute__ ((packed)) inquiry_info; +} QEMU_PACKED inquiry_info; #define INQUIRY_INFO_SIZE 14 #define EVT_CONN_COMPLETE 0x03 @@ -1333,7 +1333,7 @@ typedef struct { bdaddr_t bdaddr; uint8_t link_type; uint8_t encr_mode; -} __attribute__ ((packed)) evt_conn_complete; +} QEMU_PACKED evt_conn_complete; #define EVT_CONN_COMPLETE_SIZE 11 #define EVT_CONN_REQUEST 0x04 @@ -1341,7 +1341,7 @@ typedef struct { bdaddr_t bdaddr; uint8_t dev_class[3]; uint8_t link_type; -} __attribute__ ((packed)) evt_conn_request; +} QEMU_PACKED evt_conn_request; #define EVT_CONN_REQUEST_SIZE 10 #define EVT_DISCONN_COMPLETE 0x05 @@ -1349,14 +1349,14 @@ typedef struct { uint8_t status; uint16_t handle; uint8_t reason; -} __attribute__ ((packed)) evt_disconn_complete; +} QEMU_PACKED evt_disconn_complete; #define EVT_DISCONN_COMPLETE_SIZE 4 #define EVT_AUTH_COMPLETE 0x06 typedef struct { uint8_t status; uint16_t handle; -} __attribute__ ((packed)) evt_auth_complete; +} QEMU_PACKED evt_auth_complete; #define EVT_AUTH_COMPLETE_SIZE 3 #define EVT_REMOTE_NAME_REQ_COMPLETE 0x07 @@ -1364,7 +1364,7 @@ typedef struct { uint8_t status; bdaddr_t bdaddr; char name[248]; -} __attribute__ ((packed)) evt_remote_name_req_complete; +} QEMU_PACKED evt_remote_name_req_complete; #define EVT_REMOTE_NAME_REQ_COMPLETE_SIZE 255 #define EVT_ENCRYPT_CHANGE 0x08 @@ -1372,14 +1372,14 @@ typedef struct { uint8_t status; uint16_t handle; uint8_t encrypt; -} __attribute__ ((packed)) evt_encrypt_change; +} QEMU_PACKED evt_encrypt_change; #define EVT_ENCRYPT_CHANGE_SIZE 5 #define EVT_CHANGE_CONN_LINK_KEY_COMPLETE 0x09 typedef struct { uint8_t status; uint16_t handle; -} __attribute__ ((packed)) evt_change_conn_link_key_complete; +} QEMU_PACKED evt_change_conn_link_key_complete; #define EVT_CHANGE_CONN_LINK_KEY_COMPLETE_SIZE 3 #define EVT_MASTER_LINK_KEY_COMPLETE 0x0A @@ -1387,7 +1387,7 @@ typedef struct { uint8_t status; uint16_t handle; uint8_t key_flag; -} __attribute__ ((packed)) evt_master_link_key_complete; +} QEMU_PACKED evt_master_link_key_complete; #define EVT_MASTER_LINK_KEY_COMPLETE_SIZE 4 #define EVT_READ_REMOTE_FEATURES_COMPLETE 0x0B @@ -1395,7 +1395,7 @@ typedef struct { uint8_t status; uint16_t handle; uint8_t features[8]; -} __attribute__ ((packed)) evt_read_remote_features_complete; +} QEMU_PACKED evt_read_remote_features_complete; #define EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE 11 #define EVT_READ_REMOTE_VERSION_COMPLETE 0x0C @@ -1405,7 +1405,7 @@ typedef struct { uint8_t lmp_ver; uint16_t manufacturer; uint16_t lmp_subver; -} __attribute__ ((packed)) evt_read_remote_version_complete; +} QEMU_PACKED evt_read_remote_version_complete; #define EVT_READ_REMOTE_VERSION_COMPLETE_SIZE 8 #define EVT_QOS_SETUP_COMPLETE 0x0D @@ -1414,14 +1414,14 @@ typedef struct { uint16_t handle; uint8_t flags; /* Reserved */ hci_qos qos; -} __attribute__ ((packed)) evt_qos_setup_complete; +} QEMU_PACKED evt_qos_setup_complete; #define EVT_QOS_SETUP_COMPLETE_SIZE (4 + HCI_QOS_CP_SIZE) #define EVT_CMD_COMPLETE 0x0E typedef struct { uint8_t ncmd; uint16_t opcode; -} __attribute__ ((packed)) evt_cmd_complete; +} QEMU_PACKED evt_cmd_complete; #define EVT_CMD_COMPLETE_SIZE 3 #define EVT_CMD_STATUS 0x0F @@ -1429,19 +1429,19 @@ typedef struct { uint8_t status; uint8_t ncmd; uint16_t opcode; -} __attribute__ ((packed)) evt_cmd_status; +} QEMU_PACKED evt_cmd_status; #define EVT_CMD_STATUS_SIZE 4 #define EVT_HARDWARE_ERROR 0x10 typedef struct { uint8_t code; -} __attribute__ ((packed)) evt_hardware_error; +} QEMU_PACKED evt_hardware_error; #define EVT_HARDWARE_ERROR_SIZE 1 #define EVT_FLUSH_OCCURRED 0x11 typedef struct { uint16_t handle; -} __attribute__ ((packed)) evt_flush_occurred; +} QEMU_PACKED evt_flush_occurred; #define EVT_FLUSH_OCCURRED_SIZE 2 #define EVT_ROLE_CHANGE 0x12 @@ -1449,7 +1449,7 @@ typedef struct { uint8_t status; bdaddr_t bdaddr; uint8_t role; -} __attribute__ ((packed)) evt_role_change; +} QEMU_PACKED evt_role_change; #define EVT_ROLE_CHANGE_SIZE 8 #define EVT_NUM_COMP_PKTS 0x13 @@ -1459,7 +1459,7 @@ typedef struct { uint16_t handle; uint16_t num_packets; } connection[0]; -} __attribute__ ((packed)) evt_num_comp_pkts; +} QEMU_PACKED evt_num_comp_pkts; #define EVT_NUM_COMP_PKTS_SIZE(num_hndl) (1 + 4 * (num_hndl)) #define EVT_MODE_CHANGE 0x14 @@ -1468,26 +1468,26 @@ typedef struct { uint16_t handle; uint8_t mode; uint16_t interval; -} __attribute__ ((packed)) evt_mode_change; +} QEMU_PACKED evt_mode_change; #define EVT_MODE_CHANGE_SIZE 6 #define EVT_RETURN_LINK_KEYS 0x15 typedef struct { uint8_t num_keys; /* variable length part */ -} __attribute__ ((packed)) evt_return_link_keys; +} QEMU_PACKED evt_return_link_keys; #define EVT_RETURN_LINK_KEYS_SIZE 1 #define EVT_PIN_CODE_REQ 0x16 typedef struct { bdaddr_t bdaddr; -} __attribute__ ((packed)) evt_pin_code_req; +} QEMU_PACKED evt_pin_code_req; #define EVT_PIN_CODE_REQ_SIZE 6 #define EVT_LINK_KEY_REQ 0x17 typedef struct { bdaddr_t bdaddr; -} __attribute__ ((packed)) evt_link_key_req; +} QEMU_PACKED evt_link_key_req; #define EVT_LINK_KEY_REQ_SIZE 6 #define EVT_LINK_KEY_NOTIFY 0x18 @@ -1495,7 +1495,7 @@ typedef struct { bdaddr_t bdaddr; uint8_t link_key[16]; uint8_t key_type; -} __attribute__ ((packed)) evt_link_key_notify; +} QEMU_PACKED evt_link_key_notify; #define EVT_LINK_KEY_NOTIFY_SIZE 23 #define EVT_LOOPBACK_COMMAND 0x19 @@ -1503,14 +1503,14 @@ typedef struct { #define EVT_DATA_BUFFER_OVERFLOW 0x1A typedef struct { uint8_t link_type; -} __attribute__ ((packed)) evt_data_buffer_overflow; +} QEMU_PACKED evt_data_buffer_overflow; #define EVT_DATA_BUFFER_OVERFLOW_SIZE 1 #define EVT_MAX_SLOTS_CHANGE 0x1B typedef struct { uint16_t handle; uint8_t max_slots; -} __attribute__ ((packed)) evt_max_slots_change; +} QEMU_PACKED evt_max_slots_change; #define EVT_MAX_SLOTS_CHANGE_SIZE 3 #define EVT_READ_CLOCK_OFFSET_COMPLETE 0x1C @@ -1518,7 +1518,7 @@ typedef struct { uint8_t status; uint16_t handle; uint16_t clock_offset; -} __attribute__ ((packed)) evt_read_clock_offset_complete; +} QEMU_PACKED evt_read_clock_offset_complete; #define EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE 5 #define EVT_CONN_PTYPE_CHANGED 0x1D @@ -1526,20 +1526,20 @@ typedef struct { uint8_t status; uint16_t handle; uint16_t ptype; -} __attribute__ ((packed)) evt_conn_ptype_changed; +} QEMU_PACKED evt_conn_ptype_changed; #define EVT_CONN_PTYPE_CHANGED_SIZE 5 #define EVT_QOS_VIOLATION 0x1E typedef struct { uint16_t handle; -} __attribute__ ((packed)) evt_qos_violation; +} QEMU_PACKED evt_qos_violation; #define EVT_QOS_VIOLATION_SIZE 2 #define EVT_PSCAN_REP_MODE_CHANGE 0x20 typedef struct { bdaddr_t bdaddr; uint8_t pscan_rep_mode; -} __attribute__ ((packed)) evt_pscan_rep_mode_change; +} QEMU_PACKED evt_pscan_rep_mode_change; #define EVT_PSCAN_REP_MODE_CHANGE_SIZE 7 #define EVT_FLOW_SPEC_COMPLETE 0x21 @@ -1549,7 +1549,7 @@ typedef struct { uint8_t flags; uint8_t direction; hci_qos qos; -} __attribute__ ((packed)) evt_flow_spec_complete; +} QEMU_PACKED evt_flow_spec_complete; #define EVT_FLOW_SPEC_COMPLETE_SIZE (5 + HCI_QOS_CP_SIZE) #define EVT_INQUIRY_RESULT_WITH_RSSI 0x22 @@ -1561,7 +1561,7 @@ typedef struct { uint8_t dev_class[3]; uint16_t clock_offset; int8_t rssi; -} __attribute__ ((packed)) inquiry_info_with_rssi; +} QEMU_PACKED inquiry_info_with_rssi; #define INQUIRY_INFO_WITH_RSSI_SIZE 15 typedef struct { uint8_t num_responses; @@ -1572,7 +1572,7 @@ typedef struct { uint8_t dev_class[3]; uint16_t clock_offset; int8_t rssi; -} __attribute__ ((packed)) inquiry_info_with_rssi_and_pscan_mode; +} QEMU_PACKED inquiry_info_with_rssi_and_pscan_mode; #define INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE 16 #define EVT_READ_REMOTE_EXT_FEATURES_COMPLETE 0x23 @@ -1582,7 +1582,7 @@ typedef struct { uint8_t page_num; uint8_t max_page_num; uint8_t features[8]; -} __attribute__ ((packed)) evt_read_remote_ext_features_complete; +} QEMU_PACKED evt_read_remote_ext_features_complete; #define EVT_READ_REMOTE_EXT_FEATURES_COMPLETE_SIZE 13 #define EVT_SYNC_CONN_COMPLETE 0x2C @@ -1596,7 +1596,7 @@ typedef struct { uint16_t rx_pkt_len; uint16_t tx_pkt_len; uint8_t air_mode; -} __attribute__ ((packed)) evt_sync_conn_complete; +} QEMU_PACKED evt_sync_conn_complete; #define EVT_SYNC_CONN_COMPLETE_SIZE 17 #define EVT_SYNC_CONN_CHANGED 0x2D @@ -1607,7 +1607,7 @@ typedef struct { uint8_t retrans_window; uint16_t rx_pkt_len; uint16_t tx_pkt_len; -} __attribute__ ((packed)) evt_sync_conn_changed; +} QEMU_PACKED evt_sync_conn_changed; #define EVT_SYNC_CONN_CHANGED_SIZE 9 #define EVT_SNIFF_SUBRATE 0x2E @@ -1618,7 +1618,7 @@ typedef struct { uint16_t max_local_latency; uint16_t min_remote_timeout; uint16_t min_local_timeout; -} __attribute__ ((packed)) evt_sniff_subrate; +} QEMU_PACKED evt_sniff_subrate; #define EVT_SNIFF_SUBRATE_SIZE 11 #define EVT_EXTENDED_INQUIRY_RESULT 0x2F @@ -1630,7 +1630,7 @@ typedef struct { uint16_t clock_offset; int8_t rssi; uint8_t data[240]; -} __attribute__ ((packed)) extended_inquiry_info; +} QEMU_PACKED extended_inquiry_info; #define EXTENDED_INQUIRY_INFO_SIZE 254 #define EVT_TESTING 0xFE @@ -1656,22 +1656,22 @@ typedef struct { struct hci_command_hdr { uint16_t opcode; /* OCF & OGF */ uint8_t plen; -} __attribute__ ((packed)); +} QEMU_PACKED; struct hci_event_hdr { uint8_t evt; uint8_t plen; -} __attribute__ ((packed)); +} QEMU_PACKED; struct hci_acl_hdr { uint16_t handle; /* Handle & Flags(PB, BC) */ uint16_t dlen; -} __attribute__ ((packed)); +} QEMU_PACKED; struct hci_sco_hdr { uint16_t handle; uint8_t dlen; -} __attribute__ ((packed)); +} QEMU_PACKED; /* L2CAP layer defines */ @@ -1718,25 +1718,25 @@ typedef struct { uint16_t len; uint16_t cid; uint8_t data[0]; -} __attribute__ ((packed)) l2cap_hdr; +} QEMU_PACKED l2cap_hdr; #define L2CAP_HDR_SIZE 4 typedef struct { uint8_t code; uint8_t ident; uint16_t len; -} __attribute__ ((packed)) l2cap_cmd_hdr; +} QEMU_PACKED l2cap_cmd_hdr; #define L2CAP_CMD_HDR_SIZE 4 typedef struct { uint16_t reason; -} __attribute__ ((packed)) l2cap_cmd_rej; +} QEMU_PACKED l2cap_cmd_rej; #define L2CAP_CMD_REJ_SIZE 2 typedef struct { uint16_t dcid; uint16_t scid; -} __attribute__ ((packed)) l2cap_cmd_rej_cid; +} QEMU_PACKED l2cap_cmd_rej_cid; #define L2CAP_CMD_REJ_CID_SIZE 4 /* reject reason */ @@ -1749,7 +1749,7 @@ enum bt_l2cap_rej_reason { typedef struct { uint16_t psm; uint16_t scid; -} __attribute__ ((packed)) l2cap_conn_req; +} QEMU_PACKED l2cap_conn_req; #define L2CAP_CONN_REQ_SIZE 4 typedef struct { @@ -1757,7 +1757,7 @@ typedef struct { uint16_t scid; uint16_t result; uint16_t status; -} __attribute__ ((packed)) l2cap_conn_rsp; +} QEMU_PACKED l2cap_conn_rsp; #define L2CAP_CONN_RSP_SIZE 8 /* connect result */ @@ -1780,7 +1780,7 @@ typedef struct { uint16_t dcid; uint16_t flags; uint8_t data[0]; -} __attribute__ ((packed)) l2cap_conf_req; +} QEMU_PACKED l2cap_conf_req; #define L2CAP_CONF_REQ_SIZE(datalen) (4 + (datalen)) typedef struct { @@ -1788,7 +1788,7 @@ typedef struct { uint16_t flags; uint16_t result; uint8_t data[0]; -} __attribute__ ((packed)) l2cap_conf_rsp; +} QEMU_PACKED l2cap_conf_rsp; #define L2CAP_CONF_RSP_SIZE(datalen) (6 + datalen) enum bt_l2cap_conf_res { @@ -1802,7 +1802,7 @@ typedef struct { uint8_t type; uint8_t len; uint8_t val[0]; -} __attribute__ ((packed)) l2cap_conf_opt; +} QEMU_PACKED l2cap_conf_opt; #define L2CAP_CONF_OPT_SIZE 2 enum bt_l2cap_conf_val { @@ -1821,7 +1821,7 @@ typedef struct { uint32_t peak_bandwidth; uint32_t latency; uint32_t delay_variation; -} __attribute__ ((packed)) l2cap_conf_opt_qos; +} QEMU_PACKED l2cap_conf_opt_qos; #define L2CAP_CONF_OPT_QOS_SIZE 22 enum bt_l2cap_conf_opt_qos_st { @@ -1841,25 +1841,25 @@ enum bt_l2cap_mode { typedef struct { uint16_t dcid; uint16_t scid; -} __attribute__ ((packed)) l2cap_disconn_req; +} QEMU_PACKED l2cap_disconn_req; #define L2CAP_DISCONN_REQ_SIZE 4 typedef struct { uint16_t dcid; uint16_t scid; -} __attribute__ ((packed)) l2cap_disconn_rsp; +} QEMU_PACKED l2cap_disconn_rsp; #define L2CAP_DISCONN_RSP_SIZE 4 typedef struct { uint16_t type; -} __attribute__ ((packed)) l2cap_info_req; +} QEMU_PACKED l2cap_info_req; #define L2CAP_INFO_REQ_SIZE 2 typedef struct { uint16_t type; uint16_t result; uint8_t data[0]; -} __attribute__ ((packed)) l2cap_info_rsp; +} QEMU_PACKED l2cap_info_rsp; #define L2CAP_INFO_RSP_SIZE 4 /* info type */ diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index ec7ea8207b..4d0ef0d54c 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -2424,7 +2424,6 @@ static void cirrus_update_memory_access(CirrusVGAState *s) { unsigned mode; - memory_region_transaction_begin(); if ((s->vga.sr[0x17] & 0x44) == 0x44) { goto generic_io; } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { @@ -2444,7 +2443,6 @@ static void cirrus_update_memory_access(CirrusVGAState *s) unmap_linear_vram(s); } } - memory_region_transaction_commit(); } diff --git a/hw/collie.c b/hw/collie.c index 0b955e04f1..156404d9f3 100644 --- a/hw/collie.c +++ b/hw/collie.c @@ -26,7 +26,7 @@ static void collie_init(ram_addr_t ram_size, { StrongARMState *s; DriveInfo *dinfo; - MemoryRegion *phys_flash = g_new(MemoryRegion, 2); + ram_addr_t phys_flash; if (!cpu_model) { cpu_model = "sa1110"; @@ -34,19 +34,17 @@ static void collie_init(ram_addr_t ram_size, s = sa1110_init(collie_binfo.ram_size, cpu_model); - memory_region_init_rom_device(&phys_flash[0], &pflash_cfi01_ops_le, - NULL, "collie.fl1", 0x02000000); + phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000); dinfo = drive_get(IF_PFLASH, 0, 0); - pflash_cfi01_register(SA_CS0, &phys_flash[0], + pflash_cfi01_register(SA_CS0, phys_flash, dinfo ? dinfo->bdrv : NULL, (64 * 1024), - 512, 4, 0x00, 0x00, 0x00, 0x00); + 512, 4, 0x00, 0x00, 0x00, 0x00, 0); - memory_region_init_rom_device(&phys_flash[1], &pflash_cfi01_ops_le, - NULL, "collie.fl2", 0x02000000); + phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000); dinfo = drive_get(IF_PFLASH, 0, 1); - pflash_cfi01_register(SA_CS1, &phys_flash[1], + pflash_cfi01_register(SA_CS1, phys_flash, dinfo ? dinfo->bdrv : NULL, (64 * 1024), - 512, 4, 0x00, 0x00, 0x00, 0x00); + 512, 4, 0x00, 0x00, 0x00, 0x00, 0); sysbus_create_simple("scoop", 0x40800000, NULL); diff --git a/hw/dec_pci.c b/hw/dec_pci.c index 1aec06611c..a35f382052 100644 --- a/hw/dec_pci.c +++ b/hw/dec_pci.c @@ -80,15 +80,16 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn) static int pci_dec_21154_init_device(SysBusDevice *dev) { DECState *s; + int pci_mem_config, pci_mem_data; s = FROM_SYSBUS(DECState, dev); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops, - &s->host_state, "pci-data-idx", 0x1000); - sysbus_init_mmio_region(dev, &s->host_state.conf_mem); - sysbus_init_mmio_region(dev, &s->host_state.data_mem); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + pci_mem_data = pci_host_data_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, pci_mem_config); + sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; } diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c index 30146b9c9d..eed9e3843c 100644 --- a/hw/dummy_m68k.c +++ b/hw/dummy_m68k.c @@ -10,7 +10,6 @@ #include "boards.h" #include "loader.h" #include "elf.h" -#include "exec-memory.h" #define KERNEL_LOAD_ADDR 0x10000 @@ -22,8 +21,6 @@ static void dummy_m68k_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { CPUState *env; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); int kernel_size; uint64_t elf_entry; target_phys_addr_t entry; @@ -40,8 +37,8 @@ static void dummy_m68k_init(ram_addr_t ram_size, env->vbr = 0; /* RAM at address zero */ - memory_region_init_ram(ram, NULL, "dummy_m68k.ram", ram_size); - memory_region_add_subregion(address_space_mem, 0, ram); + cpu_register_physical_memory(0, ram_size, + qemu_ram_alloc(NULL, "dummy_m68k.ram", ram_size) | IO_MEM_RAM); /* Load kernel. */ if (kernel_filename) { diff --git a/hw/flash.h b/hw/flash.h index 7fb012bb06..270be5e127 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -1,27 +1,21 @@ -#include "memory.h" - /* NOR flash devices */ typedef struct pflash_t pflash_t; /* pflash_cfi01.c */ -extern const MemoryRegionOps pflash_cfi01_ops_be; -extern const MemoryRegionOps pflash_cfi01_ops_le; -extern const MemoryRegionOps pflash_cfi02_ops_be; -extern const MemoryRegionOps pflash_cfi02_ops_le; - -pflash_t *pflash_cfi01_register(target_phys_addr_t base, MemoryRegion *mem, +pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int width, uint16_t id0, uint16_t id1, - uint16_t id2, uint16_t id3); + uint16_t id2, uint16_t id3, int be); /* pflash_cfi02.c */ -pflash_t *pflash_cfi02_register(target_phys_addr_t base, MemoryRegion *mem, +pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int nb_mappings, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, - uint16_t unlock_addr0, uint16_t unlock_addr1); + uint16_t unlock_addr0, uint16_t unlock_addr1, + int be); /* nand.c */ DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id); @@ -42,12 +36,7 @@ uint32_t nand_getbuswidth(DeviceState *dev); #define NAND_MFR_MICRON 0x2c /* onenand.c */ -void onenand_base_update(void *opaque, target_phys_addr_t new); -void onenand_base_unmap(void *opaque); -void *onenand_init(BlockDriverState *bdrv, - uint16_t man_id, uint16_t dev_id, uint16_t ver_id, - int regshift, qemu_irq irq); -void *onenand_raw_otp(void *opaque); +void *onenand_raw_otp(DeviceState *onenand_device); /* ecc.c */ typedef struct { diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index 663ad80116..8df265c61d 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -214,7 +214,8 @@ static void fw_cfg_write(FWCfgState *s, uint8_t value) FW_CFG_DPRINTF("write %d\n", value); - if (s->cur_entry & FW_CFG_WRITE_CHANNEL && s->cur_offset < e->len) { + if (s->cur_entry & FW_CFG_WRITE_CHANNEL && e->callback && + s->cur_offset < e->len) { e->data[s->cur_offset++] = value; if (s->cur_offset == e->len) { e->callback(e->callback_opaque, e->data); diff --git a/hw/g364fb.c b/hw/g364fb.c index a7731ecfb5..5e7bcfa278 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -1,7 +1,7 @@ /* * QEMU G364 framebuffer Emulator. * - * Copyright (c) 2007-2009 Herve Poussineau + * Copyright (c) 2007-2011 Herve Poussineau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,27 +18,18 @@ */ #include "hw.h" -#include "mips.h" #include "console.h" #include "pixel_ops.h" - -//#define DEBUG_G364 - -#ifdef DEBUG_G364 -#define DPRINTF(fmt, ...) \ -do { printf("g364: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif -#define BADF(fmt, ...) \ -do { fprintf(stderr, "g364 ERROR: " fmt , ## __VA_ARGS__);} while (0) +#include "trace.h" +#include "sysbus.h" typedef struct G364State { /* hardware */ uint8_t *vram; - MemoryRegion vram_region; - int vram_size; + uint32_t vram_size; qemu_irq irq; + MemoryRegion mem_vram; + MemoryRegion mem_ctrl; /* registers */ uint8_t color_palette[256][3]; uint8_t cursor_palette[3][3]; @@ -53,31 +44,31 @@ typedef struct G364State { int blanked; } G364State; -#define REG_ID 0x000000 -#define REG_BOOT 0x080000 -#define REG_DISPLAY 0x080118 -#define REG_VDISPLAY 0x080150 -#define REG_CTLA 0x080300 -#define REG_TOP 0x080400 -#define REG_CURS_PAL 0x080508 -#define REG_CURS_POS 0x080638 -#define REG_CLR_PAL 0x080800 -#define REG_CURS_PAT 0x081000 -#define REG_RESET 0x180000 +#define REG_BOOT 0x000000 +#define REG_DISPLAY 0x000118 +#define REG_VDISPLAY 0x000150 +#define REG_CTLA 0x000300 +#define REG_TOP 0x000400 +#define REG_CURS_PAL 0x000508 +#define REG_CURS_POS 0x000638 +#define REG_CLR_PAL 0x000800 +#define REG_CURS_PAT 0x001000 +#define REG_RESET 0x100000 #define CTLA_FORCE_BLANK 0x00000400 #define CTLA_NO_CURSOR 0x00800000 static inline int check_dirty(G364State *s, ram_addr_t page) { - return memory_region_get_dirty(&s->vram_region, page, DIRTY_MEMORY_VGA); + return memory_region_get_dirty(&s->mem_vram, page, DIRTY_MEMORY_VGA); } static inline void reset_dirty(G364State *s, ram_addr_t page_min, ram_addr_t page_max) { - memory_region_reset_dirty(&s->vram_region, page_min, - page_max + TARGET_PAGE_SIZE - 1, + memory_region_reset_dirty(&s->mem_vram, + page_min, + page_max + TARGET_PAGE_SIZE - page_min - 1, DIRTY_MEMORY_VGA); } @@ -111,7 +102,8 @@ static void g364fb_draw_graphic8(G364State *s) w = 4; break; default: - BADF("unknown host depth %d\n", ds_get_bits_per_pixel(s->ds)); + hw_error("g364: unknown host depth %d", + ds_get_bits_per_pixel(s->ds)); return; } @@ -263,7 +255,7 @@ static void g364fb_update_display(void *opaque) } else if (s->depth == 8) { g364fb_draw_graphic8(s); } else { - BADF("unknown guest depth %d\n", s->depth); + error_report("g364: unknown guest depth %d", s->depth); } qemu_irq_raise(s->irq); @@ -276,13 +268,12 @@ static inline void g364fb_invalidate_display(void *opaque) s->blanked = 0; for (i = 0; i < s->vram_size; i += TARGET_PAGE_SIZE) { - memory_region_set_dirty(&s->vram_region, i); + memory_region_set_dirty(&s->mem_vram, i); } } -static void g364fb_reset(void *opaque) +static void g364fb_reset(G364State *s) { - G364State *s = opaque; qemu_irq_lower(s->irq); memset(s->color_palette, 0, sizeof(s->color_palette)); @@ -293,7 +284,7 @@ static void g364fb_reset(void *opaque) s->top_of_screen = 0; s->width = s->height = 0; memset(s->vram, 0, s->vram_size); - g364fb_invalidate_display(opaque); + g364fb_invalidate_display(s); } static void g364fb_screen_dump(void *opaque, const char *filename) @@ -305,7 +296,7 @@ static void g364fb_screen_dump(void *opaque, const char *filename) FILE *f; if (s->depth != 8) { - BADF("unknown guest depth %d\n", s->depth); + error_report("g364: unknown guest depth %d", s->depth); return; } @@ -337,7 +328,9 @@ static void g364fb_screen_dump(void *opaque, const char *filename) } /* called for accesses to io ports */ -static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) +static uint64_t g364fb_ctrl_read(void *opaque, + target_phys_addr_t addr, + unsigned int size) { G364State *s = opaque; uint32_t val; @@ -354,9 +347,6 @@ static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) val |= ((uint32_t)s->cursor_palette[idx][2] << 0); } else { switch (addr) { - case REG_ID: - val = 0x10; /* Mips G364 */ - break; case REG_DISPLAY: val = s->width / 4; break; @@ -368,33 +358,19 @@ static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) break; default: { - BADF("invalid read at [" TARGET_FMT_plx "]\n", addr); + error_report("g364: invalid read at [" TARGET_FMT_plx "]", + addr); val = 0; break; } } } - DPRINTF("read 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); + trace_g364fb_read(addr, val); return val; } -static uint32_t g364fb_ctrl_readw(void *opaque, target_phys_addr_t addr) -{ - uint32_t v = g364fb_ctrl_readl(opaque, addr & ~0x3); - if (addr & 0x2) - return v >> 16; - else - return v & 0xffff; -} - -static uint32_t g364fb_ctrl_readb(void *opaque, target_phys_addr_t addr) -{ - uint32_t v = g364fb_ctrl_readl(opaque, addr & ~0x3); - return (v >> (8 * (addr & 0x3))) & 0xff; -} - static void g364fb_update_depth(G364State *s) { static const int depths[8] = { 1, 2, 4, 8, 15, 16, 0 }; @@ -412,15 +388,18 @@ static void g364_invalidate_cursor_position(G364State *s) end = (ymax + 1) * ds_get_linesize(s->ds); for (i = start; i < end; i += TARGET_PAGE_SIZE) { - memory_region_set_dirty(&s->vram_region, i); + memory_region_set_dirty(&s->mem_vram, i); } } -static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void g364fb_ctrl_write(void *opaque, + target_phys_addr_t addr, + uint64_t val, + unsigned int size) { G364State *s = opaque; - DPRINTF("write 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); + trace_g364fb_write(addr, val); if (addr >= REG_CLR_PAL && addr < REG_CLR_PAL + 0x800) { /* color palette */ @@ -443,124 +422,65 @@ static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, uint32_t v g364fb_invalidate_display(s); } else { switch (addr) { - case REG_ID: /* Card identifier; read-only */ - case REG_BOOT: /* Boot timing */ - case 0x80108: /* Line timing: half sync */ - case 0x80110: /* Line timing: back porch */ - case 0x80120: /* Line timing: short display */ - case 0x80128: /* Frame timing: broad pulse */ - case 0x80130: /* Frame timing: v sync */ - case 0x80138: /* Frame timing: v preequalise */ - case 0x80140: /* Frame timing: v postequalise */ - case 0x80148: /* Frame timing: v blank */ - case 0x80158: /* Line timing: line time */ - case 0x80160: /* Frame store: line start */ - case 0x80168: /* vram cycle: mem init */ - case 0x80170: /* vram cycle: transfer delay */ - case 0x80200: /* vram cycle: mask register */ - /* ignore */ - break; - case REG_TOP: - s->top_of_screen = val; - g364fb_invalidate_display(s); - break; - case REG_DISPLAY: - s->width = val * 4; - break; - case REG_VDISPLAY: - s->height = val / 2; - break; - case REG_CTLA: - s->ctla = val; - g364fb_update_depth(s); - g364fb_invalidate_display(s); - break; - case REG_CURS_POS: - g364_invalidate_cursor_position(s); - s->cursor_position = val; - g364_invalidate_cursor_position(s); - break; - case REG_RESET: - g364fb_reset(s); - break; - default: - BADF("invalid write of 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); - break; + case REG_BOOT: /* Boot timing */ + case 0x00108: /* Line timing: half sync */ + case 0x00110: /* Line timing: back porch */ + case 0x00120: /* Line timing: short display */ + case 0x00128: /* Frame timing: broad pulse */ + case 0x00130: /* Frame timing: v sync */ + case 0x00138: /* Frame timing: v preequalise */ + case 0x00140: /* Frame timing: v postequalise */ + case 0x00148: /* Frame timing: v blank */ + case 0x00158: /* Line timing: line time */ + case 0x00160: /* Frame store: line start */ + case 0x00168: /* vram cycle: mem init */ + case 0x00170: /* vram cycle: transfer delay */ + case 0x00200: /* vram cycle: mask register */ + /* ignore */ + break; + case REG_TOP: + s->top_of_screen = val; + g364fb_invalidate_display(s); + break; + case REG_DISPLAY: + s->width = val * 4; + break; + case REG_VDISPLAY: + s->height = val / 2; + break; + case REG_CTLA: + s->ctla = val; + g364fb_update_depth(s); + g364fb_invalidate_display(s); + break; + case REG_CURS_POS: + g364_invalidate_cursor_position(s); + s->cursor_position = val; + g364_invalidate_cursor_position(s); + break; + case REG_RESET: + g364fb_reset(s); + break; + default: + error_report("g364: invalid write of 0x%" PRIx64 + " at [" TARGET_FMT_plx "]", val, addr); + break; } } qemu_irq_lower(s->irq); } -static void g364fb_ctrl_writew(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - uint32_t old_val = g364fb_ctrl_readl(opaque, addr & ~0x3); - - if (addr & 0x2) - val = (val << 16) | (old_val & 0x0000ffff); - else - val = val | (old_val & 0xffff0000); - g364fb_ctrl_writel(opaque, addr & ~0x3, val); -} - -static void g364fb_ctrl_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - uint32_t old_val = g364fb_ctrl_readl(opaque, addr & ~0x3); - - switch (addr & 3) { - case 0: - val = val | (old_val & 0xffffff00); - break; - case 1: - val = (val << 8) | (old_val & 0xffff00ff); - break; - case 2: - val = (val << 16) | (old_val & 0xff00ffff); - break; - case 3: - val = (val << 24) | (old_val & 0x00ffffff); - break; - } - g364fb_ctrl_writel(opaque, addr & ~0x3, val); -} - static const MemoryRegionOps g364fb_ctrl_ops = { - .old_mmio = { - .read = { - g364fb_ctrl_readb, - g364fb_ctrl_readw, - g364fb_ctrl_readl, - }, - .write = { - g364fb_ctrl_writeb, - g364fb_ctrl_writew, - g364fb_ctrl_writel, - }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, + .read = g364fb_ctrl_read, + .write = g364fb_ctrl_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, + .impl.max_access_size = 4, }; -static int g364fb_load(QEMUFile *f, void *opaque, int version_id) +static int g364fb_post_load(void *opaque, int version_id) { G364State *s = opaque; - unsigned int i, vram_size; - - if (version_id != 1) - return -EINVAL; - - vram_size = qemu_get_be32(f); - if (vram_size < s->vram_size) - return -EINVAL; - qemu_get_buffer(f, s->vram, s->vram_size); - for (i = 0; i < 256; i++) - qemu_get_buffer(f, s->color_palette[i], 3); - for (i = 0; i < 3; i++) - qemu_get_buffer(f, s->cursor_palette[i], 3); - qemu_get_buffer(f, (uint8_t *)s->cursor, sizeof(s->cursor)); - s->cursor_position = qemu_get_be32(f); - s->ctla = qemu_get_be32(f); - s->top_of_screen = qemu_get_be32(f); - s->width = qemu_get_be32(f); - s->height = qemu_get_be32(f); /* force refresh */ g364fb_update_depth(s); @@ -569,53 +489,80 @@ static int g364fb_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void g364fb_save(QEMUFile *f, void *opaque) -{ - G364State *s = opaque; - int i; - - qemu_put_be32(f, s->vram_size); - qemu_put_buffer(f, s->vram, s->vram_size); - for (i = 0; i < 256; i++) - qemu_put_buffer(f, s->color_palette[i], 3); - for (i = 0; i < 3; i++) - qemu_put_buffer(f, s->cursor_palette[i], 3); - qemu_put_buffer(f, (uint8_t *)s->cursor, sizeof(s->cursor)); - qemu_put_be32(f, s->cursor_position); - qemu_put_be32(f, s->ctla); - qemu_put_be32(f, s->top_of_screen); - qemu_put_be32(f, s->width); - qemu_put_be32(f, s->height); -} +static const VMStateDescription vmstate_g364fb = { + .name = "g364fb", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = g364fb_post_load, + .fields = (VMStateField[]) { + VMSTATE_VBUFFER_UINT32(vram, G364State, 1, NULL, 0, vram_size), + VMSTATE_BUFFER_UNSAFE(color_palette, G364State, 0, 256 * 3), + VMSTATE_BUFFER_UNSAFE(cursor_palette, G364State, 0, 9), + VMSTATE_UINT16_ARRAY(cursor, G364State, 512), + VMSTATE_UINT32(cursor_position, G364State), + VMSTATE_UINT32(ctla, G364State), + VMSTATE_UINT32(top_of_screen, G364State), + VMSTATE_UINT32(width, G364State), + VMSTATE_UINT32(height, G364State), + VMSTATE_END_OF_LIST() + } +}; -int g364fb_mm_init(MemoryRegion *system_memory, - target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift, - qemu_irq irq) +static void g364fb_init(DeviceState *dev, G364State *s) { - G364State *s; - MemoryRegion *io_ctrl = g_new(MemoryRegion, 1); - - s = g_malloc0(sizeof(G364State)); - - s->vram_size = 8 * 1024 * 1024; - memory_region_init_ram(&s->vram_region, NULL, "g364fb.vram", s->vram_size); - s->vram = memory_region_get_ram_ptr(&s->vram_region); - s->irq = irq; - - qemu_register_reset(g364fb_reset, s); - register_savevm(NULL, "g364fb", 0, 1, g364fb_save, g364fb_load, s); - g364fb_reset(s); + s->vram = g_malloc0(s->vram_size); s->ds = graphic_console_init(g364fb_update_display, g364fb_invalidate_display, g364fb_screen_dump, NULL, s); - memory_region_add_subregion(system_memory, vram_base, &s->vram_region); + memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000); + memory_region_init_ram_ptr(&s->mem_vram, dev, "vram", + s->vram_size, s->vram); + memory_region_set_coalescing(&s->mem_vram); +} + +typedef struct { + SysBusDevice busdev; + G364State g364; +} G364SysBusState; - memory_region_init_io(io_ctrl, &g364fb_ctrl_ops, s, - "g364fb-ctrl", 0x200000); - memory_region_add_subregion(system_memory, ctrl_base, io_ctrl); +static int g364fb_sysbus_init(SysBusDevice *dev) +{ + G364State *s = &FROM_SYSBUS(G364SysBusState, dev)->g364; + + g364fb_init(&dev->qdev, s); + sysbus_init_irq(dev, &s->irq); + sysbus_init_mmio_region(dev, &s->mem_ctrl); + sysbus_init_mmio_region(dev, &s->mem_vram); return 0; } + +static void g364fb_sysbus_reset(DeviceState *d) +{ + G364SysBusState *s = DO_UPCAST(G364SysBusState, busdev.qdev, d); + g364fb_reset(&s->g364); +} + +static SysBusDeviceInfo g364fb_sysbus_info = { + .init = g364fb_sysbus_init, + .qdev.name = "sysbus-g364", + .qdev.desc = "G364 framebuffer", + .qdev.size = sizeof(G364SysBusState), + .qdev.vmsd = &vmstate_g364fb, + .qdev.reset = g364fb_sysbus_reset, + .qdev.props = (Property[]) { + DEFINE_PROP_HEX32("vram_size", G364SysBusState, g364.vram_size, + 8 * 1024 * 1024), + DEFINE_PROP_END_OF_LIST(), + } +}; + +static void g364fb_register(void) +{ + sysbus_register_withprop(&g364fb_sysbus_info); +} + +device_init(g364fb_register); diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 9d3ff7d555..9a823e1c06 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -92,15 +92,16 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, static int pci_grackle_init_device(SysBusDevice *dev) { GrackleState *s; + int pci_mem_config, pci_mem_data; s = FROM_SYSBUS(GrackleState, dev); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops, - &s->host_state, "pci-data-idx", 0x1000); - sysbus_init_mmio_region(dev, &s->host_state.conf_mem); - sysbus_init_mmio_region(dev, &s->host_state.data_mem); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + pci_mem_data = pci_host_data_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, pci_mem_config); + sysbus_init_mmio(dev, 0x1000, pci_mem_data); qemu_register_reset(pci_grackle_reset, &s->host_state); return 0; diff --git a/hw/gumstix.c b/hw/gumstix.c index d3a4bb4c67..853f7e1ee8 100644 --- a/hw/gumstix.c +++ b/hw/gumstix.c @@ -48,8 +48,7 @@ static void connex_init(ram_addr_t ram_size, { PXA2xxState *cpu; DriveInfo *dinfo; - const MemoryRegionOps *flash_ops; - MemoryRegion *flash = g_new(MemoryRegion, 1); + int be; uint32_t connex_rom = 0x01000000; uint32_t connex_ram = 0x04000000; @@ -64,15 +63,14 @@ static void connex_init(ram_addr_t ram_size, } #ifdef TARGET_WORDS_BIGENDIAN - flash_ops = &pflash_cfi01_ops_be; + be = 1; #else - flash_ops = &pflash_cfi01_ops_le; + be = 0; #endif - memory_region_init_rom_device(flash, flash_ops, - NULL, "connext.rom", connex_rom); - if (!pflash_cfi01_register(0x00000000, flash, + if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "connext.rom", + connex_rom), dinfo->bdrv, sector_len, connex_rom / sector_len, - 2, 0, 0, 0, 0)) { + 2, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); } @@ -89,8 +87,7 @@ static void verdex_init(ram_addr_t ram_size, { PXA2xxState *cpu; DriveInfo *dinfo; - MemoryRegion *flash = g_new(MemoryRegion, 1); - const MemoryRegionOps *flash_ops; + int be; uint32_t verdex_rom = 0x02000000; uint32_t verdex_ram = 0x10000000; @@ -105,15 +102,14 @@ static void verdex_init(ram_addr_t ram_size, } #ifdef TARGET_WORDS_BIGENDIAN - flash_ops = &pflash_cfi01_ops_be; + be = 1; #else - flash_ops = &pflash_cfi01_ops_le; + be = 0; #endif - memory_region_init_rom_device(flash, flash_ops, - NULL, "verdex.rom", verdex_rom); - if (!pflash_cfi01_register(0x00000000, flash, + if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(NULL, "verdex.rom", + verdex_rom), dinfo->bdrv, sector_len, verdex_rom / sector_len, - 2, 0, 0, 0, 0)) { + 2, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); } diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h index 8bf312ab21..6128702533 100644 --- a/hw/hpet_emul.h +++ b/hw/hpet_emul.h @@ -59,13 +59,13 @@ struct hpet_fw_entry uint64_t address; uint16_t min_tick; uint8_t page_prot; -} __attribute__ ((packed)); +} QEMU_PACKED; struct hpet_fw_config { uint8_t count; struct hpet_fw_entry hpet[8]; -} __attribute__ ((packed)); +} QEMU_PACKED; extern struct hpet_fw_config hpet_cfg; #endif diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 29521babf7..f4fa1545bd 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -710,6 +710,7 @@ static void ncq_cb(void *opaque, int ret) DPRINTF(ncq_tfs->drive->port_no, "NCQ transfer tag %d finished\n", ncq_tfs->tag); + bdrv_acct_done(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct); qemu_sglist_destroy(&ncq_tfs->sglist); ncq_tfs->used = 0; } @@ -756,6 +757,10 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, ncq_tfs->is_read = 1; DPRINTF(port, "tag %d aio read %ld\n", ncq_tfs->tag, ncq_tfs->lba); + + bdrv_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct, + (ncq_tfs->sector_count-1) * BDRV_SECTOR_SIZE, + BDRV_ACCT_READ); ncq_tfs->aiocb = dma_bdrv_read(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->sglist, ncq_tfs->lba, ncq_cb, ncq_tfs); @@ -766,6 +771,10 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, ncq_tfs->is_read = 0; DPRINTF(port, "tag %d aio write %ld\n", ncq_tfs->tag, ncq_tfs->lba); + + bdrv_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct, + (ncq_tfs->sector_count-1) * BDRV_SECTOR_SIZE, + BDRV_ACCT_WRITE); ncq_tfs->aiocb = dma_bdrv_write(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->sglist, ncq_tfs->lba, ncq_cb, ncq_tfs); diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index e456193b2b..3c29d93b47 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -244,13 +244,13 @@ typedef struct AHCICmdHdr { uint32_t status; uint64_t tbl_addr; uint32_t reserved[4]; -} __attribute__ ((packed)) AHCICmdHdr; +} QEMU_PACKED AHCICmdHdr; typedef struct AHCI_SG { uint64_t addr; uint32_t reserved; uint32_t flags_size; -} __attribute__ ((packed)) AHCI_SG; +} QEMU_PACKED AHCI_SG; typedef struct AHCIDevice AHCIDevice; @@ -258,6 +258,7 @@ typedef struct NCQTransferState { AHCIDevice *drive; BlockDriverAIOCB *aiocb; QEMUSGList sglist; + BlockAcctCookie acct; int is_read; uint16_t sector_count; uint64_t lba; @@ -320,7 +321,7 @@ typedef struct NCQFrame { uint8_t reserved8; uint8_t reserved9; uint8_t reserved10; -} __attribute__ ((packed)) NCQFrame; +} QEMU_PACKED NCQFrame; void ahci_init(AHCIState *s, DeviceState *qdev, int ports); void ahci_uninit(AHCIState *s); diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index fe2fb0b806..f38d2896ae 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -104,17 +104,20 @@ static void cd_data_to_raw(uint8_t *buf, int lba) memset(buf, 0, 288); } -static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, - int sector_size) +static int cd_read_sector(IDEState *s, int lba, uint8_t *buf, int sector_size) { int ret; switch(sector_size) { case 2048: - ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4); + bdrv_acct_start(s->bs, &s->acct, 4 * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); + ret = bdrv_read(s->bs, (int64_t)lba << 2, buf, 4); + bdrv_acct_done(s->bs, &s->acct); break; case 2352: - ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4); + bdrv_acct_start(s->bs, &s->acct, 4 * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); + ret = bdrv_read(s->bs, (int64_t)lba << 2, buf + 16, 4); + bdrv_acct_done(s->bs, &s->acct); if (ret < 0) return ret; cd_data_to_raw(buf, lba); @@ -181,7 +184,7 @@ void ide_atapi_cmd_reply_end(IDEState *s) } else { /* see if a new sector must be read */ if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { - ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); + ret = cd_read_sector(s, s->lba, s->io_buffer, s->cd_sector_size); if (ret < 0) { ide_transfer_stop(s); ide_atapi_io_error(s, ret); @@ -250,6 +253,7 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) s->io_buffer_index = 0; if (s->atapi_dma) { + bdrv_acct_start(s->bs, &s->acct, size, BDRV_ACCT_READ); s->status = READY_STAT | SEEK_STAT | DRQ_STAT; s->bus->dma->ops->start_dma(s->bus->dma, s, ide_atapi_cmd_read_dma_cb); @@ -322,10 +326,7 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) s->status = READY_STAT | SEEK_STAT; s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; ide_set_irq(s->bus); - eot: - s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); - ide_set_inactive(s); - return; + goto eot; } s->io_buffer_index = 0; @@ -343,9 +344,11 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) #ifdef DEBUG_AIO printf("aio_read_cd: lba=%u n=%d\n", s->lba, n); #endif + s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset); s->bus->dma->iov.iov_len = n * 4 * 512; qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1); + s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2, &s->bus->dma->qiov, n * 4, ide_atapi_cmd_read_dma_cb, s); @@ -355,6 +358,12 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) ASC_MEDIUM_NOT_PRESENT); goto eot; } + + return; +eot: + bdrv_acct_done(s->bs, &s->acct); + s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); + ide_set_inactive(s); } /* start a CD-CDROM read command with DMA */ @@ -368,6 +377,8 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, s->io_buffer_size = 0; s->cd_sector_size = sector_size; + bdrv_acct_start(s->bs, &s->acct, s->packet_transfer_size, BDRV_ACCT_READ); + /* XXX: check if BUSY_STAT should be set */ s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; s->bus->dma->ops->start_dma(s->bus->dma, s, @@ -546,13 +557,13 @@ static void cmd_get_event_status_notification(IDEState *s, uint8_t reserved3[2]; uint16_t len; uint8_t control; - } __attribute__((packed)) *gesn_cdb; + } QEMU_PACKED *gesn_cdb; struct { uint16_t len; uint8_t notification_class; uint8_t supported_events; - } __attribute((packed)) *gesn_event_header; + } QEMU_PACKED *gesn_event_header; enum notification_class_request_type { NCR_RESERVED1 = 1 << 0, diff --git a/hw/ide/core.c b/hw/ide/core.c index d145b19b0c..40abc1edd2 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -473,7 +473,10 @@ void ide_sector_read(IDEState *s) #endif if (n > s->req_nb_sectors) n = s->req_nb_sectors; + + bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); + bdrv_acct_done(s->bs, &s->acct); if (ret != 0) { if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ)) @@ -610,7 +613,10 @@ handle_rw_error: return; eot: - ide_set_inactive(s); + if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { + bdrv_acct_done(s->bs, &s->acct); + } + ide_set_inactive(s); } static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) @@ -619,6 +625,20 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) s->io_buffer_index = 0; s->io_buffer_size = 0; s->dma_cmd = dma_cmd; + + switch (dma_cmd) { + case IDE_DMA_READ: + bdrv_acct_start(s->bs, &s->acct, s->nsector * BDRV_SECTOR_SIZE, + BDRV_ACCT_READ); + break; + case IDE_DMA_WRITE: + bdrv_acct_start(s->bs, &s->acct, s->nsector * BDRV_SECTOR_SIZE, + BDRV_ACCT_WRITE); + break; + default: + break; + } + s->bus->dma->ops->start_dma(s->bus->dma, s, ide_dma_cb); } @@ -641,7 +661,10 @@ void ide_sector_write(IDEState *s) n = s->nsector; if (n > s->req_nb_sectors) n = s->req_nb_sectors; + + bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); + bdrv_acct_done(s->bs, &s->acct); if (ret != 0) { if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY)) @@ -685,6 +708,7 @@ static void ide_flush_cb(void *opaque, int ret) } } + bdrv_acct_done(s->bs, &s->acct); s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); } @@ -698,6 +722,7 @@ void ide_flush_cache(IDEState *s) return; } + bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH); acb = bdrv_aio_flush(s->bs, ide_flush_cb, s); if (acb == NULL) { ide_flush_cb(s, -EIO); diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 02e805f070..7f5ef8de1d 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -440,6 +440,7 @@ struct IDEState { int lba; int cd_sector_size; int atapi_dma; /* true if dma is requested for the packet cmd */ + BlockAcctCookie acct; /* ATA DMA state */ int io_buffer_size; QEMUSGList sg; diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 44fb3fef60..fdf5d75082 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -52,8 +52,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) m->aiocb = NULL; qemu_sglist_destroy(&s->sg); ide_atapi_io_error(s, ret); - io->dma_end(opaque); - return; + goto done; } if (s->io_buffer_size > 0) { @@ -71,8 +70,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) ide_atapi_cmd_ok(s); if (io->len == 0) { - io->dma_end(opaque); - return; + goto done; } /* launch next transfer */ @@ -92,9 +90,14 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) /* Note: media not present is the most likely case */ ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - io->dma_end(opaque); - return; + goto done; } + return; + +done: + bdrv_acct_done(s->bs, &s->acct); + io->dma_end(opaque); + return; } static void pmac_ide_transfer_cb(void *opaque, int ret) @@ -109,8 +112,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) m->aiocb = NULL; qemu_sglist_destroy(&s->sg); ide_dma_error(s); - io->dma_end(io); - return; + goto done; } sector_num = ide_get_sector(s); @@ -130,10 +132,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) } /* end of DMA ? */ - if (io->len == 0) { - io->dma_end(io); - return; + goto done; } /* launch next transfer */ @@ -163,6 +163,12 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) if (!m->aiocb) pmac_ide_transfer_cb(io, -1); + return; +done: + if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { + bdrv_acct_done(s->bs, &s->acct); + } + io->dma_end(io); } static void pmac_ide_transfer(DBDMA_io *io) @@ -172,10 +178,22 @@ static void pmac_ide_transfer(DBDMA_io *io) s->io_buffer_size = 0; if (s->drive_kind == IDE_CD) { + bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); pmac_ide_atapi_transfer_cb(io, 0); return; } + switch (s->dma_cmd) { + case IDE_DMA_READ: + bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); + break; + case IDE_DMA_WRITE: + bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_WRITE); + break; + default: + break; + } + pmac_ide_transfer_cb(io, 0); } diff --git a/hw/integratorcp.c b/hw/integratorcp.c index 3c8982ea29..281410899f 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -13,13 +13,11 @@ #include "boards.h" #include "arm-misc.h" #include "net.h" -#include "exec-memory.h" typedef struct { SysBusDevice busdev; uint32_t memsz; - MemoryRegion flash; - bool flash_mapped; + uint32_t flash_offset; uint32_t cm_osc; uint32_t cm_ctrl; uint32_t cm_lock; @@ -110,15 +108,9 @@ static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset) static void integratorcm_do_remap(integratorcm_state *s, int flash) { if (flash) { - if (s->flash_mapped) { - sysbus_del_memory(&s->busdev, &s->flash); - s->flash_mapped = false; - } + cpu_register_physical_memory(0, 0x100000, IO_MEM_RAM); } else { - if (!s->flash_mapped) { - sysbus_add_memory_overlap(&s->busdev, 0, &s->flash, 1); - s->flash_mapped = true; - } + cpu_register_physical_memory(0, 0x100000, s->flash_offset | IO_MEM_RAM); } //??? tlb_flush (cpu_single_env, 1); } @@ -260,8 +252,7 @@ static int integratorcm_init(SysBusDevice *dev) } memcpy(integrator_spd + 73, "QEMU-MEMORY", 11); s->cm_init = 0x00000112; - memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000); - s->flash_mapped = false; + s->flash_offset = qemu_ram_alloc(NULL, "integrator.flash", 0x100000); iomemtype = cpu_register_io_memory(integratorcm_readfn, integratorcm_writefn, s, @@ -465,9 +456,7 @@ static void integratorcp_init(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { CPUState *env; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); - MemoryRegion *ram_alias = g_new(MemoryRegion, 1); + ram_addr_t ram_offset; qemu_irq pic[32]; qemu_irq *cpu_pic; DeviceState *dev; @@ -480,14 +469,13 @@ static void integratorcp_init(ram_addr_t ram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - memory_region_init_ram(ram, NULL, "integrator.ram", ram_size); + ram_offset = qemu_ram_alloc(NULL, "integrator.ram", ram_size); /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */ /* ??? RAM should repeat to fill physical memory space. */ /* SDRAM at address zero*/ - memory_region_add_subregion(address_space_mem, 0, ram); + cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM); /* And again at address 0x80000000 */ - memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); - memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias); + cpu_register_physical_memory(0x80000000, ram_size, ram_offset | IO_MEM_RAM); dev = qdev_create(NULL, "integrator_core"); qdev_prop_set_uint32(dev, "memsz", ram_size >> 20); diff --git a/hw/leon3.c b/hw/leon3.c index 607ec852fe..a62a9419f3 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -29,7 +29,6 @@ #include "loader.h" #include "elf.h" #include "trace.h" -#include "exec-memory.h" #include "grlib.h" @@ -101,9 +100,7 @@ static void leon3_generic_hw_init(ram_addr_t ram_size, const char *cpu_model) { CPUState *env; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); - MemoryRegion *prom = g_new(MemoryRegion, 1); + ram_addr_t ram_offset, prom_offset; int ret; char *filename; qemu_irq *cpu_irqs = NULL; @@ -142,14 +139,14 @@ static void leon3_generic_hw_init(ram_addr_t ram_size, exit(1); } - memory_region_init_ram(ram, NULL, "leon3.ram", ram_size); - memory_region_add_subregion(address_space_mem, 0x40000000, ram); + ram_offset = qemu_ram_alloc(NULL, "leon3.ram", ram_size); + cpu_register_physical_memory(0x40000000, ram_size, ram_offset | IO_MEM_RAM); /* Allocate BIOS */ prom_size = 8 * 1024 * 1024; /* 8Mb */ - memory_region_init_ram(prom, NULL, "Leon3.bios", prom_size); - memory_region_set_readonly(prom, true); - memory_region_add_subregion(address_space_mem, 0x00000000, prom); + prom_offset = qemu_ram_alloc(NULL, "Leon3.bios", prom_size); + cpu_register_physical_memory(0x00000000, prom_size, + prom_offset | IO_MEM_ROM); /* Load boot prom */ if (bios_name == NULL) { diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index a84007b0ed..d18aad7435 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -28,7 +28,6 @@ #include "elf.h" #include "lm32_hwsetup.h" #include "lm32.h" -#include "exec-memory.h" typedef struct { CPUState *env; @@ -77,9 +76,8 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used, { CPUState *env; DriveInfo *dinfo; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *phys_ram = g_new(MemoryRegion, 1); - MemoryRegion *phys_flash = g_new(MemoryRegion, 1); + ram_addr_t phys_ram; + ram_addr_t phys_flash; qemu_irq *cpu_irq, irq[32]; ResetInfo *reset_info; int i; @@ -107,17 +105,16 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used, reset_info->flash_base = flash_base; - memory_region_init_ram(phys_ram, NULL, "lm32_evr.sdram", ram_size); - memory_region_add_subregion(address_space_mem, ram_base, phys_ram); + phys_ram = qemu_ram_alloc(NULL, "lm32_evr.sdram", ram_size); + cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM); - memory_region_init_rom_device(phys_flash, &pflash_cfi02_ops_be, - NULL, "lm32_evr.flash", flash_size); + phys_flash = qemu_ram_alloc(NULL, "lm32_evr.flash", flash_size); dinfo = drive_get(IF_PFLASH, 0, 0); /* Spansion S29NS128P */ pflash_cfi02_register(flash_base, phys_flash, dinfo ? dinfo->bdrv : NULL, flash_sector_size, flash_size / flash_sector_size, 1, 2, - 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa); + 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); /* create irq lines */ cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1); @@ -167,9 +164,8 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used, { CPUState *env; DriveInfo *dinfo; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *phys_ram = g_new(MemoryRegion, 1); - MemoryRegion *phys_flash = g_new(MemoryRegion, 1); + ram_addr_t phys_ram; + ram_addr_t phys_flash; qemu_irq *cpu_irq, irq[32]; HWSetup *hw; ResetInfo *reset_info; @@ -204,17 +200,16 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used, reset_info->flash_base = flash_base; - memory_region_init_ram(phys_ram, NULL, "lm32_uclinux.sdram", ram_size); - memory_region_add_subregion(address_space_mem, ram_base, phys_ram); + phys_ram = qemu_ram_alloc(NULL, "lm32_uclinux.sdram", ram_size); + cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM); - memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_be, - NULL, "lm32_uclinux.flash", flash_size); + phys_flash = qemu_ram_alloc(NULL, "lm32_uclinux.flash", flash_size); dinfo = drive_get(IF_PFLASH, 0, 0); /* Spansion S29NS128P */ pflash_cfi02_register(flash_base, phys_flash, dinfo ? dinfo->bdrv : NULL, flash_sector_size, flash_size / flash_sector_size, 1, 2, - 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa); + 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); /* create irq lines */ cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1); diff --git a/hw/mainstone.c b/hw/mainstone.c index 82e957149d..4792f0e3ed 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -17,7 +17,6 @@ #include "flash.h" #include "blockdev.h" #include "sysbus.h" -#include "exec-memory.h" /* Device addresses */ #define MST_FPGA_PHYS 0x08000000 @@ -91,8 +90,7 @@ static struct arm_boot_info mainstone_binfo = { .ram_size = 0x04000000, }; -static void mainstone_common_init(MemoryRegion *address_space_mem, - ram_addr_t ram_size, +static void mainstone_common_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model, enum mainstone_model_e model, int arm_id) @@ -103,23 +101,21 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, DeviceState *mst_irq; DriveInfo *dinfo; int i; - MemoryRegion *rom = g_new(MemoryRegion, 1); - MemoryRegion *flashes = g_new(MemoryRegion, 2); - const MemoryRegionOps *flash_ops; + int be; if (!cpu_model) cpu_model = "pxa270-c5"; /* Setup CPU & memory */ cpu = pxa270_init(mainstone_binfo.ram_size, cpu_model); - memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM); - memory_region_set_readonly(rom, true); - memory_region_add_subregion(address_space_mem, 0, rom); + cpu_register_physical_memory(0, MAINSTONE_ROM, + qemu_ram_alloc(NULL, "mainstone.rom", + MAINSTONE_ROM) | IO_MEM_ROM); #ifdef TARGET_WORDS_BIGENDIAN - flash_ops = &pflash_cfi01_ops_be; + be = 1; #else - flash_ops = &pflash_cfi01_ops_le; + be = 0; #endif /* There are two 32MiB flash devices on the board */ for (i = 0; i < 2; i ++) { @@ -130,14 +126,13 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, exit(1); } - memory_region_init_rom_device(&flashes[i], flash_ops, - NULL, (i ? "mainstone.flash1" - : "mainstone.flash0"), - MAINSTONE_FLASH); if (!pflash_cfi01_register(mainstone_flash_base[i], - &flashes[i], dinfo->bdrv, sector_len, - MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, - 0)) { + qemu_ram_alloc(NULL, i ? "mainstone.flash1" : + "mainstone.flash0", + MAINSTONE_FLASH), + dinfo->bdrv, sector_len, + MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0, + be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); } @@ -175,7 +170,7 @@ static void mainstone_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - mainstone_common_init(get_system_memory(), ram_size, kernel_filename, + mainstone_common_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196); } diff --git a/hw/mcf5208.c b/hw/mcf5208.c index 1c2c0c48aa..8fe507f82f 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -13,7 +13,6 @@ #include "boards.h" #include "loader.h" #include "elf.h" -#include "exec-memory.h" #define SYS_FREQ 66000000 @@ -28,7 +27,6 @@ #define PCSR_PRE_MASK 0x0f00 typedef struct { - MemoryRegion iomem; qemu_irq irq; ptimer_state *timer; uint16_t pcsr; @@ -45,7 +43,7 @@ static void m5208_timer_update(m5208_timer_state *s) } static void m5208_timer_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) + uint32_t value) { m5208_timer_state *s = (m5208_timer_state *)opaque; int prescale; @@ -106,8 +104,7 @@ static void m5208_timer_trigger(void *opaque) m5208_timer_update(s); } -static uint64_t m5208_timer_read(void *opaque, target_phys_addr_t addr, - unsigned size) +static uint32_t m5208_timer_read(void *opaque, target_phys_addr_t addr) { m5208_timer_state *s = (m5208_timer_state *)opaque; switch (addr) { @@ -123,14 +120,19 @@ static uint64_t m5208_timer_read(void *opaque, target_phys_addr_t addr, } } -static const MemoryRegionOps m5208_timer_ops = { - .read = m5208_timer_read, - .write = m5208_timer_write, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUReadMemoryFunc * const m5208_timer_readfn[] = { + m5208_timer_read, + m5208_timer_read, + m5208_timer_read }; -static uint64_t m5208_sys_read(void *opaque, target_phys_addr_t addr, - unsigned size) +static CPUWriteMemoryFunc * const m5208_timer_writefn[] = { + m5208_timer_write, + m5208_timer_write, + m5208_timer_write +}; + +static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr) { switch (addr) { case 0x110: /* SDCS0 */ @@ -152,36 +154,45 @@ static uint64_t m5208_sys_read(void *opaque, target_phys_addr_t addr, } static void m5208_sys_write(void *opaque, target_phys_addr_t addr, - uint64_t value, unsigned size) + uint32_t value) { hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr); } -static const MemoryRegionOps m5208_sys_ops = { - .read = m5208_sys_read, - .write = m5208_sys_write, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUReadMemoryFunc * const m5208_sys_readfn[] = { + m5208_sys_read, + m5208_sys_read, + m5208_sys_read +}; + +static CPUWriteMemoryFunc * const m5208_sys_writefn[] = { + m5208_sys_write, + m5208_sys_write, + m5208_sys_write }; -static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic) +static void mcf5208_sys_init(qemu_irq *pic) { - MemoryRegion *iomem = g_new(MemoryRegion, 1); + int iomemtype; m5208_timer_state *s; QEMUBH *bh; int i; + iomemtype = cpu_register_io_memory(m5208_sys_readfn, + m5208_sys_writefn, NULL, + DEVICE_NATIVE_ENDIAN); /* SDRAMC. */ - memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000); - memory_region_add_subregion(address_space, 0xfc0a8000, iomem); + cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype); /* Timers. */ for (i = 0; i < 2; i++) { s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state)); bh = qemu_bh_new(m5208_timer_trigger, s); s->timer = ptimer_init(bh); - memory_region_init_io(&s->iomem, &m5208_timer_ops, s, - "m5208-timer", 0x00004000); - memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i, - &s->iomem); + iomemtype = cpu_register_io_memory(m5208_timer_readfn, + m5208_timer_writefn, s, + DEVICE_NATIVE_ENDIAN); + cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000, + iomemtype); s->irq = pic[4 + i]; } } @@ -196,9 +207,6 @@ static void mcf5208evb_init(ram_addr_t ram_size, uint64_t elf_entry; target_phys_addr_t entry; qemu_irq *pic; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); - MemoryRegion *sram = g_new(MemoryRegion, 1); if (!cpu_model) cpu_model = "m5208"; @@ -213,12 +221,12 @@ static void mcf5208evb_init(ram_addr_t ram_size, /* TODO: Configure BARs. */ /* DRAM at 0x40000000 */ - memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size); - memory_region_add_subregion(address_space_mem, 0x40000000, ram); + cpu_register_physical_memory(0x40000000, ram_size, + qemu_ram_alloc(NULL, "mcf5208.ram", ram_size) | IO_MEM_RAM); /* Internal SRAM. */ - memory_region_init_ram(sram, NULL, "mcf5208.sram", 16384); - memory_region_add_subregion(address_space_mem, 0x80000000, sram); + cpu_register_physical_memory(0x80000000, 16384, + qemu_ram_alloc(NULL, "mcf5208.sram", 16384) | IO_MEM_RAM); /* Internal peripherals. */ pic = mcf_intc_init(0xfc048000, env); @@ -227,7 +235,7 @@ static void mcf5208evb_init(ram_addr_t ram_size, mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]); mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]); - mcf5208_sys_init(address_space_mem, pic); + mcf5208_sys_init(pic); if (nb_nics > 1) { fprintf(stderr, "Too many NICs\n"); diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c index fb48e37187..cd360264c1 100644 --- a/hw/milkymist-minimac2.c +++ b/hw/milkymist-minimac2.c @@ -97,8 +97,6 @@ struct MilkymistMinimac2State { NICConf conf; char *phy_model; target_phys_addr_t buffers_base; - MemoryRegion buffers; - MemoryRegion regs_region; qemu_irq rx_irq; qemu_irq tx_irq; @@ -322,8 +320,8 @@ static ssize_t minimac2_rx(VLANClientState *nc, const uint8_t *buf, size_t size) return size; } -static uint64_t -minimac2_read(void *opaque, target_phys_addr_t addr, unsigned size) +static uint32_t +minimac2_read(void *opaque, target_phys_addr_t addr) { MilkymistMinimac2State *s = opaque; uint32_t r = 0; @@ -352,8 +350,7 @@ minimac2_read(void *opaque, target_phys_addr_t addr, unsigned size) } static void -minimac2_write(void *opaque, target_phys_addr_t addr, uint64_t value, - unsigned size) +minimac2_write(void *opaque, target_phys_addr_t addr, uint32_t value) { MilkymistMinimac2State *s = opaque; @@ -398,14 +395,16 @@ minimac2_write(void *opaque, target_phys_addr_t addr, uint64_t value, } } -static const MemoryRegionOps minimac2_ops = { - .read = minimac2_read, - .write = minimac2_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUReadMemoryFunc * const minimac2_read_fn[] = { + NULL, + NULL, + &minimac2_read, +}; + +static CPUWriteMemoryFunc * const minimac2_write_fn[] = { + NULL, + NULL, + &minimac2_write, }; static int minimac2_can_rx(VLANClientState *nc) @@ -458,23 +457,25 @@ static NetClientInfo net_milkymist_minimac2_info = { static int milkymist_minimac2_init(SysBusDevice *dev) { MilkymistMinimac2State *s = FROM_SYSBUS(typeof(*s), dev); + int regs; + ram_addr_t buffers; size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE); sysbus_init_irq(dev, &s->rx_irq); sysbus_init_irq(dev, &s->tx_irq); - memory_region_init_io(&s->regs_region, &minimac2_ops, s, - "minimac2-mmio", R_MAX * 4); - sysbus_init_mmio_region(dev, &s->regs_region); + regs = cpu_register_io_memory(minimac2_read_fn, minimac2_write_fn, s, + DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio(dev, R_MAX * 4, regs); /* register buffers memory */ - memory_region_init_ram(&s->buffers, NULL, "milkymist_minimac2.buffers", - buffers_size); - s->rx0_buf = memory_region_get_ram_ptr(&s->buffers); + buffers = qemu_ram_alloc(NULL, "milkymist_minimac2.buffers", buffers_size); + s->rx0_buf = qemu_get_ram_ptr(buffers); s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE; s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE; - sysbus_add_memory(dev, s->buffers_base, &s->buffers); + cpu_register_physical_memory(s->buffers_base, buffers_size, + buffers | IO_MEM_RAM); qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf, diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c index ef4d9ee2ce..fe4eedb2cb 100644 --- a/hw/milkymist-softusb.c +++ b/hw/milkymist-softusb.c @@ -49,9 +49,6 @@ struct MilkymistSoftUsbState { HIDState hid_kbd; HIDState hid_mouse; - MemoryRegion regs_region; - MemoryRegion pmem; - MemoryRegion dmem; qemu_irq irq; /* device properties */ @@ -71,8 +68,7 @@ struct MilkymistSoftUsbState { }; typedef struct MilkymistSoftUsbState MilkymistSoftUsbState; -static uint64_t softusb_read(void *opaque, target_phys_addr_t addr, - unsigned size) +static uint32_t softusb_read(void *opaque, target_phys_addr_t addr) { MilkymistSoftUsbState *s = opaque; uint32_t r = 0; @@ -95,8 +91,7 @@ static uint64_t softusb_read(void *opaque, target_phys_addr_t addr, } static void -softusb_write(void *opaque, target_phys_addr_t addr, uint64_t value, - unsigned size) +softusb_write(void *opaque, target_phys_addr_t addr, uint32_t value) { MilkymistSoftUsbState *s = opaque; @@ -115,14 +110,16 @@ softusb_write(void *opaque, target_phys_addr_t addr, uint64_t value, } } -static const MemoryRegionOps softusb_mmio_ops = { - .read = softusb_read, - .write = softusb_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, +static CPUReadMemoryFunc * const softusb_read_fn[] = { + NULL, + NULL, + &softusb_read, +}; + +static CPUWriteMemoryFunc * const softusb_write_fn[] = { + NULL, + NULL, + &softusb_write, }; static inline void softusb_read_dmem(MilkymistSoftUsbState *s, @@ -259,20 +256,23 @@ static void milkymist_softusb_reset(DeviceState *d) static int milkymist_softusb_init(SysBusDevice *dev) { MilkymistSoftUsbState *s = FROM_SYSBUS(typeof(*s), dev); + int softusb_regs; + ram_addr_t pmem_ram; + ram_addr_t dmem_ram; sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->regs_region, &softusb_mmio_ops, s, - "milkymist-softusb", R_MAX * 4); - sysbus_init_mmio_region(dev, &s->regs_region); + softusb_regs = cpu_register_io_memory(softusb_read_fn, softusb_write_fn, s, + DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio(dev, R_MAX * 4, softusb_regs); /* register pmem and dmem */ - memory_region_init_ram(&s->pmem, NULL, "milkymist_softusb.pmem", - s->pmem_size); - sysbus_add_memory(dev, s->pmem_base, &s->pmem); - memory_region_init_ram(&s->dmem, NULL, "milkymist_softusb.dmem", - s->dmem_size); - sysbus_add_memory(dev, s->dmem_base, &s->dmem); + pmem_ram = qemu_ram_alloc(NULL, "milkymist_softusb.pmem", s->pmem_size); + cpu_register_physical_memory(s->pmem_base, s->pmem_size, + pmem_ram | IO_MEM_RAM); + dmem_ram = qemu_ram_alloc(NULL, "milkymist_softusb.dmem", s->dmem_size); + cpu_register_physical_memory(s->dmem_base, s->dmem_size, + dmem_ram | IO_MEM_RAM); hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain); hid_init(&s->hid_mouse, HID_MOUSE, softusb_mouse_hid_datain); diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c index 790cdcb41c..953d42f16b 100644 --- a/hw/milkymist-tmu2.c +++ b/hw/milkymist-tmu2.c @@ -73,7 +73,7 @@ enum { struct vertex { int x; int y; -} __attribute__((packed)); +} QEMU_PACKED; struct MilkymistTMU2State { SysBusDevice busdev; diff --git a/hw/milkymist.c b/hw/milkymist.c index ef21ccaba1..93288c8401 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -29,7 +29,6 @@ #include "blockdev.h" #include "milkymist-hw.h" #include "lm32.h" -#include "exec-memory.h" #define BIOS_FILENAME "mmone-bios.bin" #define BIOS_OFFSET 0x00860000 @@ -82,9 +81,8 @@ milkymist_init(ram_addr_t ram_size_not_used, CPUState *env; int kernel_size; DriveInfo *dinfo; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *phys_sdram = g_new(MemoryRegion, 1); - MemoryRegion *phys_flash = g_new(MemoryRegion, 1); + ram_addr_t phys_sdram; + ram_addr_t phys_flash; qemu_irq irq[32], *cpu_irq; int i; char *bios_filename; @@ -111,17 +109,17 @@ milkymist_init(ram_addr_t ram_size_not_used, cpu_lm32_set_phys_msb_ignore(env, 1); - memory_region_init_ram(phys_sdram, NULL, "milkymist.sdram", sdram_size); - memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram); + phys_sdram = qemu_ram_alloc(NULL, "milkymist.sdram", sdram_size); + cpu_register_physical_memory(sdram_base, sdram_size, + phys_sdram | IO_MEM_RAM); - memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_be, - NULL, "milkymist.flash", flash_size); + phys_flash = qemu_ram_alloc(NULL, "milkymist.flash", flash_size); dinfo = drive_get(IF_PFLASH, 0, 0); /* Numonyx JS28F256J3F105 */ pflash_cfi01_register(flash_base, phys_flash, dinfo ? dinfo->bdrv : NULL, flash_sector_size, flash_size / flash_sector_size, 2, - 0x00, 0x89, 0x00, 0x1d); + 0x00, 0x89, 0x00, 0x1d, 1); /* create irq lines */ cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1); @@ -2,19 +2,12 @@ #define HW_MIPS_H /* Definitions for mips board emulation. */ -#include "memory.h" - /* gt64xxx.c */ PCIBus *gt64120_register(qemu_irq *pic); /* bonito.c */ PCIBus *bonito_init(qemu_irq *pic); -/* g364fb.c */ -int g364fb_mm_init(MemoryRegion *system_memory, target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift, - qemu_irq irq); - /* mipsnet.c */ void mipsnet_init(int base, qemu_irq irq, NICInfo *nd); diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index a74108646c..f3c9f93204 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -195,8 +195,20 @@ void mips_jazz_init (ram_addr_t ram_size, /* Video card */ switch (jazz_model) { case JAZZ_MAGNUM: - g364fb_mm_init(get_system_memory(), 0x40000000, 0x60000000, 0, - rc4030[3]); + dev = qdev_create(NULL, "sysbus-g364"); + qdev_init_nofail(dev); + sysbus = sysbus_from_qdev(dev); + sysbus_mmio_map(sysbus, 0, 0x60080000); + sysbus_mmio_map(sysbus, 1, 0x40000000); + sysbus_connect_irq(sysbus, 0, rc4030[3]); + { + /* Simple ROM, so user doesn't have to provide one */ + ram_addr_t rom_offset = qemu_ram_alloc(NULL, "g364fb.rom", 0x80000); + uint8_t *rom = qemu_get_ram_ptr(rom_offset); + cpu_register_physical_memory(0x60000000, 0x80000, + rom_offset | IO_MEM_ROM); + rom[0] = 0x10; /* Mips G364 */ + } break; case JAZZ_PICA61: isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory()); diff --git a/hw/mips_malta.c b/hw/mips_malta.c index b5c9bcfa51..a0adb566ab 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -46,7 +46,6 @@ #include "elf.h" #include "mc146818rtc.h" #include "blockdev.h" -#include "exec-memory.h" //#define DEBUG_BOARD_INIT @@ -733,6 +732,12 @@ static int64_t load_kernel (void) return kernel_entry; } +static void malta_mips_config(CPUState *env) +{ + env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) | + ((smp_cpus * env->nr_threads - 1) << CP0MVPC0_PTC); +} + static void main_cpu_reset(void *opaque) { CPUState *env = opaque; @@ -744,6 +749,8 @@ static void main_cpu_reset(void *opaque) if (loaderparams.kernel_filename) { env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); } + + malta_mips_config(env); } static void cpu_request_exit(void *opaque, int irq, int level) @@ -763,10 +770,7 @@ void mips_malta_init (ram_addr_t ram_size, { char *filename; ram_addr_t ram_offset; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *bios = g_new(MemoryRegion, 1); - MemoryRegion *bios_1e0 = g_new(MemoryRegion, 1); - MemoryRegion *bios_1fc = g_new(MemoryRegion, 1); + ram_addr_t bios_offset; target_long bios_size; int64_t kernel_entry; PCIBus *pci_bus; @@ -781,7 +785,7 @@ void mips_malta_init (ram_addr_t ram_size, DriveInfo *fd[MAX_FD]; int fl_idx = 0; int fl_sectors = 0; - const MemoryRegionOps *bios_ops; + int be; /* Make sure the first 3 serial ports are associated with a device. */ for(i = 0; i < 3; i++) { @@ -800,12 +804,19 @@ void mips_malta_init (ram_addr_t ram_size, cpu_model = "24Kf"; #endif } - env = cpu_init(cpu_model); - if (!env) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); + + for (i = 0; i < smp_cpus; i++) { + env = cpu_init(cpu_model); + if (!env) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + /* Init internal devices */ + cpu_mips_irq_init_cpu(env); + cpu_mips_clock_init(env); + qemu_register_reset(main_cpu_reset, env); } - qemu_register_reset(main_cpu_reset, env); + env = first_cpu; /* allocate RAM */ if (ram_size > (256 << 20)) { @@ -814,24 +825,23 @@ void mips_malta_init (ram_addr_t ram_size, ((unsigned int)ram_size / (1 << 20))); exit(1); } -#ifdef TARGET_WORDS_BIGENDIAN - bios_ops = &pflash_cfi01_ops_be; -#else - bios_ops = &pflash_cfi01_ops_le; -#endif - ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size); - memory_region_init_rom_device(bios, bios_ops, NULL, - "mips_malta.bios", BIOS_SIZE); + bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE); + cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM); /* Map the bios at two physical locations, as on the real board. */ - memory_region_init_alias(bios_1e0, "bios-1e0", bios, 0, BIOS_SIZE); - memory_region_add_subregion(address_space_mem, 0x1e000000LL, bios_1e0); - memory_region_init_alias(bios_1fc, "bios-1fc", bios, 0, BIOS_SIZE); - memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios_1fc); + cpu_register_physical_memory(0x1e000000LL, + BIOS_SIZE, bios_offset | IO_MEM_ROM); + cpu_register_physical_memory(0x1fc00000LL, + BIOS_SIZE, bios_offset | IO_MEM_ROM); +#ifdef TARGET_WORDS_BIGENDIAN + be = 1; +#else + be = 0; +#endif /* FPGA */ malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]); @@ -843,7 +853,7 @@ void mips_malta_init (ram_addr_t ram_size, loaderparams.kernel_cmdline = kernel_cmdline; loaderparams.initrd_filename = initrd_filename; kernel_entry = load_kernel(); - write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry); + write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry); } else { dinfo = drive_get(IF_PFLASH, 0, fl_idx); if (dinfo) { @@ -852,13 +862,13 @@ void mips_malta_init (ram_addr_t ram_size, fl_sectors = bios_size >> 16; #ifdef DEBUG_BOARD_INIT printf("Register parallel flash %d size " TARGET_FMT_lx " at " - "addr %08llx '%s' %x\n", - fl_idx, bios_size, 0x1e000000LL, + "offset %08lx addr %08llx '%s' %x\n", + fl_idx, bios_size, bios_offset, 0x1e000000LL, bdrv_get_device_name(dinfo->bdrv), fl_sectors); #endif - pflash_cfi01_register(0x1e000000LL, bios, + pflash_cfi01_register(0x1e000000LL, bios_offset, dinfo->bdrv, 65536, fl_sectors, - 4, 0x0000, 0x0000, 0x0000, 0x0000); + 4, 0x0000, 0x0000, 0x0000, 0x0000, be); fl_idx++; } else { /* Load a BIOS image. */ @@ -883,7 +893,7 @@ void mips_malta_init (ram_addr_t ram_size, a neat trick which allows bi-endian firmware. */ #ifndef TARGET_WORDS_BIGENDIAN { - uint32_t *addr = memory_region_get_ram_ptr(bios); + uint32_t *addr = qemu_get_ram_ptr(bios_offset);; uint32_t *end = addr + bios_size; while (addr < end) { bswap32s(addr); @@ -895,7 +905,7 @@ void mips_malta_init (ram_addr_t ram_size, /* Board ID = 0x420 (Malta Board with CoreLV) XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should map to the board ID. */ - stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420); + stl_p(qemu_get_ram_ptr(bios_offset) + 0x10, 0x00000420); /* Init internal devices */ cpu_mips_irq_init_cpu(env); @@ -960,6 +970,7 @@ static QEMUMachine mips_malta_machine = { .name = "malta", .desc = "MIPS Malta Core LV", .init = mips_malta_init, + .max_cpus = 16, .is_default = 1, }; diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 51dc8684be..9d90568e4e 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -23,7 +23,6 @@ #include "elf.h" #include "mc146818rtc.h" #include "blockdev.h" -#include "exec-memory.h" #define MAX_IDE_BUS 2 @@ -164,8 +163,7 @@ void mips_r4k_init (ram_addr_t ram_size, { char *filename; ram_addr_t ram_offset; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *bios = g_new(MemoryRegion, 1); + ram_addr_t bios_offset; int bios_size; CPUState *env; ResetData *reset_info; @@ -229,20 +227,18 @@ void mips_r4k_init (ram_addr_t ram_size, be = 0; #endif if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) { - memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE); - memory_region_set_readonly(bios, true); - memory_region_add_subregion(address_space_mem, 0x1fc00000, bios); + bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", BIOS_SIZE); + cpu_register_physical_memory(0x1fc00000, BIOS_SIZE, + bios_offset | IO_MEM_ROM); + load_image_targphys(filename, 0x1fc00000, BIOS_SIZE); } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) { uint32_t mips_rom = 0x00400000; - memory_region_init_rom_device(bios, - (be ? &pflash_cfi01_ops_be - : &pflash_cfi01_ops_le), - NULL, "mips_r4k.bios", mips_rom); - if (!pflash_cfi01_register(0x1fc00000, bios, + bios_offset = qemu_ram_alloc(NULL, "mips_r4k.bios", mips_rom); + if (!pflash_cfi01_register(0x1fc00000, bios_offset, dinfo->bdrv, sector_len, mips_rom / sector_len, - 4, 0, 0, 0, 0)) { + 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); } } diff --git a/hw/musicpal.c b/hw/musicpal.c index 5e74ee7fd7..63dd391176 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -1502,7 +1502,6 @@ static void musicpal_init(ram_addr_t ram_size, unsigned long flash_size; DriveInfo *dinfo; ram_addr_t sram_off; - MemoryRegion *flash = g_new(MemoryRegion, 1); if (!cpu_model) { cpu_model = "arm926"; @@ -1566,23 +1565,21 @@ static void musicpal_init(ram_addr_t ram_size, * image is smaller than 32 MB. */ #ifdef TARGET_WORDS_BIGENDIAN - memory_region_init_rom_device(flash, &pflash_cfi02_ops_be, - NULL, "musicpal.flash", flash_size); - pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, flash, + pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL, + "musicpal.flash", flash_size), dinfo->bdrv, 0x10000, (flash_size + 0xffff) >> 16, MP_FLASH_SIZE_MAX / flash_size, 2, 0x00BF, 0x236D, 0x0000, 0x0000, - 0x5555, 0x2AAA); + 0x5555, 0x2AAA, 1); #else - memory_region_init_rom_device(flash, &pflash_cfi02_ops_le, - NULL, "musicpal.flash", flash_size); - pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, flash, + pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(NULL, + "musicpal.flash", flash_size), dinfo->bdrv, 0x10000, (flash_size + 0xffff) >> 16, MP_FLASH_SIZE_MAX / flash_size, 2, 0x00BF, 0x236D, 0x0000, 0x0000, - 0x5555, 0x2AAA); + 0x5555, 0x2AAA, 0); #endif } diff --git a/hw/nseries.c b/hw/nseries.c index f7aae7a59e..af287dd6dc 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -32,7 +32,7 @@ #include "bt.h" #include "loader.h" #include "blockdev.h" -#include "tusb6010.h" +#include "sysbus.h" /* Nokia N8x0 support */ struct n800_s { @@ -49,10 +49,10 @@ struct n800_s { int keymap[0x80]; DeviceState *kbd; - TUSBState *usb; + DeviceState *usb; void *retu; void *tahvo; - void *nand; + DeviceState *nand; }; /* GPIO pins */ @@ -167,13 +167,21 @@ static void n8x0_nand_setup(struct n800_s *s) char *otp_region; DriveInfo *dinfo; - dinfo = drive_get(IF_MTD, 0, 0); + s->nand = qdev_create(NULL, "onenand"); + qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG); /* Either 0x40 or 0x48 are OK for the device ID */ - s->nand = onenand_init(dinfo ? dinfo->bdrv : 0, - NAND_MFR_SAMSUNG, 0x48, 0, 1, - qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO)); - omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update, - onenand_base_unmap, s->nand); + qdev_prop_set_uint16(s->nand, "device_id", 0x48); + qdev_prop_set_uint16(s->nand, "version_id", 0); + qdev_prop_set_int32(s->nand, "shift", 1); + dinfo = drive_get(IF_MTD, 0, 0); + if (dinfo && dinfo->bdrv) { + qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv); + } + qdev_init_nofail(s->nand); + sysbus_connect_irq(sysbus_from_qdev(s->nand), 0, + qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO)); + omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, + sysbus_mmio_get_region(sysbus_from_qdev(s->nand), 0)); otp_region = onenand_raw_otp(s->nand); memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac)); @@ -756,27 +764,21 @@ static void n8x0_uart_setup(struct n800_s *s) omap_uart_attach(s->cpu->uart[BT_UART], radio); } -static void n8x0_usb_power_cb(void *opaque, int line, int level) -{ - struct n800_s *s = opaque; - - tusb6010_power(s->usb, level); -} - static void n8x0_usb_setup(struct n800_s *s) { - qemu_irq tusb_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TUSB_INT_GPIO); - qemu_irq tusb_pwr = qemu_allocate_irqs(n8x0_usb_power_cb, s, 1)[0]; - TUSBState *tusb = tusb6010_init(tusb_irq); - + SysBusDevice *dev; + s->usb = qdev_create(NULL, "tusb6010"); + dev = sysbus_from_qdev(s->usb); + qdev_init_nofail(s->usb); + sysbus_connect_irq(dev, 0, + qdev_get_gpio_in(s->cpu->gpio, N8X0_TUSB_INT_GPIO)); /* Using the NOR interface */ omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_ASYNC_CS, - tusb6010_async_io(tusb), NULL, NULL, tusb); + sysbus_mmio_get_region(dev, 0)); omap_gpmc_attach(s->cpu->gpmc, N8X0_USB_SYNC_CS, - tusb6010_sync_io(tusb), NULL, NULL, tusb); - - s->usb = tusb; - qdev_connect_gpio_out(s->cpu->gpio, N8X0_TUSB_ENABLE_GPIO, tusb_pwr); + sysbus_mmio_get_region(dev, 1)); + qdev_connect_gpio_out(s->cpu->gpio, N8X0_TUSB_ENABLE_GPIO, + qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */ } /* Setup done before the main bootloader starts by some early setup code @@ -118,11 +118,12 @@ void omap_sdrc_reset(struct omap_sdrc_s *s); /* OMAP2 general purpose memory controller */ struct omap_gpmc_s; -struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq); +struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu, + target_phys_addr_t base, + qemu_irq irq, qemu_irq drq); void omap_gpmc_reset(struct omap_gpmc_s *s); -void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem, - void (*base_upd)(void *opaque, target_phys_addr_t new), - void (*unmap)(void *opaque), void *opaque); +void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem); +void omap_gpmc_attach_nand(struct omap_gpmc_s *s, int cs, DeviceState *nand); /* * Common IRQ numbers for level 1 interrupt handler @@ -788,6 +789,7 @@ i2c_bus *omap_i2c_bus(struct omap_i2c_s *s); # define cpu_is_omap2420(cpu) (cpu->mpu_model == omap2420) # define cpu_is_omap2430(cpu) (cpu->mpu_model == omap2430) # define cpu_is_omap3430(cpu) (cpu->mpu_model == omap3430) +# define cpu_is_omap3630(cpu) (cpu->mpu_model == omap3630) # define cpu_is_omap15xx(cpu) \ (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu)) @@ -799,7 +801,8 @@ i2c_bus *omap_i2c_bus(struct omap_i2c_s *s); # define cpu_class_omap1(cpu) \ (cpu_is_omap15xx(cpu) || cpu_is_omap16xx(cpu)) # define cpu_class_omap2(cpu) cpu_is_omap24xx(cpu) -# define cpu_class_omap3(cpu) cpu_is_omap3430(cpu) +# define cpu_class_omap3(cpu) \ + (cpu_is_omap3430(cpu) || cpu_is_omap3630(cpu)) struct omap_mpu_state_s { enum omap_mpu_model { @@ -813,6 +816,7 @@ struct omap_mpu_state_s { omap2423, omap2430, omap3430, + omap3630, } mpu_model; CPUState *env; diff --git a/hw/omap2.c b/hw/omap2.c index 7e5820a97b..ca088d9f53 100644 --- a/hw/omap2.c +++ b/hw/omap2.c @@ -2402,7 +2402,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size, sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5)); s->sdrc = omap_sdrc_init(0x68009000); - s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]); + s->gpmc = omap_gpmc_init(s, 0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ], + s->drq[OMAP24XX_DMA_GPMC]); dinfo = drive_get(IF_SD, 0, 0); if (!dinfo) { diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c index 673dddd237..02f0c52107 100644 --- a/hw/omap_gpmc.c +++ b/hw/omap_gpmc.c @@ -27,82 +27,410 @@ /* General-Purpose Memory Controller */ struct omap_gpmc_s { qemu_irq irq; + qemu_irq drq; MemoryRegion iomem; + int accept_256; + uint8_t revision; uint8_t sysconfig; uint16_t irqst; uint16_t irqen; + uint16_t lastirq; uint16_t timeout; uint16_t config; - uint32_t prefconfig[2]; - int prefcontrol; - int preffifo; - int prefcount; struct omap_gpmc_cs_file_s { uint32_t config[7]; - target_phys_addr_t base; - size_t size; MemoryRegion *iomem; MemoryRegion container; - void (*base_update)(void *opaque, target_phys_addr_t new); - void (*unmap)(void *opaque); - void *opaque; + MemoryRegion nandiomem; + DeviceState *dev; } cs_file[8]; int ecc_cs; int ecc_ptr; uint32_t ecc_cfg; ECCState ecc[9]; + struct prefetch { + uint32_t config1; /* GPMC_PREFETCH_CONFIG1 */ + uint32_t transfercount; /* GPMC_PREFETCH_CONFIG2:TRANSFERCOUNT */ + int startengine; /* GPMC_PREFETCH_CONTROL:STARTENGINE */ + int fifopointer; /* GPMC_PREFETCH_STATUS:FIFOPOINTER */ + int count; /* GPMC_PREFETCH_STATUS:COUNTVALUE */ + MemoryRegion iomem; + uint8_t fifo[64]; + } prefetch; }; +#define OMAP_GPMC_8BIT 0 +#define OMAP_GPMC_16BIT 1 +#define OMAP_GPMC_NOR 0 +#define OMAP_GPMC_NAND 2 + +static int omap_gpmc_devtype(struct omap_gpmc_cs_file_s *f) +{ + return (f->config[0] >> 10) & 3; +} + +static int omap_gpmc_devsize(struct omap_gpmc_cs_file_s *f) +{ + /* devsize field is really 2 bits but we ignore the high + * bit to ensure consistent behaviour if the guest sets + * it (values 2 and 3 are reserved in the TRM) + */ + return (f->config[0] >> 12) & 1; +} + +/* Extract the chip-select value from the prefetch config1 register */ +static int prefetch_cs(uint32_t config1) +{ + return (config1 >> 24) & 7; +} + +static int prefetch_threshold(uint32_t config1) +{ + return (config1 >> 8) & 0x7f; +} + static void omap_gpmc_int_update(struct omap_gpmc_s *s) { - qemu_set_irq(s->irq, s->irqen & s->irqst); + /* The TRM is a bit unclear, but it seems to say that + * the TERMINALCOUNTSTATUS bit is set only on the + * transition when the prefetch engine goes from + * active to inactive, whereas the FIFOEVENTSTATUS + * bit is held high as long as the fifo has at + * least THRESHOLD bytes available. + * So we do the latter here, but TERMINALCOUNTSTATUS + * is set elsewhere. + */ + if (s->prefetch.fifopointer >= prefetch_threshold(s->prefetch.config1)) { + s->irqst |= 1; + } + if ((s->irqen & s->irqst) != s->lastirq) { + s->lastirq = s->irqen & s->irqst; + qemu_set_irq(s->irq, s->lastirq); + } } -static void omap_gpmc_cs_map(struct omap_gpmc_cs_file_s *f, int base, int mask) +static void omap_gpmc_dma_update(struct omap_gpmc_s *s, int value) { - /* TODO: check for overlapping regions and report access errors */ - if ((mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf) || - (base < 0 || base >= 0x40) || - (base & 0x0f & ~mask)) { - fprintf(stderr, "%s: wrong cs address mapping/decoding!\n", - __FUNCTION__); + if (s->prefetch.config1 & 4) { + qemu_set_irq(s->drq, value); + } +} + +/* Access functions for when a NAND-like device is mapped into memory: + * all addresses in the region behave like accesses to the relevant + * GPMC_NAND_DATA_i register (which is actually implemented to call these) + */ +static uint64_t omap_nand_read(void *opaque, target_phys_addr_t addr, + unsigned size) +{ + struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque; + uint64_t v; + nand_setpins(f->dev, 0, 0, 0, 1, 0); + switch (omap_gpmc_devsize(f)) { + case OMAP_GPMC_8BIT: + v = nand_getio(f->dev); + if (size == 1) { + return v; + } + v |= (nand_getio(f->dev) << 8); + if (size == 2) { + return v; + } + v |= (nand_getio(f->dev) << 16); + v |= (nand_getio(f->dev) << 24); + return v; + case OMAP_GPMC_16BIT: + v = nand_getio(f->dev); + if (size == 1) { + /* 8 bit read from 16 bit device : probably a guest bug */ + return v & 0xff; + } + if (size == 2) { + return v; + } + v |= (nand_getio(f->dev) << 16); + return v; + default: + abort(); + } +} + +static void omap_nand_setio(DeviceState *dev, uint64_t value, + int nandsize, int size) +{ + /* Write the specified value to the NAND device, respecting + * both size of the NAND device and size of the write access. + */ + switch (nandsize) { + case OMAP_GPMC_8BIT: + switch (size) { + case 1: + nand_setio(dev, value & 0xff); + break; + case 2: + nand_setio(dev, value & 0xff); + nand_setio(dev, (value >> 8) & 0xff); + break; + case 4: + default: + nand_setio(dev, value & 0xff); + nand_setio(dev, (value >> 8) & 0xff); + nand_setio(dev, (value >> 16) & 0xff); + nand_setio(dev, (value >> 24) & 0xff); + break; + } + case OMAP_GPMC_16BIT: + switch (size) { + case 1: + /* writing to a 16bit device with 8bit access is probably a guest + * bug; pass the value through anyway. + */ + case 2: + nand_setio(dev, value & 0xffff); + break; + case 4: + default: + nand_setio(dev, value & 0xffff); + nand_setio(dev, (value >> 16) & 0xffff); + break; + } + } +} + +static void omap_nand_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) +{ + struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque; + nand_setpins(f->dev, 0, 0, 0, 1, 0); + omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size); +} + +static const MemoryRegionOps omap_nand_ops = { + .read = omap_nand_read, + .write = omap_nand_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void fill_prefetch_fifo(struct omap_gpmc_s *s) +{ + /* Fill the prefetch FIFO by reading data from NAND. + * We do this synchronously, unlike the hardware which + * will do this asynchronously. We refill when the + * FIFO has THRESHOLD bytes free, and we always refill + * as much data as possible starting at the top end + * of the FIFO. + * (We have to refill at THRESHOLD rather than waiting + * for the FIFO to empty to allow for the case where + * the FIFO size isn't an exact multiple of THRESHOLD + * and we're doing DMA transfers.) + * This means we never need to handle wrap-around in + * the fifo-reading code, and the next byte of data + * to read is always fifo[63 - fifopointer]. + */ + int fptr; + int cs = prefetch_cs(s->prefetch.config1); + int is16bit = (((s->cs_file[cs].config[0] >> 12) & 3) != 0); + int bytes; + /* Don't believe the bit of the OMAP TRM that says that COUNTVALUE + * and TRANSFERCOUNT are in units of 16 bit words for 16 bit NAND. + * Instead believe the bit that says it is always a byte count. + */ + bytes = 64 - s->prefetch.fifopointer; + if (bytes > s->prefetch.count) { + bytes = s->prefetch.count; + } + s->prefetch.count -= bytes; + s->prefetch.fifopointer += bytes; + fptr = 64 - s->prefetch.fifopointer; + /* Move the existing data in the FIFO so it sits just + * before what we're about to read in + */ + while (fptr < (64 - bytes)) { + s->prefetch.fifo[fptr] = s->prefetch.fifo[fptr + bytes]; + fptr++; + } + while (fptr < 64) { + if (is16bit) { + uint32_t v = omap_nand_read(&s->cs_file[cs], 0, 2); + s->prefetch.fifo[fptr++] = v & 0xff; + s->prefetch.fifo[fptr++] = (v >> 8) & 0xff; + } else { + s->prefetch.fifo[fptr++] = omap_nand_read(&s->cs_file[cs], 0, 1); + } + } + if (s->prefetch.startengine && (s->prefetch.count == 0)) { + /* This was the final transfer: raise TERMINALCOUNTSTATUS */ + s->irqst |= 2; + s->prefetch.startengine = 0; + } + /* If there are any bytes in the FIFO at this point then + * we must raise a DMA request (either this is a final part + * transfer, or we filled the FIFO in which case we certainly + * have THRESHOLD bytes available) + */ + if (s->prefetch.fifopointer != 0) { + omap_gpmc_dma_update(s, 1); + } + omap_gpmc_int_update(s); +} + +/* Access functions for a NAND-like device when the prefetch/postwrite + * engine is enabled -- all addresses in the region behave alike: + * data is read or written to the FIFO. + */ +static uint64_t omap_gpmc_prefetch_read(void *opaque, target_phys_addr_t addr, + unsigned size) +{ + struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; + uint32_t data; + if (s->prefetch.config1 & 1) { + /* The TRM doesn't define the behaviour if you read from the + * FIFO when the prefetch engine is in write mode. We choose + * to always return zero. + */ + return 0; + } + /* Note that trying to read an empty fifo repeats the last byte */ + if (s->prefetch.fifopointer) { + s->prefetch.fifopointer--; + } + data = s->prefetch.fifo[63 - s->prefetch.fifopointer]; + if (s->prefetch.fifopointer == + (64 - prefetch_threshold(s->prefetch.config1))) { + /* We've drained THRESHOLD bytes now. So deassert the + * DMA request, then refill the FIFO (which will probably + * assert it again.) + */ + omap_gpmc_dma_update(s, 0); + fill_prefetch_fifo(s); + } + omap_gpmc_int_update(s); + return data; +} + +static void omap_gpmc_prefetch_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) +{ + struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque; + int cs = prefetch_cs(s->prefetch.config1); + if ((s->prefetch.config1 & 1) == 0) { + /* The TRM doesn't define the behaviour of writing to the + * FIFO when the prefetch engine is in read mode. We + * choose to ignore the write. + */ + return; + } + if (s->prefetch.count == 0) { + /* The TRM doesn't define the behaviour of writing to the + * FIFO if the transfer is complete. We choose to ignore. + */ return; } + /* The only reason we do any data buffering in postwrite + * mode is if we are talking to a 16 bit NAND device, in + * which case we need to buffer the first byte of the + * 16 bit word until the other byte arrives. + */ + int is16bit = (((s->cs_file[cs].config[0] >> 12) & 3) != 0); + if (is16bit) { + /* fifopointer alternates between 64 (waiting for first + * byte of word) and 63 (waiting for second byte) + */ + if (s->prefetch.fifopointer == 64) { + s->prefetch.fifo[0] = value; + s->prefetch.fifopointer--; + } else { + value = (value << 8) | s->prefetch.fifo[0]; + omap_nand_write(&s->cs_file[cs], 0, value, 2); + s->prefetch.count--; + s->prefetch.fifopointer = 64; + } + } else { + /* Just write the byte : fifopointer remains 64 at all times */ + omap_nand_write(&s->cs_file[cs], 0, value, 1); + s->prefetch.count--; + } + if (s->prefetch.count == 0) { + /* Final transfer: raise TERMINALCOUNTSTATUS */ + s->irqst |= 2; + s->prefetch.startengine = 0; + } + omap_gpmc_int_update(s); +} + +static const MemoryRegionOps omap_prefetch_ops = { + .read = omap_gpmc_prefetch_read, + .write = omap_gpmc_prefetch_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl.min_access_size = 1, + .impl.max_access_size = 1, +}; - if (!f->opaque) +static MemoryRegion *omap_gpmc_cs_memregion(struct omap_gpmc_s *s, int cs) +{ + /* Return the MemoryRegion* to map/unmap for this chipselect */ + struct omap_gpmc_cs_file_s *f = &s->cs_file[cs]; + if (omap_gpmc_devtype(f) == OMAP_GPMC_NOR) { + return f->iomem; + } + if ((s->prefetch.config1 & 0x80) && + (prefetch_cs(s->prefetch.config1) == cs)) { + /* The prefetch engine is enabled for this CS: map the FIFO */ + return &s->prefetch.iomem; + } + return &f->nandiomem; +} + +static void omap_gpmc_cs_map(struct omap_gpmc_s *s, int cs) +{ + struct omap_gpmc_cs_file_s *f = &s->cs_file[cs]; + uint32_t mask = (f->config[6] >> 8) & 0xf; + uint32_t base = f->config[6] & 0x3f; + uint32_t size; + + if (!f->iomem && !f->dev) { + return; + } + + if (!(f->config[6] & (1 << 6))) { + /* Do nothing unless CSVALID */ return; + } - f->base = base << 24; - f->size = (0x0fffffff & ~(mask << 24)) + 1; + /* TODO: check for overlapping regions and report access errors */ + if (mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf + && !(s->accept_256 && !mask)) { + fprintf(stderr, "%s: invalid chip-select mask address (0x%x)\n", + __func__, mask); + } + + base <<= 24; + size = (0x0fffffff & ~(mask << 24)) + 1; /* TODO: rather than setting the size of the mapping (which should be * constant), the mask should cause wrapping of the address space, so * that the same memory becomes accessible at every <i>size</i> bytes * starting from <i>base</i>. */ - if (f->iomem) { - memory_region_init(&f->container, "omap-gpmc-file", f->size); - memory_region_add_subregion(&f->container, 0, f->iomem); - memory_region_add_subregion(get_system_memory(), f->base, - &f->container); - } - - if (f->base_update) - f->base_update(f->opaque, f->base); + memory_region_init(&f->container, "omap-gpmc-file", size); + memory_region_add_subregion(&f->container, 0, + omap_gpmc_cs_memregion(s, cs)); + memory_region_add_subregion(get_system_memory(), base, + &f->container); } -static void omap_gpmc_cs_unmap(struct omap_gpmc_cs_file_s *f) +static void omap_gpmc_cs_unmap(struct omap_gpmc_s *s, int cs) { - if (f->size) { - if (f->unmap) - f->unmap(f->opaque); - if (f->iomem) { - memory_region_del_subregion(get_system_memory(), &f->container); - memory_region_del_subregion(&f->container, f->iomem); - memory_region_destroy(&f->container); - } - f->base = 0; - f->size = 0; + struct omap_gpmc_cs_file_s *f = &s->cs_file[cs]; + if (!(f->config[6] & (1 << 6))) { + /* Do nothing unless CSVALID */ + return; + } + if (!f->iomem && !f->dev) { + return; } + memory_region_del_subregion(get_system_memory(), &f->container); + memory_region_del_subregion(&f->container, omap_gpmc_cs_memregion(s, cs)); + memory_region_destroy(&f->container); } void omap_gpmc_reset(struct omap_gpmc_s *s) @@ -115,25 +443,32 @@ void omap_gpmc_reset(struct omap_gpmc_s *s) omap_gpmc_int_update(s); s->timeout = 0; s->config = 0xa00; - s->prefconfig[0] = 0x00004000; - s->prefconfig[1] = 0x00000000; - s->prefcontrol = 0; - s->preffifo = 0; - s->prefcount = 0; + s->prefetch.config1 = 0x00004000; + s->prefetch.transfercount = 0x00000000; + s->prefetch.startengine = 0; + s->prefetch.fifopointer = 0; + s->prefetch.count = 0; for (i = 0; i < 8; i ++) { - if (s->cs_file[i].config[6] & (1 << 6)) /* CSVALID */ - omap_gpmc_cs_unmap(s->cs_file + i); - s->cs_file[i].config[0] = i ? 1 << 12 : 0; + omap_gpmc_cs_unmap(s, i); s->cs_file[i].config[1] = 0x101001; s->cs_file[i].config[2] = 0x020201; s->cs_file[i].config[3] = 0x10031003; s->cs_file[i].config[4] = 0x10f1111; s->cs_file[i].config[5] = 0; s->cs_file[i].config[6] = 0xf00 | (i ? 0 : 1 << 6); - if (s->cs_file[i].config[6] & (1 << 6)) /* CSVALID */ - omap_gpmc_cs_map(&s->cs_file[i], - s->cs_file[i].config[6] & 0x1f, /* MASKADDR */ - (s->cs_file[i].config[6] >> 8 & 0xf)); /* BASEADDR */ + + s->cs_file[i].config[6] = 0xf00; + /* In theory we could probe attached devices for some CFG1 + * bits here, but we just retain them across resets as they + * were set initially by omap_gpmc_attach(). + */ + if (i == 0) { + s->cs_file[i].config[0] &= 0x00433e00; + s->cs_file[i].config[6] |= 1 << 6; /* CSVALID */ + omap_gpmc_cs_map(s, i); + } else { + s->cs_file[i].config[0] &= 0x00403c00; + } } s->ecc_cs = 0; s->ecc_ptr = 0; @@ -142,6 +477,24 @@ void omap_gpmc_reset(struct omap_gpmc_s *s) ecc_reset(&s->ecc[i]); } +static int gpmc_wordaccess_only(target_phys_addr_t addr) +{ + /* Return true if the register offset is to a register that + * only permits word width accesses. + * Non-word accesses are only OK for GPMC_NAND_DATA/ADDRESS/COMMAND + * for any chipselect. + */ + if (addr >= 0x60 && addr <= 0x1d4) { + int cs = (addr - 0x60) / 0x30; + addr -= cs * 0x30; + if (addr >= 0x7c && addr < 0x88) { + /* GPMC_NAND_COMMAND, GPMC_NAND_ADDRESS, GPMC_NAND_DATA */ + return 0; + } + } + return 1; +} + static uint64_t omap_gpmc_read(void *opaque, target_phys_addr_t addr, unsigned size) { @@ -149,13 +502,13 @@ static uint64_t omap_gpmc_read(void *opaque, target_phys_addr_t addr, int cs; struct omap_gpmc_cs_file_s *f; - if (size != 4) { + if (size != 4 && gpmc_wordaccess_only(addr)) { return omap_badwidth_read32(opaque, addr); } switch (addr) { case 0x000: /* GPMC_REVISION */ - return 0x20; + return s->revision; case 0x010: /* GPMC_SYSCONFIG */ return s->sysconfig; @@ -187,36 +540,39 @@ static uint64_t omap_gpmc_read(void *opaque, target_phys_addr_t addr, addr -= cs * 0x30; f = s->cs_file + cs; switch (addr) { - case 0x60: /* GPMC_CONFIG1 */ - return f->config[0]; - case 0x64: /* GPMC_CONFIG2 */ - return f->config[1]; - case 0x68: /* GPMC_CONFIG3 */ - return f->config[2]; - case 0x6c: /* GPMC_CONFIG4 */ - return f->config[3]; - case 0x70: /* GPMC_CONFIG5 */ - return f->config[4]; - case 0x74: /* GPMC_CONFIG6 */ - return f->config[5]; - case 0x78: /* GPMC_CONFIG7 */ - return f->config[6]; - case 0x84: /* GPMC_NAND_DATA */ - return 0; + case 0x60: /* GPMC_CONFIG1 */ + return f->config[0]; + case 0x64: /* GPMC_CONFIG2 */ + return f->config[1]; + case 0x68: /* GPMC_CONFIG3 */ + return f->config[2]; + case 0x6c: /* GPMC_CONFIG4 */ + return f->config[3]; + case 0x70: /* GPMC_CONFIG5 */ + return f->config[4]; + case 0x74: /* GPMC_CONFIG6 */ + return f->config[5]; + case 0x78: /* GPMC_CONFIG7 */ + return f->config[6]; + case 0x84 ... 0x87: /* GPMC_NAND_DATA */ + if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) { + return omap_nand_read(f, 0, size); + } + return 0; } break; case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ - return s->prefconfig[0]; + return s->prefetch.config1; case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */ - return s->prefconfig[1]; + return s->prefetch.transfercount; case 0x1ec: /* GPMC_PREFETCH_CONTROL */ - return s->prefcontrol; + return s->prefetch.startengine; case 0x1f0: /* GPMC_PREFETCH_STATUS */ - return (s->preffifo << 24) | - ((s->preffifo > - ((s->prefconfig[0] >> 8) & 0x7f) ? 1 : 0) << 16) | - s->prefcount; + return (s->prefetch.fifopointer << 24) | + ((s->prefetch.fifopointer >= + ((s->prefetch.config1 >> 8) & 0x7f) ? 1 : 0) << 16) | + s->prefetch.count; case 0x1f4: /* GPMC_ECC_CONFIG */ return s->ecc_cs; @@ -251,7 +607,7 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr, int cs; struct omap_gpmc_cs_file_s *f; - if (size != 4) { + if (size != 4 && gpmc_wordaccess_only(addr)) { return omap_badwidth_write32(opaque, addr, value); } @@ -276,7 +632,7 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr, break; case 0x018: /* GPMC_IRQSTATUS */ - s->irqen = ~value; + s->irqen &= ~value; omap_gpmc_int_update(s); break; @@ -302,62 +658,109 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr, addr -= cs * 0x30; f = s->cs_file + cs; switch (addr) { - case 0x60: /* GPMC_CONFIG1 */ - f->config[0] = value & 0xffef3e13; - break; - case 0x64: /* GPMC_CONFIG2 */ - f->config[1] = value & 0x001f1f8f; - break; - case 0x68: /* GPMC_CONFIG3 */ - f->config[2] = value & 0x001f1f8f; - break; - case 0x6c: /* GPMC_CONFIG4 */ - f->config[3] = value & 0x1f8f1f8f; - break; - case 0x70: /* GPMC_CONFIG5 */ - f->config[4] = value & 0x0f1f1f1f; - break; - case 0x74: /* GPMC_CONFIG6 */ - f->config[5] = value & 0x00000fcf; - break; - case 0x78: /* GPMC_CONFIG7 */ - if ((f->config[6] ^ value) & 0xf7f) { - if (f->config[6] & (1 << 6)) /* CSVALID */ - omap_gpmc_cs_unmap(f); - if (value & (1 << 6)) /* CSVALID */ - omap_gpmc_cs_map(f, value & 0x1f, /* MASKADDR */ - (value >> 8 & 0xf)); /* BASEADDR */ - } + case 0x60: /* GPMC_CONFIG1 */ + f->config[0] = value & 0xffef3e13; + break; + case 0x64: /* GPMC_CONFIG2 */ + f->config[1] = value & 0x001f1f8f; + break; + case 0x68: /* GPMC_CONFIG3 */ + f->config[2] = value & 0x001f1f8f; + break; + case 0x6c: /* GPMC_CONFIG4 */ + f->config[3] = value & 0x1f8f1f8f; + break; + case 0x70: /* GPMC_CONFIG5 */ + f->config[4] = value & 0x0f1f1f1f; + break; + case 0x74: /* GPMC_CONFIG6 */ + f->config[5] = value & 0x00000fcf; + break; + case 0x78: /* GPMC_CONFIG7 */ + if ((f->config[6] ^ value) & 0xf7f) { + omap_gpmc_cs_unmap(s, cs); f->config[6] = value & 0x00000f7f; - break; - case 0x7c: /* GPMC_NAND_COMMAND */ - case 0x80: /* GPMC_NAND_ADDRESS */ - case 0x84: /* GPMC_NAND_DATA */ - break; - - default: - goto bad_reg; + omap_gpmc_cs_map(s, cs); + } + break; + case 0x7c ... 0x7f: /* GPMC_NAND_COMMAND */ + if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) { + nand_setpins(f->dev, 1, 0, 0, 1, 0); /* CLE */ + omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size); + } + break; + case 0x80 ... 0x83: /* GPMC_NAND_ADDRESS */ + if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) { + nand_setpins(f->dev, 0, 1, 0, 1, 0); /* ALE */ + omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size); + } + break; + case 0x84 ... 0x87: /* GPMC_NAND_DATA */ + if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) { + omap_nand_write(f, 0, value, size); + } + break; + default: + goto bad_reg; } break; case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ - s->prefconfig[0] = value & 0x7f8f7fbf; - /* TODO: update interrupts, fifos, dmas */ + if (!s->prefetch.startengine) { + uint32_t oldconfig1 = s->prefetch.config1; + uint32_t changed; + s->prefetch.config1 = value & 0x7f8f7fbf; + changed = oldconfig1 ^ s->prefetch.config1; + if (changed & (0x80 | 0x7000000)) { + /* Turning the engine on or off, or mapping it somewhere else. + * cs_map() and cs_unmap() check the prefetch config and + * overall CSVALID bits, so it is sufficient to unmap-and-map + * both the old cs and the new one. + */ + int oldcs = prefetch_cs(oldconfig1); + int newcs = prefetch_cs(s->prefetch.config1); + omap_gpmc_cs_unmap(s, oldcs); + omap_gpmc_cs_map(s, oldcs); + if (newcs != oldcs) { + omap_gpmc_cs_unmap(s, newcs); + omap_gpmc_cs_map(s, newcs); + } + } + } break; case 0x1e4: /* GPMC_PREFETCH_CONFIG2 */ - s->prefconfig[1] = value & 0x3fff; + if (!s->prefetch.startengine) { + s->prefetch.transfercount = value & 0x3fff; + } break; case 0x1ec: /* GPMC_PREFETCH_CONTROL */ - s->prefcontrol = value & 1; - if (s->prefcontrol) { - if (s->prefconfig[0] & 1) - s->preffifo = 0x40; - else - s->preffifo = 0x00; + if (s->prefetch.startengine != (value & 1)) { + s->prefetch.startengine = value & 1; + if (s->prefetch.startengine) { + /* Prefetch engine start */ + s->prefetch.count = s->prefetch.transfercount; + if (s->prefetch.config1 & 1) { + /* Write */ + s->prefetch.fifopointer = 64; + } else { + /* Read */ + s->prefetch.fifopointer = 0; + fill_prefetch_fifo(s); + } + } else { + /* Prefetch engine forcibly stopped. The TRM + * doesn't define the behaviour if you do this. + * We clear the prefetch count, which means that + * we permit no more writes, and don't read any + * more data from NAND. The CPU can still drain + * the FIFO of unread data. + */ + s->prefetch.count = 0; + } + omap_gpmc_int_update(s); } - /* TODO: start */ break; case 0x1f4: /* GPMC_ECC_CONFIG */ @@ -394,24 +797,47 @@ static const MemoryRegionOps omap_gpmc_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq) +struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu, + target_phys_addr_t base, + qemu_irq irq, qemu_irq drq) { + int cs; struct omap_gpmc_s *s = (struct omap_gpmc_s *) g_malloc0(sizeof(struct omap_gpmc_s)); - omap_gpmc_reset(s); - memory_region_init_io(&s->iomem, &omap_gpmc_ops, s, "omap-gpmc", 0x1000); memory_region_add_subregion(get_system_memory(), base, &s->iomem); + s->irq = irq; + s->drq = drq; + s->accept_256 = cpu_is_omap3630(mpu); + s->revision = cpu_class_omap3(mpu) ? 0x50 : 0x20; + s->lastirq = 0; + omap_gpmc_reset(s); + + /* We have to register a different IO memory handler for each + * chip select region in case a NAND device is mapped there. We + * make the region the worst-case size of 256MB and rely on the + * container memory region in cs_map to chop it down to the actual + * guest-requested size. + */ + for (cs = 0; cs < 8; cs++) { + memory_region_init_io(&s->cs_file[cs].nandiomem, + &omap_nand_ops, + &s->cs_file[cs], + "omap-nand", + 256 * 1024 * 1024); + } + + memory_region_init_io(&s->prefetch.iomem, &omap_prefetch_ops, s, + "omap-gpmc-prefetch", 256 * 1024 * 1024); return s; } -void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem, - void (*base_upd)(void *opaque, target_phys_addr_t new), - void (*unmap)(void *opaque), void *opaque) +void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem) { struct omap_gpmc_cs_file_s *f; + assert(iomem); if (cs < 0 || cs >= 8) { fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs); @@ -419,12 +845,29 @@ void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem, } f = &s->cs_file[cs]; + omap_gpmc_cs_unmap(s, cs); + f->config[0] &= ~(0xf << 10); f->iomem = iomem; - f->base_update = base_upd; - f->unmap = unmap; - f->opaque = opaque; + omap_gpmc_cs_map(s, cs); +} - if (f->config[6] & (1 << 6)) /* CSVALID */ - omap_gpmc_cs_map(f, f->config[6] & 0x1f, /* MASKADDR */ - (f->config[6] >> 8 & 0xf)); /* BASEADDR */ +void omap_gpmc_attach_nand(struct omap_gpmc_s *s, int cs, DeviceState *nand) +{ + struct omap_gpmc_cs_file_s *f; + assert(nand); + + if (cs < 0 || cs >= 8) { + fprintf(stderr, "%s: bad chip-select %i\n", __func__, cs); + exit(-1); + } + f = &s->cs_file[cs]; + + omap_gpmc_cs_unmap(s, cs); + f->config[0] &= ~(0xf << 10); + f->config[0] |= (OMAP_GPMC_NAND << 10); + f->dev = nand; + if (nand_getbuswidth(f->dev) == 16) { + f->config[0] |= OMAP_GPMC_16BIT << 12; + } + omap_gpmc_cs_map(s, cs); } diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index 70364f4c72..a7b687bc41 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -129,8 +129,7 @@ static void sx1_init(ram_addr_t ram_size, DriveInfo *dinfo; int fl_idx; uint32_t flash_size = flash0_size; - const MemoryRegionOps *flash_ops; - MemoryRegion *flash = g_new(MemoryRegion, 2); + int be; if (version == 2) { flash_size = flash2_size; @@ -156,18 +155,17 @@ static void sx1_init(ram_addr_t ram_size, fl_idx = 0; #ifdef TARGET_WORDS_BIGENDIAN - flash_ops = &pflash_cfi01_ops_be; + be = 1; #else - flash_ops = &pflash_cfi01_ops_le; + be = 0; #endif if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) { - memory_region_init_rom_device(&flash[0], flash_ops, - NULL, "omap_sx1.flash0-1", flash_size); - if (!pflash_cfi01_register(OMAP_CS0_BASE, &flash[0], + if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(NULL, + "omap_sx1.flash0-1", flash_size), dinfo->bdrv, sector_size, flash_size / sector_size, - 4, 0, 0, 0, 0)) { + 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory %d.\n", fl_idx); } @@ -184,12 +182,11 @@ static void sx1_init(ram_addr_t ram_size, cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size, OMAP_CS1_SIZE - flash1_size, io); - memory_region_init_rom_device(&flash[1], flash_ops, - NULL, "omap_sx1.flash1-1", flash1_size); - if (!pflash_cfi01_register(OMAP_CS1_BASE, &flash[1], + if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(NULL, + "omap_sx1.flash1-1", flash1_size), dinfo->bdrv, sector_size, flash1_size / sector_size, - 4, 0, 0, 0, 0)) { + 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory %d.\n", fl_idx); } diff --git a/hw/onenand.c b/hw/onenand.c index 00276a03cb..6f68f70698 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -25,6 +25,7 @@ #include "blockdev.h" #include "memory.h" #include "exec-memory.h" +#include "sysbus.h" /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */ #define PAGE_SHIFT 11 @@ -33,6 +34,7 @@ #define BLOCK_SHIFT (PAGE_SHIFT + 6) typedef struct { + SysBusDevice busdev; struct { uint16_t man; uint16_t dev; @@ -49,6 +51,7 @@ typedef struct { uint8_t *current; MemoryRegion ram; MemoryRegion mapped_ram; + uint8_t current_direction; uint8_t *boot[2]; uint8_t *data[2][2]; MemoryRegion iomem; @@ -120,27 +123,72 @@ static void onenand_mem_setup(OneNANDState *s) 1); } -void onenand_base_update(void *opaque, target_phys_addr_t new) +static void onenand_intr_update(OneNANDState *s) { - OneNANDState *s = (OneNANDState *) opaque; - - s->base = new; - - memory_region_add_subregion(get_system_memory(), s->base, &s->container); + qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1); } -void onenand_base_unmap(void *opaque) +static void onenand_pre_save(void *opaque) { - OneNANDState *s = (OneNANDState *) opaque; - - memory_region_del_subregion(get_system_memory(), &s->container); + OneNANDState *s = opaque; + if (s->current == s->otp) { + s->current_direction = 1; + } else if (s->current == s->image) { + s->current_direction = 2; + } else { + s->current_direction = 0; + } } -static void onenand_intr_update(OneNANDState *s) +static int onenand_post_load(void *opaque, int version_id) { - qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1); + OneNANDState *s = opaque; + switch (s->current_direction) { + case 0: + break; + case 1: + s->current = s->otp; + break; + case 2: + s->current = s->image; + break; + default: + return -1; + } + onenand_intr_update(s); + return 0; } +static const VMStateDescription vmstate_onenand = { + .name = "onenand", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .pre_save = onenand_pre_save, + .post_load = onenand_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT8(current_direction, OneNANDState), + VMSTATE_INT32(cycle, OneNANDState), + VMSTATE_INT32(otpmode, OneNANDState), + VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8), + VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8), + VMSTATE_INT32(bufaddr, OneNANDState), + VMSTATE_INT32(count, OneNANDState), + VMSTATE_UINT16(command, OneNANDState), + VMSTATE_UINT16_ARRAY(config, OneNANDState, 2), + VMSTATE_UINT16(status, OneNANDState), + VMSTATE_UINT16(intstatus, OneNANDState), + VMSTATE_UINT16(wpstatus, OneNANDState), + VMSTATE_INT32(secs_cur, OneNANDState), + VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks), + VMSTATE_UINT8(ecc.cp, OneNANDState), + VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2), + VMSTATE_UINT16(ecc.count, OneNANDState), + VMSTATE_BUFFER_UNSAFE(otp, OneNANDState, 0, ((64 + 2) << PAGE_SHIFT)), + VMSTATE_END_OF_LIST() + } +}; + /* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */ static void onenand_reset(OneNANDState *s, int cold) { @@ -167,11 +215,17 @@ static void onenand_reset(OneNANDState *s, int cold) /* Lock the whole flash */ memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks); - if (s->bdrv && bdrv_read(s->bdrv, 0, s->boot[0], 8) < 0) - hw_error("%s: Loading the BootRAM failed.\n", __FUNCTION__); + if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) { + hw_error("%s: Loading the BootRAM failed.\n", __func__); + } } } +static void onenand_system_reset(DeviceState *dev) +{ + onenand_reset(FROM_SYSBUS(OneNANDState, sysbus_from_qdev(dev)), 1); +} + static inline int onenand_load_main(OneNANDState *s, int sec, int secn, void *dest) { @@ -191,8 +245,8 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn, int result = 0; if (secn > 0) { - uint32_t size = (uint32_t) secn * 512; - const uint8_t *sp = (const uint8_t *) src; + uint32_t size = (uint32_t)secn * 512; + const uint8_t *sp = (const uint8_t *)src; uint8_t *dp = 0; if (s->bdrv_cur) { dp = g_malloc(size); @@ -203,7 +257,7 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn, if (sec + secn > s->secs_cur) { result = 1; } else { - dp = (uint8_t *) s->current + (sec << 9); + dp = (uint8_t *)s->current + (sec << 9); } } if (!result) { @@ -245,13 +299,13 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn, { int result = 0; if (secn > 0) { - const uint8_t *sp = (const uint8_t *) src; + const uint8_t *sp = (const uint8_t *)src; uint8_t *dp = 0, *dpp = 0; if (s->bdrv_cur) { dp = g_malloc(512); if (!dp || bdrv_read(s->bdrv_cur, - s->secs_cur + (sec >> 5), - dp, 1) < 0) { + s->secs_cur + (sec >> 5), + dp, 1) < 0) { result = 1; } else { dpp = dp + ((sec & 31) << 4); @@ -270,7 +324,7 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn, } if (s->bdrv_cur) { result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), - dp, 1) < 0; + dp, 1) < 0; } } if (dp) { @@ -326,7 +380,7 @@ fail: return 1; } -static void onenand_command(OneNANDState *s, int cmd) +static void onenand_command(OneNANDState *s) { int b; int sec; @@ -346,7 +400,7 @@ static void onenand_command(OneNANDState *s, int cmd) s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1]; \ buf += (s->bufaddr & 3) << 4; - switch (cmd) { + switch (s->command) { case 0x00: /* Load single/multiple sector data unit into buffer */ SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE) @@ -527,7 +581,7 @@ static void onenand_command(OneNANDState *s, int cmd) s->status |= ONEN_ERR_CMD; s->intstatus |= ONEN_INT; fprintf(stderr, "%s: unknown OneNAND command %x\n", - __FUNCTION__, cmd); + __func__, s->command); } onenand_intr_update(s); @@ -659,7 +713,7 @@ static void onenand_write(void *opaque, target_phys_addr_t addr, if (s->intstatus & (1 << 15)) break; s->command = value; - onenand_command(s, s->command); + onenand_command(s); break; case 0xf221: /* System Configuration 1 */ s->config[0] = value; @@ -700,30 +754,25 @@ static const MemoryRegionOps onenand_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -void *onenand_init(BlockDriverState *bdrv, - uint16_t man_id, uint16_t dev_id, uint16_t ver_id, - int regshift, qemu_irq irq) +static int onenand_initfn(SysBusDevice *dev) { - OneNANDState *s = (OneNANDState *) g_malloc0(sizeof(*s)); - uint32_t size = 1 << (24 + ((dev_id >> 4) & 7)); + OneNANDState *s = (OneNANDState *)dev; + uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7)); void *ram; - - s->shift = regshift; - s->intr = irq; + s->base = (target_phys_addr_t)-1; s->rdy = NULL; - s->id.man = man_id; - s->id.dev = dev_id; - s->id.ver = ver_id; s->blocks = size >> BLOCK_SHIFT; s->secs = size >> 9; s->blockwp = g_malloc(s->blocks); - s->density_mask = (dev_id & 0x08) ? (1 << (6 + ((dev_id >> 4) & 7))) : 0; + s->density_mask = (s->id.dev & 0x08) + ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0; memory_region_init_io(&s->iomem, &onenand_ops, s, "onenand", 0x10000 << s->shift); - s->bdrv = bdrv; if (!s->bdrv) { s->image = memset(g_malloc(size + (size >> 5)), - 0xff, size + (size >> 5)); + 0xff, size + (size >> 5)); + } else { + s->bdrv_cur = s->bdrv; } s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT), 0xff, (64 + 2) << PAGE_SHIFT); @@ -736,15 +785,40 @@ void *onenand_init(BlockDriverState *bdrv, s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift); s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift); onenand_mem_setup(s); + sysbus_init_irq(dev, &s->intr); + sysbus_init_mmio_region(dev, &s->container); + vmstate_register(&dev->qdev, + ((s->shift & 0x7f) << 24) + | ((s->id.man & 0xff) << 16) + | ((s->id.dev & 0xff) << 8) + | (s->id.ver & 0xff), + &vmstate_onenand, s); + return 0; +} - onenand_reset(s, 1); +static SysBusDeviceInfo onenand_info = { + .init = onenand_initfn, + .qdev.name = "onenand", + .qdev.size = sizeof(OneNANDState), + .qdev.reset = onenand_system_reset, + .qdev.props = (Property[]) { + DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0), + DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0), + DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0), + DEFINE_PROP_INT32("shift", OneNANDState, shift, 0), + DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv), + DEFINE_PROP_END_OF_LIST() + } +}; - return s; +static void onenand_register_device(void) +{ + sysbus_register_withprop(&onenand_info); } -void *onenand_raw_otp(void *opaque) +void *onenand_raw_otp(DeviceState *onenand_device) { - OneNANDState *s = (OneNANDState *) opaque; - - return s->otp; + return FROM_SYSBUS(OneNANDState, sysbus_from_qdev(onenand_device))->otp; } + +device_init(onenand_register_device) @@ -78,12 +78,12 @@ struct e820_entry { uint64_t address; uint64_t length; uint32_t type; -} __attribute((__packed__, __aligned__(4))); +} QEMU_PACKED __attribute((__aligned__(4))); struct e820_table { uint32_t count; struct e820_entry entry[E820_NR_ENTRIES]; -} __attribute((__packed__, __aligned__(4))); +} QEMU_PACKED __attribute((__aligned__(4))); static struct e820_table e820_table; struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; diff --git a/hw/pci-stub.c b/hw/pci-stub.c index c5a0aa8979..1fb105d51c 100644 --- a/hw/pci-stub.c +++ b/hw/pci-stub.c @@ -1,5 +1,5 @@ /* - * PCI stubs for plathome that doesn't support pci bus. + * PCI stubs for platforms that don't support pci bus. * * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp> * VA Linux Systems Japan K.K. @@ -1811,6 +1811,25 @@ static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id, return next; } +static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset) +{ + uint8_t next, prev, found = 0; + + if (!(pdev->used[offset])) { + return 0; + } + + assert(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST); + + for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); + prev = next + PCI_CAP_LIST_NEXT) { + if (next <= offset && next > found) { + found = next; + } + } + return found; +} + /* Patch the PCI vendor and device ids in a PCI rom image if necessary. This is needed for an option rom which is used for more than one device. */ static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) @@ -1952,11 +1971,30 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t offset, uint8_t size) { uint8_t *config; + int i, overlapping_cap; + if (!offset) { offset = pci_find_space(pdev, size); if (!offset) { return -ENOSPC; } + } else { + /* Verify that capabilities don't overlap. Note: device assignment + * depends on this check to verify that the device is not broken. + * Should never trigger for emulated devices, but it's helpful + * for debugging these. */ + for (i = offset; i < offset + size; i++) { + overlapping_cap = pci_find_capability_at_offset(pdev, i); + if (overlapping_cap) { + fprintf(stderr, "ERROR: %04x:%02x:%02x.%x " + "Attempt to add PCI capability %x at offset " + "%x overlaps existing capability %x at offset %x\n", + pci_find_domain(pdev->bus), pci_bus_num(pdev->bus), + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + cap_id, offset, overlapping_cap, i); + return -EINVAL; + } + } } config = pdev->config + offset; diff --git a/hw/pci_host.c b/hw/pci_host.c index 44c6c207a9..2e8a29f1e3 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -94,72 +94,82 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len) return val; } -static void pci_host_config_write(void *opaque, target_phys_addr_t addr, - uint64_t val, unsigned len) +static void pci_host_config_write(ReadWriteHandler *handler, + pcibus_t addr, uint32_t val, int len) { - PCIHostState *s = opaque; + PCIHostState *s = container_of(handler, PCIHostState, conf_handler); - PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx64"\n", + PCI_DPRINTF("%s addr %" FMT_PCIBUS " %d val %"PRIx32"\n", __func__, addr, len, val); s->config_reg = val; } -static uint64_t pci_host_config_read(void *opaque, target_phys_addr_t addr, - unsigned len) +static uint32_t pci_host_config_read(ReadWriteHandler *handler, + pcibus_t addr, int len) { - PCIHostState *s = opaque; + PCIHostState *s = container_of(handler, PCIHostState, conf_handler); uint32_t val = s->config_reg; - PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx32"\n", + PCI_DPRINTF("%s addr %" FMT_PCIBUS " len %d val %"PRIx32"\n", __func__, addr, len, val); return val; } -static void pci_host_data_write(void *opaque, target_phys_addr_t addr, - uint64_t val, unsigned len) +static void pci_host_data_write(ReadWriteHandler *handler, + pcibus_t addr, uint32_t val, int len) { - PCIHostState *s = opaque; - PCI_DPRINTF("write addr " TARGET_FMT_plx " len %d val %x\n", - addr, len, (unsigned)val); + PCIHostState *s = container_of(handler, PCIHostState, data_handler); + PCI_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", + addr, len, val); if (s->config_reg & (1u << 31)) pci_data_write(s->bus, s->config_reg | (addr & 3), val, len); } -static uint64_t pci_host_data_read(void *opaque, - target_phys_addr_t addr, unsigned len) +static uint32_t pci_host_data_read(ReadWriteHandler *handler, + pcibus_t addr, int len) { - PCIHostState *s = opaque; + PCIHostState *s = container_of(handler, PCIHostState, data_handler); uint32_t val; if (!(s->config_reg & (1 << 31))) return 0xffffffff; val = pci_data_read(s->bus, s->config_reg | (addr & 3), len); - PCI_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n", + PCI_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val); return val; } -const MemoryRegionOps pci_host_conf_le_ops = { - .read = pci_host_config_read, - .write = pci_host_config_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -const MemoryRegionOps pci_host_conf_be_ops = { - .read = pci_host_config_read, - .write = pci_host_config_write, - .endianness = DEVICE_BIG_ENDIAN, -}; +static void pci_host_init(PCIHostState *s) +{ + s->conf_handler.write = pci_host_config_write; + s->conf_handler.read = pci_host_config_read; + s->data_handler.write = pci_host_data_write; + s->data_handler.read = pci_host_data_read; +} -const MemoryRegionOps pci_host_data_le_ops = { - .read = pci_host_data_read, - .write = pci_host_data_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; +int pci_host_conf_register_mmio(PCIHostState *s, int endian) +{ + pci_host_init(s); + return cpu_register_io_memory_simple(&s->conf_handler, endian); +} -const MemoryRegionOps pci_host_data_be_ops = { - .read = pci_host_data_read, - .write = pci_host_data_write, - .endianness = DEVICE_BIG_ENDIAN, -}; +void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s) +{ + pci_host_init(s); + register_ioport_simple(&s->conf_handler, ioport, 4, 4); + sysbus_init_ioports(&s->busdev, ioport, 4); +} +int pci_host_data_register_mmio(PCIHostState *s, int endian) +{ + pci_host_init(s); + return cpu_register_io_memory_simple(&s->data_handler, endian); +} +void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s) +{ + pci_host_init(s); + register_ioport_simple(&s->data_handler, ioport, 4, 1); + register_ioport_simple(&s->data_handler, ioport, 4, 2); + register_ioport_simple(&s->data_handler, ioport, 4, 4); + sysbus_init_ioports(&s->busdev, ioport, 4); +} diff --git a/hw/pci_host.h b/hw/pci_host.h index 0211086d70..7f551143bb 100644 --- a/hw/pci_host.h +++ b/hw/pci_host.h @@ -29,11 +29,12 @@ #define PCI_HOST_H #include "sysbus.h" +#include "rwhandler.h" struct PCIHostState { SysBusDevice busdev; - MemoryRegion conf_mem; - MemoryRegion data_mem; + ReadWriteHandler conf_handler; + ReadWriteHandler data_handler; MemoryRegion *address_space; uint32_t config_reg; PCIBus *bus; @@ -48,9 +49,12 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr, void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len); uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len); -extern const MemoryRegionOps pci_host_conf_le_ops; -extern const MemoryRegionOps pci_host_conf_be_ops; -extern const MemoryRegionOps pci_host_data_le_ops; -extern const MemoryRegionOps pci_host_data_be_ops; +/* for mmio */ +int pci_host_conf_register_mmio(PCIHostState *s, int endian); +int pci_host_data_register_mmio(PCIHostState *s, int endian); + +/* for ioio */ +void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s); +void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s); #endif /* PCI_HOST_H */ @@ -175,6 +175,14 @@ static void hotplug_event_notify(PCIDevice *dev) } } +static void hotplug_event_clear(PCIDevice *dev) +{ + hotplug_event_update_event_status(dev); + if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) { + qemu_set_irq(dev->irq[dev->exp.hpev_intx], 0); + } +} + /* * A PCI Express Hot-Plug Event has occurred, so update slot status register * and notify OS of the event if necessary. @@ -320,6 +328,10 @@ void pcie_cap_slot_write_config(PCIDevice *dev, uint8_t *exp_cap = dev->config + pos; uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA); + if (ranges_overlap(addr, len, pos + PCI_EXP_SLTSTA, 2)) { + hotplug_event_clear(dev); + } + if (!ranges_overlap(addr, len, pos + PCI_EXP_SLTCTL, 2)) { return; } diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c index 2ae65ec807..62c06eafd6 100644 --- a/hw/pcie_aer.c +++ b/hw/pcie_aer.c @@ -415,7 +415,7 @@ static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err) int i; assert(err->status); - assert(err->status & (err->status - 1)); + assert(!(err->status & (err->status - 1))); errcap &= ~(PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP); errcap |= PCI_ERR_CAP_FEP(first_bit); @@ -495,7 +495,7 @@ static int pcie_aer_record_error(PCIDevice *dev, int fep = PCI_ERR_CAP_FEP(errcap); assert(err->status); - assert(err->status & (err->status - 1)); + assert(!(err->status & (err->status - 1))); if (errcap & PCI_ERR_CAP_MHRE && (pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS) & (1U << fep))) { @@ -979,20 +979,21 @@ int do_pcie_aer_inejct_error(Monitor *mon, if (pcie_aer_parse_error_string(error_name, &error_status, &correctable)) { char *e = NULL; error_status = strtoul(error_name, &e, 0); - correctable = !!qdict_get_int(qdict, "correctable"); + correctable = qdict_get_try_bool(qdict, "correctable", 0); if (!e || *e != '\0') { monitor_printf(mon, "invalid error status value. \"%s\"", error_name); return -EINVAL; } } + err.status = error_status; err.source_id = (pci_bus_num(dev->bus) << 8) | dev->devfn; err.flags = 0; if (correctable) { err.flags |= PCIE_AER_ERR_IS_CORRECTABLE; } - if (qdict_get_int(qdict, "advisory_non_fatal")) { + if (qdict_get_try_bool(qdict, "advisory_non_fatal", 0)) { err.flags |= PCIE_AER_ERR_MAYBE_ADVISORY; } if (qdict_haskey(qdict, "header0")) { diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index 257fccaa88..e3ca310efd 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -149,7 +149,7 @@ petalogix_ml605_init(ram_addr_t ram_size, target_phys_addr_t ddr_base = MEMORY_BASEADDR; ram_addr_t phys_lmb_bram; ram_addr_t phys_ram; - MemoryRegion *phys_flash = g_new(MemoryRegion, 1); + ram_addr_t phys_flash; qemu_irq irq[32], *cpu_irq; /* init CPUs */ @@ -169,15 +169,14 @@ petalogix_ml605_init(ram_addr_t ram_size, phys_ram = qemu_ram_alloc(NULL, "petalogix_ml605.ram", ram_size); cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM); - memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_le, - NULL, "petalogix_ml605.flash", FLASH_SIZE); + phys_flash = qemu_ram_alloc(NULL, "petalogix_ml605.flash", FLASH_SIZE); dinfo = drive_get(IF_PFLASH, 0, 0); /* 5th parameter 2 means bank-width * 10th paremeter 0 means little-endian */ pflash_cfi01_register(FLASH_BASEADDR, phys_flash, dinfo ? dinfo->bdrv : NULL, (64 * 1024), FLASH_SIZE >> 16, - 2, 0x89, 0x18, 0x0000, 0x0); + 2, 0x89, 0x18, 0x0000, 0x0, 0); cpu_irq = microblaze_pic_init_cpu(env); diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index 14817452c6..a43fb4c95c 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -127,7 +127,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size, target_phys_addr_t ddr_base = 0x90000000; ram_addr_t phys_lmb_bram; ram_addr_t phys_ram; - MemoryRegion *phys_flash = g_new(MemoryRegion, 1); + ram_addr_t phys_flash; qemu_irq irq[32], *cpu_irq; /* init CPUs */ @@ -148,14 +148,12 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size, phys_ram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.ram", ram_size); cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM); - memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_be, - NULL, "petalogix_s3adsp1800.flash", - FLASH_SIZE); + phys_flash = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE); dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi01_register(0xa0000000, phys_flash, dinfo ? dinfo->bdrv : NULL, (64 * 1024), FLASH_SIZE >> 16, - 1, 0x89, 0x18, 0x0000, 0x0); + 1, 0x89, 0x18, 0x0000, 0x0, 1); cpu_irq = microblaze_pic_init_cpu(env); dev = xilinx_intc_create(0x81800000, cpu_irq[0], 2); diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 2144c6a3fd..90e1301c5e 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -40,7 +40,6 @@ #include "flash.h" #include "block.h" #include "qemu-timer.h" -#include "exec-memory.h" #define PFLASH_BUG(fmt, ...) \ do { \ @@ -75,7 +74,8 @@ struct pflash_t { target_phys_addr_t counter; unsigned int writeblock_size; QEMUTimer *timer; - MemoryRegion *mem; + ram_addr_t off; + int fl_mem; void *storage; }; @@ -89,7 +89,8 @@ static void pflash_timer (void *opaque) if (pfl->bypass) { pfl->wcycle = 2; } else { - memory_region_rom_device_set_readable(pfl->mem, true); + cpu_register_physical_memory(pfl->base, pfl->total_len, + pfl->off | IO_MEM_ROMD | pfl->fl_mem); pfl->wcycle = 0; } pfl->cmd = 0; @@ -262,7 +263,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, if (!pfl->wcycle) { /* Set the device in I/O access mode */ - memory_region_rom_device_set_readable(pfl->mem, false); + cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem); } switch (pfl->wcycle) { @@ -421,7 +422,8 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, __func__, offset, pfl->wcycle, pfl->cmd, value); reset_flash: - memory_region_rom_device_set_readable(pfl->mem, true); + cpu_register_physical_memory(pfl->base, pfl->total_len, + pfl->off | IO_MEM_ROMD | pfl->fl_mem); pfl->bypass = 0; pfl->wcycle = 0; @@ -512,20 +514,28 @@ static void pflash_writel_le(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 4, 0); } -const MemoryRegionOps pflash_cfi01_ops_be = { - .old_mmio = { - .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, }, - .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUWriteMemoryFunc * const pflash_write_ops_be[] = { + &pflash_writeb_be, + &pflash_writew_be, + &pflash_writel_be, }; -const MemoryRegionOps pflash_cfi01_ops_le = { - .old_mmio = { - .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, }, - .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUReadMemoryFunc * const pflash_read_ops_be[] = { + &pflash_readb_be, + &pflash_readw_be, + &pflash_readl_be, +}; + +static CPUWriteMemoryFunc * const pflash_write_ops_le[] = { + &pflash_writeb_le, + &pflash_writew_le, + &pflash_writel_le, +}; + +static CPUReadMemoryFunc * const pflash_read_ops_le[] = { + &pflash_readb_le, + &pflash_readw_le, + &pflash_readl_le, }; /* Count trailing zeroes of a 32 bits quantity */ @@ -564,11 +574,12 @@ static int ctz32 (uint32_t n) return ret; } -pflash_t *pflash_cfi01_register(target_phys_addr_t base, MemoryRegion *mem, +pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int width, uint16_t id0, uint16_t id1, - uint16_t id2, uint16_t id3) + uint16_t id2, uint16_t id3, + int be) { pflash_t *pfl; target_phys_addr_t total_len; @@ -586,16 +597,26 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, MemoryRegion *mem, pfl = g_malloc0(sizeof(pflash_t)); /* FIXME: Allocate ram ourselves. */ - pfl->storage = memory_region_get_ram_ptr(mem); - pfl->mem = mem; - memory_region_add_subregion(get_system_memory(), base, mem); + pfl->storage = qemu_get_ram_ptr(off); + if (be) { + pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be, + pflash_write_ops_be, pfl, + DEVICE_NATIVE_ENDIAN); + } else { + pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le, + pflash_write_ops_le, pfl, + DEVICE_NATIVE_ENDIAN); + } + pfl->off = off; + cpu_register_physical_memory(base, total_len, + off | pfl->fl_mem | IO_MEM_ROMD); pfl->bs = bs; if (pfl->bs) { /* read the initial flash content */ ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9); if (ret < 0) { - memory_region_del_subregion(get_system_memory(), mem); + cpu_unregister_io_memory(pfl->fl_mem); g_free(pfl); return NULL; } diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index e7e0408fc4..ac5115e4c8 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -39,7 +39,6 @@ #include "flash.h" #include "qemu-timer.h" #include "block.h" -#include "exec-memory.h" //#define PFLASH_DEBUG #ifdef PFLASH_DEBUG @@ -70,39 +69,25 @@ struct pflash_t { uint8_t cfi_len; uint8_t cfi_table[0x52]; QEMUTimer *timer; - /* The device replicates the flash memory across its memory space. Emulate - * that by having a container (.mem) filled with an array of aliases - * (.mem_mappings) pointing to the flash memory (.orig_mem). - */ - MemoryRegion mem; - MemoryRegion *mem_mappings; /* array; one per mapping */ - MemoryRegion *orig_mem; + ram_addr_t off; + int fl_mem; int rom_mode; int read_counter; /* used for lazy switch-back to rom mode */ void *storage; }; -/* - * Set up replicated mappings of the same region. - */ -static void pflash_setup_mappings(pflash_t *pfl, MemoryRegion *mem) -{ - unsigned i; - target_phys_addr_t size = memory_region_size(mem); - - pfl->orig_mem = mem; - memory_region_init(&pfl->mem, "pflash", pfl->mappings * size); - pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings); - for (i = 0; i < pfl->mappings; ++i) { - memory_region_init_alias(&pfl->mem_mappings[i], "pflash-alias", mem, - 0, size); - memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]); - } -} - static void pflash_register_memory(pflash_t *pfl, int rom_mode) { - memory_region_rom_device_set_readable(pfl->orig_mem, rom_mode); + unsigned long phys_offset = pfl->fl_mem; + int i; + + if (rom_mode) + phys_offset |= pfl->off | IO_MEM_ROMD; + pfl->rom_mode = rom_mode; + + for (i = 0; i < pfl->mappings; i++) + cpu_register_physical_memory(pfl->base + i * pfl->chip_len, + pfl->chip_len, phys_offset); } static void pflash_timer (void *opaque) @@ -553,20 +538,28 @@ static void pflash_writel_le(void *opaque, target_phys_addr_t addr, pflash_write(pfl, addr, value, 4, 0); } -const MemoryRegionOps pflash_cfi02_ops_be = { - .old_mmio = { - .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, }, - .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUWriteMemoryFunc * const pflash_write_ops_be[] = { + &pflash_writeb_be, + &pflash_writew_be, + &pflash_writel_be, +}; + +static CPUReadMemoryFunc * const pflash_read_ops_be[] = { + &pflash_readb_be, + &pflash_readw_be, + &pflash_readl_be, }; -const MemoryRegionOps pflash_cfi02_ops_le = { - .old_mmio = { - .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, }, - .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUWriteMemoryFunc * const pflash_write_ops_le[] = { + &pflash_writeb_le, + &pflash_writew_le, + &pflash_writel_le, +}; + +static CPUReadMemoryFunc * const pflash_read_ops_le[] = { + &pflash_readb_le, + &pflash_readw_le, + &pflash_readl_le, }; /* Count trailing zeroes of a 32 bits quantity */ @@ -605,12 +598,13 @@ static int ctz32 (uint32_t n) return ret; } -pflash_t *pflash_cfi02_register(target_phys_addr_t base, MemoryRegion *mem, +pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, BlockDriverState *bs, uint32_t sector_len, int nb_blocs, int nb_mappings, int width, uint16_t id0, uint16_t id1, uint16_t id2, uint16_t id3, - uint16_t unlock_addr0, uint16_t unlock_addr1) + uint16_t unlock_addr0, uint16_t unlock_addr1, + int be) { pflash_t *pfl; int32_t chip_len; @@ -625,22 +619,31 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, MemoryRegion *mem, #endif pfl = g_malloc0(sizeof(pflash_t)); /* FIXME: Allocate ram ourselves. */ - pfl->storage = memory_region_get_ram_ptr(mem); + pfl->storage = qemu_get_ram_ptr(off); + if (be) { + pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be, + pflash_write_ops_be, + pfl, DEVICE_NATIVE_ENDIAN); + } else { + pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le, + pflash_write_ops_le, + pfl, DEVICE_NATIVE_ENDIAN); + } + pfl->off = off; pfl->base = base; pfl->chip_len = chip_len; pfl->mappings = nb_mappings; + pflash_register_memory(pfl, 1); pfl->bs = bs; if (pfl->bs) { /* read the initial flash content */ ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9); if (ret < 0) { + cpu_unregister_io_memory(pfl->fl_mem); g_free(pfl); return NULL; } } - pflash_setup_mappings(pfl, mem); - pfl->rom_mode = 1; - memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem); #if 0 /* XXX: there should be a bit to set up read-only, * the same way the hardware does (with WP pin). */ diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 8f6ea42e2c..c563c6e1a3 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -142,7 +142,6 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) int i, r; uint32_t smram; - memory_region_transaction_begin(); update_pam(d, 0xf0000, 0x100000, (d->dev.config[I440FX_PAM] >> 4) & 3, &d->pam_regions[0]); for(i = 0; i < 12; i++) { @@ -163,7 +162,6 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) d->smram_enabled = false; } } - memory_region_transaction_commit(); } static void i440fx_set_smm(int val, void *arg) @@ -237,16 +235,9 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev) { I440FXState *s = FROM_SYSBUS(I440FXState, dev); - memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s, - "pci-conf-idx", 4); - sysbus_add_io(dev, 0xcf8, &s->conf_mem); - sysbus_init_ioports(&s->busdev, 0xcf8, 4); - - memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s, - "pci-conf-data", 4); - sysbus_add_io(dev, 0xcfc, &s->data_mem); - sysbus_init_ioports(&s->busdev, 0xcfc, 4); + pci_host_conf_register_ioport(0xcf8, s); + pci_host_data_register_ioport(0xcfc, s); return 0; } diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index 1eb807c4c1..dec165e40f 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -32,7 +32,6 @@ #include "qemu-log.h" #include "loader.h" #include "blockdev.h" -#include "exec-memory.h" #define BIOS_FILENAME "ppc405_rom.bin" #define BIOS_SIZE (2048 * 1024) @@ -182,9 +181,7 @@ static void ref405ep_init (ram_addr_t ram_size, ppc4xx_bd_info_t bd; CPUPPCState *env; qemu_irq *pic; - ram_addr_t sram_offset, bdloc; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *bios = g_new(MemoryRegion, 1); + ram_addr_t sram_offset, bios_offset, bdloc; MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories)); target_phys_addr_t ram_bases[2], ram_sizes[2]; target_ulong sram_size; @@ -227,18 +224,18 @@ static void ref405ep_init (ram_addr_t ram_size, dinfo = drive_get(IF_PFLASH, 0, fl_idx); if (dinfo) { bios_size = bdrv_getlength(dinfo->bdrv); - memory_region_init_rom_device(bios, &pflash_cfi02_ops_be, - NULL, "ef405ep.bios", bios_size); + bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", bios_size); fl_sectors = (bios_size + 65535) >> 16; #ifdef DEBUG_BOARD_INIT printf("Register parallel flash %d size %lx" - " at addr %lx '%s' %d\n", - fl_idx, bios_size, -bios_size, + " at offset %08lx addr %lx '%s' %d\n", + fl_idx, bios_size, bios_offset, -bios_size, bdrv_get_device_name(dinfo->bdrv), fl_sectors); #endif - pflash_cfi02_register((uint32_t)(-bios_size), bios, + pflash_cfi02_register((uint32_t)(-bios_size), bios_offset, dinfo->bdrv, 65536, fl_sectors, 1, - 2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); + 2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, + 1); fl_idx++; } else #endif @@ -246,12 +243,12 @@ static void ref405ep_init (ram_addr_t ram_size, #ifdef DEBUG_BOARD_INIT printf("Load BIOS from file\n"); #endif - memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE); + bios_offset = qemu_ram_alloc(NULL, "ef405ep.bios", BIOS_SIZE); if (bios_name == NULL) bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { - bios_size = load_image(filename, memory_region_get_ram_ptr(bios)); + bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset)); g_free(filename); } else { bios_size = -1; @@ -262,9 +259,8 @@ static void ref405ep_init (ram_addr_t ram_size, exit(1); } bios_size = (bios_size + 0xfff) & ~0xfff; - memory_region_set_readonly(bios, true); - memory_region_add_subregion(address_space_mem, (uint32_t)(-bios_size), - bios); + cpu_register_physical_memory((uint32_t)(-bios_size), + bios_size, bios_offset | IO_MEM_ROM); } /* Register FPGA */ #ifdef DEBUG_BOARD_INIT @@ -511,9 +507,7 @@ static void taihu_405ep_init(ram_addr_t ram_size, { char *filename; qemu_irq *pic; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *bios = g_new(MemoryRegion, 1); - MemoryRegion *flash = g_new(MemoryRegion, 1); + ram_addr_t bios_offset; MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories)); target_phys_addr_t ram_bases[2], ram_sizes[2]; long bios_size; @@ -550,17 +544,17 @@ static void taihu_405ep_init(ram_addr_t ram_size, /* XXX: should check that size is 2MB */ // bios_size = 2 * 1024 * 1024; fl_sectors = (bios_size + 65535) >> 16; - memory_region_init_rom_device(bios, &pflash_cfi02_ops_be, - NULL, "taihu_405ep.bios", bios_size); + bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", bios_size); #ifdef DEBUG_BOARD_INIT printf("Register parallel flash %d size %lx" - " at addr %lx '%s' %d\n", - fl_idx, bios_size, -bios_size, + " at offset %08lx addr %lx '%s' %d\n", + fl_idx, bios_size, bios_offset, -bios_size, bdrv_get_device_name(dinfo->bdrv), fl_sectors); #endif - pflash_cfi02_register((uint32_t)(-bios_size), bios, + pflash_cfi02_register((uint32_t)(-bios_size), bios_offset, dinfo->bdrv, 65536, fl_sectors, 1, - 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); + 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, + 1); fl_idx++; } else #endif @@ -570,10 +564,10 @@ static void taihu_405ep_init(ram_addr_t ram_size, #endif if (bios_name == NULL) bios_name = BIOS_FILENAME; - memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE); + bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.bios", BIOS_SIZE); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { - bios_size = load_image(filename, memory_region_get_ram_ptr(bios)); + bios_size = load_image(filename, qemu_get_ram_ptr(bios_offset)); g_free(filename); } else { bios_size = -1; @@ -584,9 +578,8 @@ static void taihu_405ep_init(ram_addr_t ram_size, exit(1); } bios_size = (bios_size + 0xfff) & ~0xfff; - memory_region_set_readonly(bios, true); - memory_region_add_subregion(address_space_mem, - (uint32_t)(-bios_size), bios); + cpu_register_physical_memory((uint32_t)(-bios_size), + bios_size, bios_offset | IO_MEM_ROM); } /* Register Linux flash */ dinfo = drive_get(IF_PFLASH, 0, fl_idx); @@ -597,15 +590,15 @@ static void taihu_405ep_init(ram_addr_t ram_size, fl_sectors = (bios_size + 65535) >> 16; #ifdef DEBUG_BOARD_INIT printf("Register parallel flash %d size %lx" - " at addr " TARGET_FMT_lx " '%s'\n", - fl_idx, bios_size, (target_ulong)0xfc000000, + " at offset %08lx addr " TARGET_FMT_lx " '%s'\n", + fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000, bdrv_get_device_name(dinfo->bdrv)); #endif - memory_region_init_rom_device(flash, &pflash_cfi02_ops_be, - NULL, "taihu_405ep.flash", bios_size); - pflash_cfi02_register(0xfc000000, flash, + bios_offset = qemu_ram_alloc(NULL, "taihu_405ep.flash", bios_size); + pflash_cfi02_register(0xfc000000, bios_offset, dinfo->bdrv, 65536, fl_sectors, 1, - 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); + 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, + 1); fl_idx++; } /* Register CLPD & LCD display */ diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 339b38ec7a..52e2663a01 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -368,12 +368,10 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4], cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index); /* CFGDATA */ - memory_region_init_io(&controller->pci_state.data_mem, - &pci_host_data_be_ops, - &controller->pci_state, "pci-conf-data", 4); - memory_region_add_subregion(get_system_memory(), - config_space + PCIC0_CFGDATA, - &controller->pci_state.data_mem); + index = pci_host_data_register_mmio(&controller->pci_state, 1); + if (index < 0) + goto free; + cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index); /* Internal registers */ index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller, diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 2db365d0b6..4390aeb559 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -79,6 +79,8 @@ struct PPCE500PCIState { uint32_t gasket_time; qemu_irq irq[4]; /* mmio maps */ + int cfgaddr; + int cfgdata; int reg; }; @@ -266,18 +268,18 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base) PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h); - sysbus_add_memory(dev, base + PCIE500_CFGADDR, &h->conf_mem); - sysbus_add_memory(dev, base + PCIE500_CFGDATA, &h->data_mem); + cpu_register_physical_memory(base + PCIE500_CFGADDR, 4, s->cfgaddr); + cpu_register_physical_memory(base + PCIE500_CFGDATA, 4, s->cfgdata); cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE, s->reg); } static void e500_pci_unmap(SysBusDevice *dev, target_phys_addr_t base) { - PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev)); - - sysbus_del_memory(dev, &h->conf_mem); - sysbus_del_memory(dev, &h->data_mem); + cpu_register_physical_memory(base + PCIE500_CFGADDR, 4, + IO_MEM_UNASSIGNED); + cpu_register_physical_memory(base + PCIE500_CFGDATA, 4, + IO_MEM_UNASSIGNED); cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE, IO_MEM_UNASSIGNED); } @@ -307,10 +309,9 @@ static int e500_pcihost_initfn(SysBusDevice *dev) pci_create_simple(b, 0, "e500-host-bridge"); - memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h, - "pci-conf-idx", 4); - memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h, - "pci-conf-data", 4); + s->cfgaddr = pci_host_conf_register_mmio(&s->pci_state, DEVICE_BIG_ENDIAN); + s->cfgdata = pci_host_data_register_mmio(&s->pci_state, + DEVICE_LITTLE_ENDIAN); s->reg = cpu_register_io_memory(e500_pci_reg_read, e500_pci_reg_write, s, DEVICE_BIG_ENDIAN); sysbus_init_mmio_cb2(dev, e500_pci_map, e500_pci_unmap); diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 55e4e25099..c36232a808 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -125,15 +125,9 @@ PCIBus *pci_prep_init(qemu_irq *pic, address_space_io, 0, 4); - memory_region_init_io(&s->conf_mem, &pci_host_conf_be_ops, s, - "pci-conf-idx", 1); - memory_region_add_subregion(address_space_io, 0xcf8, &s->conf_mem); - sysbus_init_ioports(&s->busdev, 0xcf8, 1); - - memory_region_init_io(&s->conf_mem, &pci_host_data_be_ops, s, - "pci-conf-data", 1); - memory_region_add_subregion(address_space_io, 0xcfc, &s->data_mem); - sysbus_init_ioports(&s->busdev, 0xcfc, 1); + pci_host_conf_register_ioport(0xcf8, s); + + pci_host_data_register_ioport(0xcfc, s); PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read, PPC_PCIIO_write, s, diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index 97f90153b7..b73290cb3f 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -70,7 +70,7 @@ struct PXA2xxLCDState { int orientation; }; -typedef struct __attribute__ ((__packed__)) { +typedef struct QEMU_PACKED { uint32_t fdaddr; uint32_t fsaddr; uint32_t fidr; @@ -1388,11 +1388,7 @@ static void init_pipe_signaling(PCIQXLDevice *d) dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__); return; } -#ifdef CONFIG_IOTHREAD fcntl(d->pipe[0], F_SETFL, O_NONBLOCK); -#else - fcntl(d->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */); -#endif fcntl(d->pipe[1], F_SETFL, O_NONBLOCK); fcntl(d->pipe[0], F_SETOWN, getpid()); @@ -209,7 +209,7 @@ static void main_cpu_reset(void *opaque) env->pc = s->vector; } -static struct __attribute__((__packed__)) +static struct QEMU_PACKED { int mount_root_rdonly; int ramdisk_flags; @@ -235,7 +235,6 @@ static void r2d_init(ram_addr_t ram_size, qemu_irq *irq; DriveInfo *dinfo; int i; - MemoryRegion *flash = g_new(MemoryRegion, 1); if (!cpu_model) cpu_model = "SH7751R"; @@ -268,13 +267,11 @@ static void r2d_init(ram_addr_t ram_size, /* onboard flash memory */ dinfo = drive_get(IF_PFLASH, 0, 0); - memory_region_init_rom_device(flash, &pflash_cfi02_ops_le, - NULL, "r2d.flash", FLASH_SIZE); - pflash_cfi02_register(0x0, flash, + pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE), dinfo ? dinfo->bdrv : NULL, (16 * 1024), FLASH_SIZE >> 16, 1, 4, 0x0000, 0x0000, 0x0000, 0x0000, - 0x555, 0x2aa); + 0x555, 0x2aa, 0); /* NIC: rtl8139 on-board, and 2 slots. */ for (i = 0; i < nb_nics; i++) diff --git a/hw/rc4030.c b/hw/rc4030.c index a2a20996a2..33e10709c6 100644 --- a/hw/rc4030.c +++ b/hw/rc4030.c @@ -50,7 +50,7 @@ do { fprintf(stderr, "rc4030 ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } whi typedef struct dma_pagetable_entry { int32_t frame; int32_t owner; -} __attribute__((packed)) dma_pagetable_entry; +} QEMU_PACKED dma_pagetable_entry; #define DMA_PAGESIZE 4096 #define DMA_REG_ENABLE 1 diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index d94b1eb53c..3cc830ff95 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -57,6 +57,7 @@ typedef struct SCSIDiskReq { struct iovec iov; QEMUIOVector qiov; uint32_t status; + BlockAcctCookie acct; } SCSIDiskReq; struct SCSIDiskState @@ -107,10 +108,13 @@ static void scsi_cancel_io(SCSIRequest *req) static void scsi_read_complete(void * opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); int n; r->req.aiocb = NULL; + bdrv_acct_done(s->bs, &r->acct); + if (ret) { if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) { return; @@ -161,6 +165,8 @@ static void scsi_read_data(SCSIRequest *req) r->iov.iov_len = n * 512; qemu_iovec_init_external(&r->qiov, &r->iov, 1); + + bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n, scsi_read_complete, r); if (r->req.aiocb == NULL) { @@ -207,11 +213,14 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type) static void scsi_write_complete(void * opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); uint32_t len; uint32_t n; r->req.aiocb = NULL; + bdrv_acct_done(s->bs, &r->acct); + if (ret) { if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) { return; @@ -252,6 +261,8 @@ static void scsi_write_data(SCSIRequest *req) n = r->iov.iov_len / 512; if (n) { qemu_iovec_init_external(&r->qiov, &r->iov, 1); + + bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE); r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n, scsi_write_complete, r); if (r->req.aiocb == NULL) { @@ -854,13 +865,19 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) buflen = 8; break; case SYNCHRONIZE_CACHE: + { + BlockAcctCookie acct; + + bdrv_acct_start(s->bs, &acct, 0, BDRV_ACCT_FLUSH); ret = bdrv_flush(s->bs); + bdrv_acct_done(s->bs, &acct); if (ret < 0) { if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) { return -1; } } break; + } case GET_CONFIGURATION: memset(outbuf, 0, 8); /* ??? This should probably return much more information. For now diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 76061bb756..36f39300d5 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -150,7 +150,7 @@ static int sh_pci_init_device(SysBusDevice *dev) PCI_DEVFN(0, 0), 4); memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s, "sh_pci", 0x224); - memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_a7, + memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4, 0, 0x224); isa_mmio_setup(&s->isa, 0x40000); sysbus_init_mmio_cb2(dev, sh_pci_map, sh_pci_unmap); diff --git a/hw/smbios.c b/hw/smbios.c index 8f2e965387..c9ba43e8d0 100644 --- a/hw/smbios.c +++ b/hw/smbios.c @@ -21,19 +21,19 @@ struct smbios_header { uint16_t length; uint8_t type; -} __attribute__((__packed__)); +} QEMU_PACKED; struct smbios_field { struct smbios_header header; uint8_t type; uint16_t offset; uint8_t data[]; -} __attribute__((__packed__)); +} QEMU_PACKED; struct smbios_table { struct smbios_header header; uint8_t data[]; -} __attribute__((__packed__)); +} QEMU_PACKED; #define SMBIOS_FIELD_ENTRY 0 #define SMBIOS_TABLE_ENTRY 1 diff --git a/hw/smbios.h b/hw/smbios.h index 3a5169dbd3..94e3641f9a 100644 --- a/hw/smbios.h +++ b/hw/smbios.h @@ -26,7 +26,7 @@ struct smbios_structure_header { uint8_t type; uint8_t length; uint16_t handle; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 0 - BIOS Information */ struct smbios_type_0 { @@ -42,7 +42,7 @@ struct smbios_type_0 { uint8_t system_bios_minor_release; uint8_t embedded_controller_major_release; uint8_t embedded_controller_minor_release; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 1 - System Information */ struct smbios_type_1 { @@ -55,7 +55,7 @@ struct smbios_type_1 { uint8_t wake_up_type; uint8_t sku_number_str; uint8_t family_str; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 3 - System Enclosure (v2.3) */ struct smbios_type_3 { @@ -74,7 +74,7 @@ struct smbios_type_3 { uint8_t number_of_power_cords; uint8_t contained_element_count; // contained elements follow -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 4 - Processor Information (v2.0) */ struct smbios_type_4 { @@ -94,7 +94,7 @@ struct smbios_type_4 { uint16_t l1_cache_handle; uint16_t l2_cache_handle; uint16_t l3_cache_handle; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 16 - Physical Memory Array * Associated with one type 17 (Memory Device). @@ -107,7 +107,7 @@ struct smbios_type_16 { uint32_t maximum_capacity; uint16_t memory_error_information_handle; uint16_t number_of_memory_devices; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 17 - Memory Device * Associated with one type 19 */ @@ -124,7 +124,7 @@ struct smbios_type_17 { uint8_t bank_locator_str; uint8_t memory_type; uint16_t type_detail; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 19 - Memory Array Mapped Address */ struct smbios_type_19 { @@ -133,7 +133,7 @@ struct smbios_type_19 { uint32_t ending_address; uint16_t memory_array_handle; uint8_t partition_width; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 20 - Memory Device Mapped Address */ struct smbios_type_20 { @@ -145,18 +145,18 @@ struct smbios_type_20 { uint8_t partition_row_position; uint8_t interleave_position; uint8_t interleaved_data_depth; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 32 - System Boot Information */ struct smbios_type_32 { struct smbios_structure_header header; uint8_t reserved[6]; uint8_t boot_status; -} __attribute__((__packed__)); +} QEMU_PACKED; /* SMBIOS type 127 -- End-of-table */ struct smbios_type_127 { struct smbios_structure_header header; -} __attribute__((__packed__)); +} QEMU_PACKED; #endif /*QEMU_SMBIOS_H */ @@ -106,7 +106,7 @@ struct srp_indirect_buf { struct srp_direct_buf table_desc; uint32_t len; struct srp_direct_buf desc_list[0]; -} __attribute__((packed)); +} QEMU_PACKED; enum { SRP_MULTICHAN_SINGLE = 0, @@ -141,7 +141,7 @@ struct srp_login_rsp { uint16_t buf_fmt; uint8_t rsp_flags; uint8_t reserved2[25]; -} __attribute__((packed)); +} QEMU_PACKED; struct srp_login_rej { uint8_t opcode; @@ -177,7 +177,7 @@ struct srp_tsk_mgmt { uint8_t reserved1[6]; uint64_t tag; uint8_t reserved2[4]; - uint64_t lun __attribute__((packed)); + uint64_t lun QEMU_PACKED; uint8_t reserved3[2]; uint8_t tsk_mgmt_func; uint8_t reserved4; @@ -198,7 +198,7 @@ struct srp_cmd { uint8_t data_in_desc_cnt; uint64_t tag; uint8_t reserved2[4]; - uint64_t lun __attribute__((packed)); + uint64_t lun QEMU_PACKED; uint8_t reserved3; uint8_t task_attr; uint8_t reserved4; @@ -235,6 +235,6 @@ struct srp_rsp { uint32_t sense_data_len; uint32_t resp_data_len; uint8_t data[0]; -} __attribute__((packed)); +} QEMU_PACKED; #endif /* SCSI_SRP_H */ diff --git a/hw/stellaris.c b/hw/stellaris.c index 2bf1c235dc..9b0db7f511 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -15,7 +15,6 @@ #include "i2c.h" #include "net.h" #include "boards.h" -#include "exec-memory.h" #define GPIO_A 0 #define GPIO_B 1 @@ -1261,7 +1260,6 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, 0x40024000, 0x40025000, 0x40026000}; static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31}; - MemoryRegion *address_space_mem = get_system_memory(); qemu_irq *pic; DeviceState *gpio_dev[7]; qemu_irq gpio_in[7][8]; @@ -1276,8 +1274,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, flash_size = ((board->dc0 & 0xffff) + 1) << 1; sram_size = (board->dc0 >> 18) + 1; - pic = armv7m_init(address_space_mem, - flash_size, sram_size, kernel_filename, cpu_model); + pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model); if (board->dc1 & (1 << 16)) { dev = sysbus_create_varargs("stellaris-adc", 0x40038000, diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index d5613ffffd..f9bd3da209 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -69,7 +69,7 @@ typedef struct { NICState *nic; NICConf conf; qemu_irq irq; - MemoryRegion mmio; + int mmio_index; } stellaris_enet_state; static void stellaris_enet_update(stellaris_enet_state *s) @@ -130,8 +130,7 @@ static int stellaris_enet_can_receive(VLANClientState *nc) return (s->np < 31); } -static uint64_t stellaris_enet_read(void *opaque, target_phys_addr_t offset, - unsigned size) +static uint32_t stellaris_enet_read(void *opaque, target_phys_addr_t offset) { stellaris_enet_state *s = (stellaris_enet_state *)opaque; uint32_t val; @@ -199,7 +198,7 @@ static uint64_t stellaris_enet_read(void *opaque, target_phys_addr_t offset, } static void stellaris_enet_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) + uint32_t value) { stellaris_enet_state *s = (stellaris_enet_state *)opaque; @@ -304,12 +303,17 @@ static void stellaris_enet_write(void *opaque, target_phys_addr_t offset, } } -static const MemoryRegionOps stellaris_enet_ops = { - .read = stellaris_enet_read, - .write = stellaris_enet_write, - .endianness = DEVICE_NATIVE_ENDIAN, +static CPUReadMemoryFunc * const stellaris_enet_readfn[] = { + stellaris_enet_read, + stellaris_enet_read, + stellaris_enet_read }; +static CPUWriteMemoryFunc * const stellaris_enet_writefn[] = { + stellaris_enet_write, + stellaris_enet_write, + stellaris_enet_write +}; static void stellaris_enet_reset(stellaris_enet_state *s) { s->mdv = 0x80; @@ -387,7 +391,7 @@ static void stellaris_enet_cleanup(VLANClientState *nc) unregister_savevm(&s->busdev.qdev, "stellaris_enet", s); - memory_region_destroy(&s->mmio); + cpu_unregister_io_memory(s->mmio_index); g_free(s); } @@ -404,9 +408,10 @@ static int stellaris_enet_init(SysBusDevice *dev) { stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev); - memory_region_init_io(&s->mmio, &stellaris_enet_ops, s, "stellaris_enet", - 0x1000); - sysbus_init_mmio_region(dev, &s->mmio); + s->mmio_index = cpu_register_io_memory(stellaris_enet_readfn, + stellaris_enet_writefn, s, + DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, s->mmio_index); sysbus_init_irq(dev, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); diff --git a/hw/sun4u.c b/hw/sun4u.c index 1b60e4ef59..32e6ab9beb 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -261,7 +261,9 @@ void cpu_check_irqs(CPUState *env) pil |= 1 << 14; } - if (!pil) { + /* The bit corresponding to psrpil is (1<< psrpil), the next bit + is (2 << psrpil). */ + if (pil < (2 << env->psrpil)){ if (env->interrupt_request & CPU_INTERRUPT_HARD) { CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n", env->interrupt_index); @@ -293,10 +295,12 @@ void cpu_check_irqs(CPUState *env) break; } } - } else { + } else if (env->interrupt_request & CPU_INTERRUPT_HARD) { CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x " "current interrupt %x\n", pil, env->pil_in, env->softint, env->interrupt_index); + env->interrupt_index = 0; + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); } } diff --git a/hw/sysbus.c b/hw/sysbus.c index 6e89f065b4..c365d39d24 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -131,6 +131,11 @@ void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory) dev->mmio[n].memory = memory; } +MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n) +{ + return dev->mmio[n].memory; +} + void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size) { pio_addr_t i; @@ -256,32 +261,3 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev) return strdup(path); } - -void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr, - MemoryRegion *mem) -{ - memory_region_add_subregion(get_system_memory(), addr, mem); -} - -void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr, - MemoryRegion *mem, unsigned priority) -{ - memory_region_add_subregion_overlap(get_system_memory(), addr, mem, - priority); -} - -void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem) -{ - memory_region_del_subregion(get_system_memory(), mem); -} - -void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr, - MemoryRegion *mem) -{ - memory_region_add_subregion(get_system_io(), addr, mem); -} - -void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem) -{ - memory_region_del_subregion(get_system_io(), mem); -} diff --git a/hw/sysbus.h b/hw/sysbus.h index b3e1f99db5..aa3d383277 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -50,6 +50,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, void sysbus_init_mmio_cb2(SysBusDevice *dev, mmio_mapfunc cb, mmio_mapfunc unmap); void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory); +MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n); void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p); void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target); void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size); @@ -57,14 +58,6 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size); void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq); void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr); -void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr, - MemoryRegion *mem); -void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr, - MemoryRegion *mem, unsigned priority); -void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem); -void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr, - MemoryRegion *mem); -void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem); /* Legacy helper function for creating devices. */ DeviceState *sysbus_create_varargs(const char *name, diff --git a/hw/tusb6010.c b/hw/tusb6010.c index b2bf35934d..de6ffc6133 100644 --- a/hw/tusb6010.c +++ b/hw/tusb6010.c @@ -23,9 +23,11 @@ #include "usb.h" #include "omap.h" #include "irq.h" -#include "tusb6010.h" +#include "devices.h" +#include "sysbus.h" -struct TUSBState { +typedef struct TUSBState { + SysBusDevice busdev; MemoryRegion iomem[2]; qemu_irq irq; MUSBState *musb; @@ -59,7 +61,7 @@ struct TUSBState { uint32_t pullup[2]; uint32_t control_config; uint32_t otg_timer_val; -}; +} TUSBState; #define TUSB_DEVCLOCK 60000000 /* 60 MHz */ @@ -234,16 +236,6 @@ struct TUSBState { #define TUSB_EP_CONFIG_XFR_SIZE(v) ((v) & 0x7fffffff) #define TUSB_PROD_TEST_RESET_VAL 0xa596 -MemoryRegion *tusb6010_sync_io(TUSBState *s) -{ - return &s->iomem[0]; -} - -MemoryRegion *tusb6010_async_io(TUSBState *s) -{ - return &s->iomem[1]; -} - static void tusb_intr_update(TUSBState *s) { if (s->control_config & TUSB_INT_CTRL_CONF_INT_POLARITY) @@ -723,9 +715,33 @@ static void tusb_musb_core_intr(void *opaque, int source, int level) } } -TUSBState *tusb6010_init(qemu_irq intr) +static void tusb6010_power(TUSBState *s, int on) { - TUSBState *s = g_malloc0(sizeof(*s)); + if (!on) { + s->power = 0; + } else if (!s->power && on) { + s->power = 1; + /* Pull the interrupt down after TUSB6010 comes up. */ + s->intr_ok = 0; + tusb_intr_update(s); + qemu_mod_timer(s->pwr_timer, + qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 2); + } +} + +static void tusb6010_irq(void *opaque, int source, int level) +{ + if (source) { + tusb_musb_core_intr(opaque, source - 1, level); + } else { + tusb6010_power(opaque, level); + } +} + +static void tusb6010_reset(DeviceState *dev) +{ + TUSBState *s = FROM_SYSBUS(TUSBState, sysbus_from_qdev(dev)); + int i; s->test_reset = TUSB_PROD_TEST_RESET_VAL; s->host_mode = 0; @@ -735,28 +751,59 @@ TUSBState *tusb6010_init(qemu_irq intr) s->mask = 0xffffffff; s->intr = 0x00000000; s->otg_timer_val = 0; - memory_region_init_io(&s->iomem[1], &tusb_async_ops, s, "tusb-async", - UINT32_MAX); - s->irq = intr; + s->scratch = 0; + s->prcm_config = 0; + s->prcm_mngmt = 0; + s->intr_ok = 0; + s->usbip_intr = 0; + s->usbip_mask = 0; + s->gpio_intr = 0; + s->gpio_mask = 0; + s->gpio_config = 0; + s->dma_intr = 0; + s->dma_mask = 0; + s->dma_map = 0; + s->dma_config = 0; + s->ep0_config = 0; + s->wkup_mask = 0; + s->pullup[0] = s->pullup[1] = 0; + s->control_config = 0; + for (i = 0; i < 15; i++) { + s->rx_config[i] = s->tx_config[i] = 0; + } +} + +static int tusb6010_init(SysBusDevice *dev) +{ + TUSBState *s = FROM_SYSBUS(TUSBState, dev); + qemu_irq *musb_irqs; + int i; s->otg_timer = qemu_new_timer_ns(vm_clock, tusb_otg_tick, s); s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s); - s->musb = musb_init(qemu_allocate_irqs(tusb_musb_core_intr, s, - __musb_irq_max)); - - return s; + memory_region_init_io(&s->iomem[1], &tusb_async_ops, s, "tusb-async", + UINT32_MAX); + sysbus_init_mmio_region(dev, &s->iomem[0]); + sysbus_init_mmio_region(dev, &s->iomem[1]); + sysbus_init_irq(dev, &s->irq); + qdev_init_gpio_in(&dev->qdev, tusb6010_irq, __musb_irq_max + 1); + musb_irqs = g_new0(qemu_irq, __musb_irq_max); + for (i = 0; i < __musb_irq_max; i++) { + musb_irqs[i] = qdev_get_gpio_in(&dev->qdev, i + 1); + } + s->musb = musb_init(musb_irqs); + return 0; } -void tusb6010_power(TUSBState *s, int on) -{ - if (!on) - s->power = 0; - else if (!s->power && on) { - s->power = 1; +static SysBusDeviceInfo tusb6010_info = { + .init = tusb6010_init, + .qdev.name = "tusb6010", + .qdev.size = sizeof(TUSBState), + .qdev.reset = tusb6010_reset, +}; - /* Pull the interrupt down after TUSB6010 comes up. */ - s->intr_ok = 0; - tusb_intr_update(s); - qemu_mod_timer(s->pwr_timer, - qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 2); - } +static void tusb6010_register_device(void) +{ + sysbus_register_withprop(&tusb6010_info); } + +device_init(tusb6010_register_device) diff --git a/hw/tusb6010.h b/hw/tusb6010.h deleted file mode 100644 index b85ee86215..0000000000 --- a/hw/tusb6010.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * tusb6010 interfaces - * - * Copyright 2011 Red Hat, Inc. and/or its affiliates - * - * Authors: - * Avi Kivity <avi@redhat.com> - * - * Derived from hw/devices.h. - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#ifndef TUSB6010_H -#define TUSB6010_H - -#include "targphys.h" -#include "memory.h" - -typedef struct TUSBState TUSBState; -TUSBState *tusb6010_init(qemu_irq intr); -MemoryRegion *tusb6010_sync_io(TUSBState *s); -MemoryRegion *tusb6010_async_io(TUSBState *s); -void tusb6010_power(TUSBState *s, int on); - -#endif diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 600cd1e5bd..f896f8c76b 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -41,6 +41,7 @@ static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e }; typedef struct UNINState { SysBusDevice busdev; PCIHostState host_state; + ReadWriteHandler data_handler; } UNINState; static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num) @@ -99,70 +100,67 @@ static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr) return retval; } -static void unin_data_write(void *opaque, target_phys_addr_t addr, - uint64_t val, unsigned len) +static void unin_data_write(ReadWriteHandler *handler, + pcibus_t addr, uint32_t val, int len) { - UNINState *s = opaque; - UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n", - addr, len, val); + UNINState *s = container_of(handler, UNINState, data_handler); + UNIN_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val); pci_data_write(s->host_state.bus, unin_get_config_reg(s->host_state.config_reg, addr), val, len); } -static uint64_t unin_data_read(void *opaque, target_phys_addr_t addr, - unsigned len) +static uint32_t unin_data_read(ReadWriteHandler *handler, + pcibus_t addr, int len) { - UNINState *s = opaque; + UNINState *s = container_of(handler, UNINState, data_handler); uint32_t val; val = pci_data_read(s->host_state.bus, unin_get_config_reg(s->host_state.config_reg, addr), len); - UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n", - addr, len, val); + UNIN_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val); return val; } -static const MemoryRegionOps unin_data_ops = { - .read = unin_data_read, - .write = unin_data_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - static int pci_unin_main_init_device(SysBusDevice *dev) { UNINState *s; + int pci_mem_config, pci_mem_data; /* Use values found on a real PowerMac */ /* Uninorth main bus */ s = FROM_SYSBUS(UNINState, dev); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s, - "pci-conf-data", 0x1000); - sysbus_init_mmio_region(dev, &s->host_state.conf_mem); - sysbus_init_mmio_region(dev, &s->host_state.data_mem); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + s->data_handler.read = unin_data_read; + s->data_handler.write = unin_data_write; + pci_mem_data = cpu_register_io_memory_simple(&s->data_handler, + DEVICE_LITTLE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, pci_mem_config); + sysbus_init_mmio(dev, 0x1000, pci_mem_data); qemu_register_reset(pci_unin_reset, &s->host_state); return 0; } - static int pci_u3_agp_init_device(SysBusDevice *dev) { UNINState *s; + int pci_mem_config, pci_mem_data; /* Uninorth U3 AGP bus */ s = FROM_SYSBUS(UNINState, dev); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &unin_data_ops, s, - "pci-conf-data", 0x1000); - sysbus_init_mmio_region(dev, &s->host_state.conf_mem); - sysbus_init_mmio_region(dev, &s->host_state.data_mem); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + s->data_handler.read = unin_data_read; + s->data_handler.write = unin_data_write; + pci_mem_data = cpu_register_io_memory_simple(&s->data_handler, + DEVICE_LITTLE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, pci_mem_config); + sysbus_init_mmio(dev, 0x1000, pci_mem_data); qemu_register_reset(pci_unin_reset, &s->host_state); @@ -172,32 +170,34 @@ static int pci_u3_agp_init_device(SysBusDevice *dev) static int pci_unin_agp_init_device(SysBusDevice *dev) { UNINState *s; + int pci_mem_config, pci_mem_data; /* Uninorth AGP bus */ s = FROM_SYSBUS(UNINState, dev); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops, - &s->host_state, "pci-conf-data", 0x1000); - sysbus_init_mmio_region(dev, &s->host_state.conf_mem); - sysbus_init_mmio_region(dev, &s->host_state.data_mem); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + pci_mem_data = pci_host_data_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, pci_mem_config); + sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; } static int pci_unin_internal_init_device(SysBusDevice *dev) { UNINState *s; + int pci_mem_config, pci_mem_data; /* Uninorth internal bus */ s = FROM_SYSBUS(UNINState, dev); - memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops, - &s->host_state, "pci-conf-idx", 0x1000); - memory_region_init_io(&s->host_state.data_mem, &pci_host_data_le_ops, - &s->host_state, "pci-conf-data", 0x1000); - sysbus_init_mmio_region(dev, &s->host_state.conf_mem); - sysbus_init_mmio_region(dev, &s->host_state.data_mem); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + pci_mem_data = pci_host_data_register_mmio(&s->host_state, + DEVICE_LITTLE_ENDIAN); + sysbus_init_mmio(dev, 0x1000, pci_mem_config); + sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; } diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c index 66aeb211af..c2f9241014 100644 --- a/hw/usb-ccid.c +++ b/hw/usb-ccid.c @@ -176,56 +176,56 @@ enum { */ }; -typedef struct __attribute__ ((__packed__)) CCID_Header { +typedef struct QEMU_PACKED CCID_Header { uint8_t bMessageType; uint32_t dwLength; uint8_t bSlot; uint8_t bSeq; } CCID_Header; -typedef struct __attribute__ ((__packed__)) CCID_BULK_IN { +typedef struct QEMU_PACKED CCID_BULK_IN { CCID_Header hdr; uint8_t bStatus; /* Only used in BULK_IN */ uint8_t bError; /* Only used in BULK_IN */ } CCID_BULK_IN; -typedef struct __attribute__ ((__packed__)) CCID_SlotStatus { +typedef struct QEMU_PACKED CCID_SlotStatus { CCID_BULK_IN b; uint8_t bClockStatus; } CCID_SlotStatus; -typedef struct __attribute__ ((__packed__)) CCID_Parameter { +typedef struct QEMU_PACKED CCID_Parameter { CCID_BULK_IN b; uint8_t bProtocolNum; uint8_t abProtocolDataStructure[0]; } CCID_Parameter; -typedef struct __attribute__ ((__packed__)) CCID_DataBlock { +typedef struct QEMU_PACKED CCID_DataBlock { CCID_BULK_IN b; uint8_t bChainParameter; uint8_t abData[0]; } CCID_DataBlock; /* 6.1.4 PC_to_RDR_XfrBlock */ -typedef struct __attribute__ ((__packed__)) CCID_XferBlock { +typedef struct QEMU_PACKED CCID_XferBlock { CCID_Header hdr; uint8_t bBWI; /* Block Waiting Timeout */ uint16_t wLevelParameter; /* XXX currently unused */ uint8_t abData[0]; } CCID_XferBlock; -typedef struct __attribute__ ((__packed__)) CCID_IccPowerOn { +typedef struct QEMU_PACKED CCID_IccPowerOn { CCID_Header hdr; uint8_t bPowerSelect; uint16_t abRFU; } CCID_IccPowerOn; -typedef struct __attribute__ ((__packed__)) CCID_IccPowerOff { +typedef struct QEMU_PACKED CCID_IccPowerOff { CCID_Header hdr; uint16_t abRFU; } CCID_IccPowerOff; -typedef struct __attribute__ ((__packed__)) CCID_SetParameters { +typedef struct QEMU_PACKED CCID_SetParameters { CCID_Header hdr; uint8_t bProtocolNum; uint16_t abRFU; @@ -176,6 +176,7 @@ static void vga_update_memory_access(VGACommonState *s) size = 0x8000; break; case 3: + default: base = 0xb8000; size = 0x8000; break; diff --git a/hw/vhost.c b/hw/vhost.c index 18860678ba..0870cb7d85 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -515,11 +515,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, }; struct VirtQueue *vvq = virtio_get_queue(vdev, idx); - if (!vdev->binding->set_host_notifier) { - fprintf(stderr, "binding does not support host notifiers\n"); - return -ENOSYS; - } - vq->num = state.num = virtio_queue_get_num(vdev, idx); r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state); if (r) { @@ -567,12 +562,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, r = -errno; goto fail_alloc; } - r = vdev->binding->set_host_notifier(vdev->binding_opaque, idx, true); - if (r < 0) { - fprintf(stderr, "Error binding host notifier: %d\n", -r); - goto fail_host_notifier; - } - file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq)); r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file); if (r) { @@ -591,8 +580,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, fail_call: fail_kick: - vdev->binding->set_host_notifier(vdev->binding_opaque, idx, false); -fail_host_notifier: fail_alloc: cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx), 0, 0); @@ -618,12 +605,6 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev, .index = idx, }; int r; - r = vdev->binding->set_host_notifier(vdev->binding_opaque, idx, false); - if (r < 0) { - fprintf(stderr, "vhost VQ %d host cleanup failed: %d\n", idx, r); - fflush(stderr); - } - assert (r >= 0); r = ioctl(dev->control, VHOST_GET_VRING_BASE, &state); if (r < 0) { fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r); @@ -697,6 +678,60 @@ bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev) hdev->force; } +/* Stop processing guest IO notifications in qemu. + * Start processing them in vhost in kernel. + */ +int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev) +{ + int i, r; + if (!vdev->binding->set_host_notifier) { + fprintf(stderr, "binding does not support host notifiers\n"); + r = -ENOSYS; + goto fail; + } + + for (i = 0; i < hdev->nvqs; ++i) { + r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, true); + if (r < 0) { + fprintf(stderr, "vhost VQ %d notifier binding failed: %d\n", i, -r); + goto fail_vq; + } + } + + return 0; +fail_vq: + while (--i >= 0) { + r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, false); + if (r < 0) { + fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r); + fflush(stderr); + } + assert (r >= 0); + } +fail: + return r; +} + +/* Stop processing guest IO notifications in vhost. + * Start processing them in qemu. + * This might actually run the qemu handlers right away, + * so virtio in qemu must be completely setup when this is called. + */ +void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev) +{ + int i, r; + + for (i = 0; i < hdev->nvqs; ++i) { + r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, false); + if (r < 0) { + fprintf(stderr, "vhost VQ %d notifier cleanup failed: %d\n", i, -r); + fflush(stderr); + } + assert (r >= 0); + } +} + +/* Host notifiers must be enabled at this point. */ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) { int i, r; @@ -762,6 +797,7 @@ fail: return r; } +/* Host notifiers must be enabled at this point. */ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) { int i, r; diff --git a/hw/vhost.h b/hw/vhost.h index c8c595a147..c9452f0732 100644 --- a/hw/vhost.h +++ b/hw/vhost.h @@ -46,5 +46,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev); bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); +int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); +void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); #endif diff --git a/hw/vhost_net.c b/hw/vhost_net.c index a55981200d..950a6b8d99 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -139,16 +139,22 @@ int vhost_net_start(struct vhost_net *net, { struct vhost_vring_file file = { }; int r; + + net->dev.nvqs = 2; + net->dev.vqs = net->vqs; + + r = vhost_dev_enable_notifiers(&net->dev, dev); + if (r < 0) { + goto fail_notifiers; + } if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr_mrg_rxbuf)); } - net->dev.nvqs = 2; - net->dev.vqs = net->vqs; r = vhost_dev_start(&net->dev, dev); if (r < 0) { - return r; + goto fail_start; } net->vc->info->poll(net->vc, false); @@ -173,6 +179,9 @@ fail: if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); } +fail_start: + vhost_dev_disable_notifiers(&net->dev, dev); +fail_notifiers: return r; } @@ -190,6 +199,7 @@ void vhost_net_stop(struct vhost_net *net, if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); } + vhost_dev_disable_notifiers(&net->dev, dev); } void vhost_net_cleanup(struct vhost_net *net) diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index aa9e51222f..333050cdac 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -196,7 +196,7 @@ static void virtex_init(ram_addr_t ram_size, target_phys_addr_t ram_base = 0; DriveInfo *dinfo; ram_addr_t phys_ram; - MemoryRegion *phys_flash = g_new(MemoryRegion, 1); + ram_addr_t phys_flash; qemu_irq irq[32], *cpu_irq; clk_setup_t clk_setup[7]; int kernel_size; @@ -215,13 +215,12 @@ static void virtex_init(ram_addr_t ram_size, phys_ram = qemu_ram_alloc(NULL, "ram", ram_size); cpu_register_physical_memory(ram_base, ram_size, phys_ram | IO_MEM_RAM); - memory_region_init_rom_device(phys_flash, &pflash_cfi01_ops_be, - NULL, "virtex.flash", FLASH_SIZE); + phys_flash = qemu_ram_alloc(NULL, "virtex.flash", FLASH_SIZE); dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi01_register(0xfc000000, phys_flash, dinfo ? dinfo->bdrv : NULL, (64 * 1024), FLASH_SIZE >> 16, - 1, 0x89, 0x18, 0x0000, 0x0); + 1, 0x89, 0x18, 0x0000, 0x0, 1); cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT]; dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0); diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h index e20cf6bc0d..73300ddc86 100644 --- a/hw/virtio-balloon.h +++ b/hw/virtio-balloon.h @@ -50,6 +50,6 @@ struct virtio_balloon_config typedef struct VirtIOBalloonStat { uint16_t tag; uint64_t val; -} __attribute__((packed)) VirtIOBalloonStat; +} QEMU_PACKED VirtIOBalloonStat; #endif diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index dad8c0a6a2..2a8ccd0aa9 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -47,6 +47,7 @@ typedef struct VirtIOBlockReq struct virtio_scsi_inhdr *scsi; QEMUIOVector qiov; struct VirtIOBlockReq *next; + BlockAcctCookie acct; } VirtIOBlockReq; static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) @@ -58,8 +59,6 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) stb_p(&req->in->status, status); virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in)); virtio_notify(&s->vdev, s->vq); - - g_free(req); } static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, @@ -81,6 +80,8 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, vm_stop(VMSTOP_DISKFULL); } else { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); + bdrv_acct_done(s->bs, &req->acct); + g_free(req); bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read); } @@ -100,6 +101,8 @@ static void virtio_blk_rw_complete(void *opaque, int ret) } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); + bdrv_acct_done(req->dev->bs, &req->acct); + g_free(req); } static void virtio_blk_flush_complete(void *opaque, int ret) @@ -113,6 +116,8 @@ static void virtio_blk_flush_complete(void *opaque, int ret) } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); + bdrv_acct_done(req->dev->bs, &req->acct); + g_free(req); } static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s) @@ -155,6 +160,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req) */ if (req->elem.out_num < 2 || req->elem.in_num < 3) { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); + g_free(req); return; } @@ -163,6 +169,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req) */ if (req->elem.out_num > 2 && req->elem.in_num > 3) { virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); + g_free(req); return; } @@ -229,11 +236,13 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req) stl_p(&req->scsi->data_len, hdr.dxfer_len); virtio_blk_req_complete(req, status); + g_free(req); } #else static void virtio_blk_handle_scsi(VirtIOBlockReq *req) { virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); + g_free(req); } #endif /* __linux__ */ @@ -266,6 +275,8 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb) { BlockDriverAIOCB *acb; + bdrv_acct_start(req->dev->bs, &req->acct, 0, BDRV_ACCT_FLUSH); + /* * Make sure all outstanding writes are posted to the backing device. */ @@ -284,6 +295,8 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb) sector = ldq_p(&req->out->sector); + bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE); + trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512); if (sector & req->dev->sector_mask) { @@ -317,6 +330,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req) sector = ldq_p(&req->out->sector); + bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ); + if (sector & req->dev->sector_mask) { virtio_blk_rw_complete(req, -EIO); return; @@ -370,6 +385,7 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req, s->serial ? s->serial : "", MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES)); virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); + g_free(req); } else if (type & VIRTIO_BLK_T_OUT) { qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], req->elem.out_num - 1); diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 5645d2bf3c..244dce45aa 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -49,7 +49,7 @@ struct virtio_blk_config uint8_t alignment_offset; uint16_t min_io_size; uint32_t opt_io_size; -} __attribute__((packed)); +} QEMU_PACKED; /* These two define direction. */ #define VIRTIO_BLK_T_IN 0 diff --git a/hw/virtio-net.h b/hw/virtio-net.h index 8af9a1ce55..44687414c9 100644 --- a/hw/virtio-net.h +++ b/hw/virtio-net.h @@ -72,7 +72,7 @@ struct virtio_net_config uint8_t mac[ETH_ALEN]; /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ uint16_t status; -} __attribute__((packed)); +} QEMU_PACKED; /* This is the first element of the scatter-gather list. If you don't * specify GSO or CSUM features, you can simply ignore the header. */ diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h index 36e9d222e5..ab138038c0 100644 --- a/hw/virtio-serial.h +++ b/hw/virtio-serial.h @@ -37,7 +37,7 @@ struct virtio_console_config { uint16_t rows; uint32_t max_nr_ports; -} __attribute__((packed)); +} QEMU_PACKED; struct virtio_console_control { uint32_t id; /* Port number */ diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 52d2d26f1b..aa682376ad 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -70,7 +70,7 @@ struct vmsvga_state_s { union { uint32_t *fifo; - struct __attribute__((__packed__)) { + struct QEMU_PACKED { uint32_t min; uint32_t max; uint32_t next_cmd; diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 31f91514f2..bd5c66916b 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -79,6 +79,7 @@ struct ioreq { struct XenBlkDev *blkdev; QLIST_ENTRY(ioreq) list; + BlockAcctCookie acct; }; struct XenBlkDev { @@ -401,6 +402,7 @@ static void qemu_aio_complete(void *opaque, int ret) ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; ioreq_unmap(ioreq); ioreq_finish(ioreq); + bdrv_acct_done(ioreq->blkdev->bs, &ioreq->acct); qemu_bh_schedule(ioreq->blkdev->bh); } @@ -419,6 +421,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) switch (ioreq->req.operation) { case BLKIF_OP_READ: + bdrv_acct_start(blkdev->bs, &ioreq->acct, ioreq->v.size, BDRV_ACCT_READ); ioreq->aio_inflight++; bdrv_aio_readv(blkdev->bs, ioreq->start / BLOCK_SIZE, &ioreq->v, ioreq->v.size / BLOCK_SIZE, @@ -429,6 +432,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) if (!ioreq->req.nr_segments) { break; } + + bdrv_acct_start(blkdev->bs, &ioreq->acct, ioreq->v.size, BDRV_ACCT_WRITE); ioreq->aio_inflight++; bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE, &ioreq->v, ioreq->v.size / BLOCK_SIZE, diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c index f35ba8461a..6f44c8466e 100644 --- a/hw/xilinx_ethlite.c +++ b/hw/xilinx_ethlite.c @@ -50,6 +50,7 @@ struct xlx_ethlite { SysBusDevice busdev; + MemoryRegion mmio; qemu_irq irq; NICState *nic; NICConf conf; @@ -70,7 +71,8 @@ static inline void eth_pulse_irq(struct xlx_ethlite *s) } } -static uint32_t eth_readl (void *opaque, target_phys_addr_t addr) +static uint64_t +eth_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct xlx_ethlite *s = opaque; uint32_t r = 0; @@ -98,10 +100,12 @@ static uint32_t eth_readl (void *opaque, target_phys_addr_t addr) } static void -eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +eth_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) { struct xlx_ethlite *s = opaque; unsigned int base = 0; + uint32_t value = val64; addr >>= 2; switch (addr) @@ -146,12 +150,14 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value) } } -static CPUReadMemoryFunc * const eth_read[] = { - NULL, NULL, ð_readl, -}; - -static CPUWriteMemoryFunc * const eth_write[] = { - NULL, NULL, ð_writel, +static const MemoryRegionOps eth_ops = { + .read = eth_read, + .write = eth_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } }; static int eth_can_rx(VLANClientState *nc) @@ -206,13 +212,12 @@ static NetClientInfo net_xilinx_ethlite_info = { static int xilinx_ethlite_init(SysBusDevice *dev) { struct xlx_ethlite *s = FROM_SYSBUS(typeof (*s), dev); - int regs; sysbus_init_irq(dev, &s->irq); s->rxbuf = 0; - regs = cpu_register_io_memory(eth_read, eth_write, s, DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4, regs); + memory_region_init_io(&s->mmio, ð_ops, s, "xilinx-ethlite", R_MAX * 4); + sysbus_init_mmio_region(dev, &s->mmio); qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c index cb72d5a14e..58b73d95cc 100644 --- a/hw/xilinx_intc.c +++ b/hw/xilinx_intc.c @@ -40,6 +40,7 @@ struct xlx_pic { SysBusDevice busdev; + MemoryRegion mmio; qemu_irq parent_irq; /* Configuration reg chosen at synthesis-time. QEMU populates @@ -72,7 +73,8 @@ static void update_irq(struct xlx_pic *p) } } -static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) +static uint64_t +pic_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct xlx_pic *p = opaque; uint32_t r = 0; @@ -91,9 +93,11 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) } static void -pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +pic_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) { struct xlx_pic *p = opaque; + uint32_t value = val64; addr >>= 2; D(qemu_log("%s addr=%x val=%x\n", __func__, addr * 4, value)); @@ -116,14 +120,14 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) update_irq(p); } -static CPUReadMemoryFunc * const pic_read[] = { - NULL, NULL, - &pic_readl, -}; - -static CPUWriteMemoryFunc * const pic_write[] = { - NULL, NULL, - &pic_writel, +static const MemoryRegionOps pic_ops = { + .read = pic_read, + .write = pic_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } }; static void irq_handler(void *opaque, int irq, int level) @@ -148,13 +152,12 @@ static void irq_handler(void *opaque, int irq, int level) static int xilinx_intc_init(SysBusDevice *dev) { struct xlx_pic *p = FROM_SYSBUS(typeof (*p), dev); - int pic_regs; qdev_init_gpio_in(&dev->qdev, irq_handler, 32); sysbus_init_irq(dev, &p->parent_irq); - pic_regs = cpu_register_io_memory(pic_read, pic_write, p, DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4, pic_regs); + memory_region_init_io(&p->mmio, &pic_ops, p, "xilinx-pic", R_MAX * 4); + sysbus_init_mmio_region(dev, &p->mmio); return 0; } diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index f1c7abc99e..8779c56f0b 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -59,6 +59,7 @@ struct xlx_timer struct timerblock { SysBusDevice busdev; + MemoryRegion mmio; qemu_irq irq; uint32_t nr_timers; uint32_t freq_hz; @@ -85,7 +86,8 @@ static void timer_update_irq(struct timerblock *t) qemu_set_irq(t->irq, !!irq); } -static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) +static uint64_t +timer_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct timerblock *t = opaque; struct xlx_timer *xt; @@ -134,11 +136,13 @@ static void timer_enable(struct xlx_timer *xt) } static void -timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +timer_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) { struct timerblock *t = opaque; struct xlx_timer *xt; unsigned int timer; + uint32_t value = val64; addr >>= 2; timer = timer_from_addr(addr); @@ -166,14 +170,14 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) timer_update_irq(t); } -static CPUReadMemoryFunc * const timer_read[] = { - NULL, NULL, - &timer_readl, -}; - -static CPUWriteMemoryFunc * const timer_write[] = { - NULL, NULL, - &timer_writel, +static const MemoryRegionOps timer_ops = { + .read = timer_read, + .write = timer_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } }; static void timer_hit(void *opaque) @@ -192,7 +196,6 @@ static int xilinx_timer_init(SysBusDevice *dev) { struct timerblock *t = FROM_SYSBUS(typeof (*t), dev); unsigned int i; - int timer_regs; /* All timers share a single irq line. */ sysbus_init_irq(dev, &t->irq); @@ -209,9 +212,9 @@ static int xilinx_timer_init(SysBusDevice *dev) ptimer_set_freq(xt->ptimer, t->freq_hz); } - timer_regs = cpu_register_io_memory(timer_read, timer_write, t, - DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4 * t->nr_timers, timer_regs); + memory_region_init_io(&t->mmio, &timer_ops, t, "xilinx-timer", + R_MAX * 4 * t->nr_timers); + sysbus_init_mmio_region(dev, &t->mmio); return 0; } diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c index 467a26cc9e..ceb7b4d9ed 100644 --- a/hw/xilinx_uartlite.c +++ b/hw/xilinx_uartlite.c @@ -49,6 +49,7 @@ struct xlx_uartlite { SysBusDevice busdev; + MemoryRegion mmio; CharDriverState *chr; qemu_irq irq; @@ -82,7 +83,8 @@ static void uart_update_status(struct xlx_uartlite *s) s->regs[R_STATUS] = r; } -static uint32_t uart_readl (void *opaque, target_phys_addr_t addr) +static uint64_t +uart_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct xlx_uartlite *s = opaque; uint32_t r = 0; @@ -107,9 +109,11 @@ static uint32_t uart_readl (void *opaque, target_phys_addr_t addr) } static void -uart_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +uart_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) { struct xlx_uartlite *s = opaque; + uint32_t value = val64; unsigned char ch = value; addr >>= 2; @@ -147,16 +151,14 @@ uart_writel (void *opaque, target_phys_addr_t addr, uint32_t value) uart_update_irq(s); } -static CPUReadMemoryFunc * const uart_read[] = { - &uart_readl, - &uart_readl, - &uart_readl, -}; - -static CPUWriteMemoryFunc * const uart_write[] = { - &uart_writel, - &uart_writel, - &uart_writel, +static const MemoryRegionOps uart_ops = { + .read = uart_read, + .write = uart_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4 + } }; static void uart_rx(void *opaque, const uint8_t *buf, int size) @@ -196,14 +198,12 @@ static void uart_event(void *opaque, int event) static int xilinx_uartlite_init(SysBusDevice *dev) { struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev); - int uart_regs; sysbus_init_irq(dev, &s->irq); uart_update_status(s); - uart_regs = cpu_register_io_memory(uart_read, uart_write, s, - DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4, uart_regs); + memory_region_init_io(&s->mmio, &uart_ops, s, "xilinx-uartlite", R_MAX * 4); + sysbus_init_mmio_region(dev, &s->mmio); s->chr = qdev_init_chardev(&dev->qdev); if (s->chr) @@ -280,11 +280,10 @@ static void z2_init(ram_addr_t ram_size, uint32_t sector_len = 0x10000; PXA2xxState *cpu; DriveInfo *dinfo; - const MemoryRegionOps *flash_ops; + int be; void *z2_lcd; i2c_bus *bus; DeviceState *wm; - MemoryRegion *flash = g_new(MemoryRegion, 1); if (!cpu_model) { cpu_model = "pxa270-c5"; @@ -294,9 +293,9 @@ static void z2_init(ram_addr_t ram_size, cpu = pxa270_init(z2_binfo.ram_size, cpu_model); #ifdef TARGET_WORDS_BIGENDIAN - flash_ops = &pflash_cfi01_ops_be; + be = 1; #else - flash_ops = &pflash_cfi01_ops_le; + be = 0; #endif dinfo = drive_get(IF_PFLASH, 0, 0); if (!dinfo) { @@ -305,11 +304,11 @@ static void z2_init(ram_addr_t ram_size, exit(1); } - memory_region_init_rom_device(flash, flash_ops, - NULL, "z2.flash0", Z2_FLASH_SIZE); - if (!pflash_cfi01_register(Z2_FLASH_BASE, flash, + if (!pflash_cfi01_register(Z2_FLASH_BASE, + qemu_ram_alloc(NULL, "z2.flash0", Z2_FLASH_SIZE), dinfo->bdrv, sector_len, - Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0)) { + Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0, + be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); } diff --git a/hw/zaurus.c b/hw/zaurus.c index c24aeb5763..0eeacf7cb3 100644 --- a/hw/zaurus.c +++ b/hw/zaurus.c @@ -246,7 +246,7 @@ device_init(scoop_register); #define MAGIC_CHG(a, b, c, d) ((d << 24) | (c << 16) | (b << 8) | a) -static struct __attribute__ ((__packed__)) sl_param_info { +static struct QEMU_PACKED sl_param_info { uint32_t comadj_keyword; int32_t comadj; @@ -42,16 +42,16 @@ SECTIONS .rel.plt : { *(.rel.plt) - PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE (__rel_iplt_start = .); *(.rel.iplt) - PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE (__rel_iplt_end = .); } .rela.plt : { *(.rela.plt) - PROVIDE_HIDDEN (__rela_iplt_start = .); + PROVIDE (__rela_iplt_start = .); *(.rela.iplt) - PROVIDE_HIDDEN (__rela_iplt_end = .); + PROVIDE (__rela_iplt_end = .); } .init : { *(.init) } =0x47ff041f .text : diff --git a/iohandler.c b/iohandler.c index 4deae1e6ab..4cc1c5ade6 100644 --- a/iohandler.c +++ b/iohandler.c @@ -80,12 +80,64 @@ int qemu_set_fd_handler2(int fd, return 0; } +typedef struct IOTrampoline +{ + GIOChannel *chan; + IOHandler *fd_read; + IOHandler *fd_write; + void *opaque; + guint tag; +} IOTrampoline; + +static gboolean fd_trampoline(GIOChannel *chan, GIOCondition cond, gpointer opaque) +{ + IOTrampoline *tramp = opaque; + + if ((cond & G_IO_IN) && tramp->fd_read) { + tramp->fd_read(tramp->opaque); + } + + if ((cond & G_IO_OUT) && tramp->fd_write) { + tramp->fd_write(tramp->opaque); + } + + return TRUE; +} + int qemu_set_fd_handler(int fd, IOHandler *fd_read, IOHandler *fd_write, void *opaque) { - return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); + static IOTrampoline fd_trampolines[FD_SETSIZE]; + IOTrampoline *tramp = &fd_trampolines[fd]; + + if (tramp->tag != 0) { + g_io_channel_unref(tramp->chan); + g_source_remove(tramp->tag); + tramp->tag = 0; + } + + if (fd_read || fd_write || opaque) { + GIOCondition cond = 0; + + tramp->fd_read = fd_read; + tramp->fd_write = fd_write; + tramp->opaque = opaque; + + if (fd_read) { + cond |= G_IO_IN | G_IO_ERR; + } + + if (fd_write) { + cond |= G_IO_OUT | G_IO_ERR; + } + + tramp->chan = g_io_channel_unix_new(fd); + tramp->tag = g_io_add_watch(tramp->chan, cond, fd_trampoline, tramp); + } + + return 0; } void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) @@ -479,7 +479,7 @@ static int kvm_check_many_ioeventfds(void) * Older kernels have a 6 device limit on the KVM io bus. Find out so we * can avoid creating too many ioeventfds. */ -#if defined(CONFIG_EVENTFD) && defined(CONFIG_IOTHREAD) +#if defined(CONFIG_EVENTFD) int ioeventfds[7]; int i, ret = 0; for (i = 0; i < ARRAY_SIZE(ioeventfds); i++) { diff --git a/libcacard/Makefile b/libcacard/Makefile index b3f5e6c011..bf052bcc12 100644 --- a/libcacard/Makefile +++ b/libcacard/Makefile @@ -20,7 +20,7 @@ QEMU_CFLAGS+=$(GLIB_CFLAGS) libcacard.lib-y=$(addsuffix .lo,$(basename $(libcacard-y))) vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o - $(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS) -lrt," LINK $@") + $(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@") clean: rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo .libs/* *.la *.pc @@ -39,7 +39,7 @@ install-libcacard: @echo "libtool is missing, please install and rerun configure"; exit 1 else libcacard.la: $(libcacard.lib-y) $(QEMU_OBJS_LIB) - $(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(libcacard_libs) -lrt," lt LINK $@") + $(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(libcacard_libs)," lt LINK $@") libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in sed -e 's|@LIBDIR@|$(libdir)|' \ diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c index a7b38340dc..2191f6038c 100644 --- a/libcacard/vscclient.c +++ b/libcacard/vscclient.c @@ -585,7 +585,7 @@ main( printf(" recv APDU: "); print_byte_array(pbSendBuffer, mhHeader.length); } - /* Transmit recieved APDU */ + /* Transmit received APDU */ dwSendLength = mhHeader.length; dwRecvLength = sizeof(pbRecvBuffer); reader = vreader_get_reader_by_id(mhHeader.reader_id); diff --git a/linux-user/signal.c b/linux-user/signal.c index 07ad07a58f..89276eb6a5 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -3064,10 +3064,10 @@ static void setup_frame(int sig, struct target_sigaction *ka, goto give_sigsegv; /* Set up registers for signal handler */ - regs->gregs[15] = (unsigned long) frame; + regs->gregs[15] = frame_addr; regs->gregs[4] = signal; /* Arg for signal handler */ regs->gregs[5] = 0; - regs->gregs[6] = (unsigned long) &frame->sc; + regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc); regs->pc = (unsigned long) ka->_sa_handler; unlock_user_struct(frame, frame_addr, 1); @@ -3127,10 +3127,10 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, goto give_sigsegv; /* Set up registers for signal handler */ - regs->gregs[15] = (unsigned long) frame; + regs->gregs[15] = frame_addr; regs->gregs[4] = signal; /* Arg for signal handler */ - regs->gregs[5] = (unsigned long) &frame->info; - regs->gregs[6] = (unsigned long) &frame->uc; + regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info); + regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc); regs->pc = (unsigned long) ka->_sa_handler; unlock_user_struct(frame, frame_addr, 1); @@ -3381,11 +3381,12 @@ static void setup_frame(int sig, struct target_sigaction *ka, goto badframe; /* Set up registers for signal handler */ - env->regs[1] = (unsigned long) frame; + env->regs[1] = frame_addr; /* Signal handler args: */ env->regs[5] = sig; /* Arg 0: signum */ env->regs[6] = 0; - env->regs[7] = (unsigned long) &frame->uc; /* arg 1: sigcontext */ + /* arg 1: sigcontext */ + env->regs[7] = frame_addr += offsetof(typeof(*frame), uc); /* Offset of 4 to handle microblaze rtid r14, 0 */ env->sregs[SR_PC] = (unsigned long)ka->_sa_handler; @@ -3559,11 +3560,11 @@ static void setup_frame(int sig, struct target_sigaction *ka, setup_sigcontext(&frame->sc, env); /* Move the stack and setup the arguments for the handler. */ - env->regs[R_SP] = (uint32_t) (unsigned long) frame; + env->regs[R_SP] = frame_addr; env->regs[10] = sig; env->pc = (unsigned long) ka->_sa_handler; /* Link SRP so the guest returns through the trampoline. */ - env->pregs[PR_SRP] = (uint32_t) (unsigned long) &frame->retcode[0]; + env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode); unlock_user_struct(frame, frame_addr, 1); return; @@ -3769,11 +3770,11 @@ static void setup_frame(int sig, struct target_sigaction *ka, } /* Set up registers for signal handler */ - env->regs[15] = (target_ulong)(unsigned long) frame; + env->regs[15] = frame_addr; env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; env->regs[2] = sig; //map_signal(sig); - env->regs[3] = (target_ulong)(unsigned long) &frame->sc; + env->regs[3] = frame_addr += offsetof(typeof(*frame), sc); /* We forgot to include these in the sigcontext. To avoid breaking binary compatibility, they are passed as args. */ @@ -3844,12 +3845,12 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, } /* Set up registers for signal handler */ - env->regs[15] = (target_ulong)(unsigned long) frame; + env->regs[15] = frame_addr; env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; env->regs[2] = sig; //map_signal(sig); - env->regs[3] = (target_ulong)(unsigned long) &frame->info; - env->regs[4] = (target_ulong)(unsigned long) &frame->uc; + env->regs[3] = frame_addr + offsetof(typeof(*frame), info); + env->regs[4] = frame_addr + offsetof(typeof(*frame), uc); return; give_sigsegv: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index a117407d84..15c44d45a8 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -1120,7 +1120,7 @@ struct target_stat64 { abi_ulong __pad7; /* will be high 32 bits of ctime someday */ unsigned long long st_ino; -} __attribute__((packed)); +} QEMU_PACKED; #ifdef TARGET_ARM struct target_eabi_stat64 { @@ -1151,7 +1151,7 @@ struct target_eabi_stat64 { abi_ulong target_st_ctime_nsec; unsigned long long st_ino; -} __attribute__ ((packed)); +} QEMU_PACKED; #endif #elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32) @@ -1294,7 +1294,7 @@ struct target_stat { #endif }; -struct __attribute__((__packed__)) target_stat64 { +struct QEMU_PACKED target_stat64 { unsigned long long st_dev; unsigned long long st_ino; unsigned int st_mode; @@ -1341,7 +1341,7 @@ struct target_stat { }; /* FIXME: Microblaze no-mmu user-space has a difference stat64 layout... */ -struct __attribute__((__packed__)) target_stat64 { +struct QEMU_PACKED target_stat64 { uint64_t st_dev; #define TARGET_STAT64_HAS_BROKEN_ST_INO 1 uint32_t pad0; @@ -1428,7 +1428,7 @@ struct target_stat64 { abi_ulong target_st_ctime_nsec; unsigned long long st_ino; -} __attribute__((packed)); +} QEMU_PACKED; #elif defined(TARGET_ABI_MIPSN64) @@ -1680,7 +1680,7 @@ struct target_stat { /* This matches struct stat64 in glibc2.1, hence the absolutely * insane amounts of padding around dev_t's. */ -struct __attribute__((__packed__)) target_stat64 { +struct QEMU_PACKED target_stat64 { unsigned long long st_dev; unsigned char __pad0[4]; @@ -2095,7 +2095,7 @@ struct target_flock64 { unsigned long long l_start; unsigned long long l_len; int l_pid; -}__attribute__((packed)); +} QEMU_PACKED; #ifdef TARGET_ARM struct target_eabi_flock64 { @@ -2105,7 +2105,7 @@ struct target_eabi_flock64 { unsigned long long l_start; unsigned long long l_len; int l_pid; -}__attribute__((packed)); +} QEMU_PACKED; #endif /* soundcard defines */ diff --git a/m68k-semi.c b/m68k-semi.c index 7fde10e8f3..bab01ee863 100644 --- a/m68k-semi.c +++ b/m68k-semi.c @@ -70,12 +70,12 @@ struct m68k_gdb_stat { gdb_time_t gdb_st_atime; /* time of last access */ gdb_time_t gdb_st_mtime; /* time of last modification */ gdb_time_t gdb_st_ctime; /* time of last change */ -} __attribute__((packed)); +} QEMU_PACKED; struct gdb_timeval { gdb_time_t tv_sec; /* second */ uint64_t tv_usec; /* microsecond */ -} __attribute__((packed)); +} QEMU_PACKED; #define GDB_O_RDONLY 0x0 #define GDB_O_WRONLY 0x1 @@ -304,7 +304,7 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr) } if (!fr->readable) { - phys_offset &= TARGET_PAGE_MASK; + phys_offset &= ~TARGET_PAGE_MASK & ~IO_MEM_ROMD; } cpu_register_physical_memory_log(fr->addr.start, @@ -962,11 +962,14 @@ void memory_region_init_alias(MemoryRegion *mr, void memory_region_init_rom_device(MemoryRegion *mr, const MemoryRegionOps *ops, + void *opaque, DeviceState *dev, const char *name, uint64_t size) { memory_region_init(mr, name, size); + mr->ops = ops; + mr->opaque = opaque; mr->terminates = true; mr->destructor = memory_region_destructor_rom_device; mr->ram_addr = qemu_ram_alloc(dev, name, size); @@ -1060,7 +1063,7 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr) assert(mr->terminates); - return qemu_get_ram_ptr(mr->ram_addr); + return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK); } static void memory_region_update_coalesced_range(MemoryRegion *mr) @@ -235,6 +235,7 @@ void memory_region_init_alias(MemoryRegion *mr, */ void memory_region_init_rom_device(MemoryRegion *mr, const MemoryRegionOps *ops, + void *opaque, DeviceState *dev, /* FIXME: layering violation */ const char *name, uint64_t size); @@ -79,36 +79,34 @@ SECTIONS } .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN (0x40000) - ((0x40000 - .) & (0x40000 - 1)); . = DATA_SEGMENT_ALIGN (0x40000, 0x1000); /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { @@ -57,9 +57,11 @@ #include "json-parser.h" #include "osdep.h" #include "cpu.h" -#ifdef CONFIG_SIMPLE_TRACE -#include "trace.h" +#include "trace/control.h" +#ifdef CONFIG_TRACE_SIMPLE +#include "trace/simple.h" #endif +#include "trace/control.h" #include "ui/qemu-spice.h" //#define DEBUG @@ -592,18 +594,18 @@ static void do_help_cmd(Monitor *mon, const QDict *qdict) help_cmd(mon, qdict_get_try_str(qdict, "name")); } -#ifdef CONFIG_SIMPLE_TRACE -static void do_change_trace_event_state(Monitor *mon, const QDict *qdict) +static void do_trace_event_set_state(Monitor *mon, const QDict *qdict) { const char *tp_name = qdict_get_str(qdict, "name"); bool new_state = qdict_get_bool(qdict, "option"); - int ret = st_change_trace_event_state(tp_name, new_state); + int ret = trace_event_set_state(tp_name, new_state); if (!ret) { monitor_printf(mon, "unknown event name \"%s\"\n", tp_name); } } +#ifdef CONFIG_SIMPLE_TRACE static void do_trace_file(Monitor *mon, const QDict *qdict) { const char *op = qdict_get_try_str(qdict, "op"); @@ -996,17 +998,17 @@ static void do_info_cpu_stats(Monitor *mon) } #endif -#if defined(CONFIG_SIMPLE_TRACE) +#if defined(CONFIG_TRACE_SIMPLE) static void do_info_trace(Monitor *mon) { st_print_trace((FILE *)mon, &monitor_fprintf); } +#endif -static void do_info_trace_events(Monitor *mon) +static void do_trace_print_events(Monitor *mon) { - st_print_trace_events((FILE *)mon, &monitor_fprintf); + trace_print_events((FILE *)mon, &monitor_fprintf); } -#endif /** * do_quit(): Quit QEMU execution @@ -1189,7 +1191,6 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d { const char *protocol = qdict_get_str(qdict, "protocol"); const char *fdname = qdict_get_str(qdict, "fdname"); - int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); CharDriverState *s; if (strcmp(protocol, "spice") == 0) { @@ -1203,6 +1204,7 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d #ifdef CONFIG_VNC } else if (strcmp(protocol, "vnc") == 0) { int fd = monitor_get_fd(mon, fdname); + int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); vnc_display_add_client(NULL, fd, skipauth); return 0; #endif @@ -3135,7 +3137,7 @@ static const mon_cmd_t info_cmds[] = { .help = "show roms", .mhandler.info = do_info_roms, }, -#if defined(CONFIG_SIMPLE_TRACE) +#if defined(CONFIG_TRACE_SIMPLE) { .name = "trace", .args_type = "", @@ -3143,14 +3145,14 @@ static const mon_cmd_t info_cmds[] = { .help = "show current contents of trace buffer", .mhandler.info = do_info_trace, }, +#endif { .name = "trace-events", .args_type = "", .params = "", .help = "show available trace-events & their state", - .mhandler.info = do_info_trace_events, + .mhandler.info = do_trace_print_events, }, -#endif { .name = NULL, }, @@ -31,13 +31,13 @@ struct nbd_request { uint64_t handle; uint64_t from; uint32_t len; -} __attribute__ ((__packed__)); +} QEMU_PACKED; struct nbd_reply { uint32_t magic; uint32_t error; uint64_t handle; -} __attribute__ ((__packed__)); +} QEMU_PACKED; enum { NBD_CMD_READ = 0, @@ -174,11 +174,6 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data); #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" -#ifdef __sun__ -#define SMBD_COMMAND "/usr/sfw/sbin/smbd" -#else -#define SMBD_COMMAND "/usr/sbin/smbd" -#endif void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd); diff --git a/net/slirp.c b/net/slirp.c index 3b39d21183..c6cda5dcb2 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -529,7 +529,7 @@ static int slirp_smb(SlirpState* s, const char *exported_dir, fclose(f); snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s", - SMBD_COMMAND, smb_conf); + CONFIG_SMBD_COMMAND, smb_conf); if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0) { slirp_smb_cleanup(s); diff --git a/posix-aio-compat.c b/posix-aio-compat.c index babb0940dd..3193dbf83c 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -30,6 +30,7 @@ #include "block/raw-posix-aio.h" +static void do_spawn_thread(void); struct qemu_paiocb { BlockDriverAIOCB common; @@ -64,6 +65,9 @@ static pthread_attr_t attr; static int max_threads = 64; static int cur_threads = 0; static int idle_threads = 0; +static int new_threads = 0; /* backlog of threads we need to create */ +static int pending_threads = 0; /* threads created but not running yet */ +static QEMUBH *new_thread_bh; static QTAILQ_HEAD(, qemu_paiocb) request_list; #ifdef CONFIG_PREADV @@ -311,6 +315,11 @@ static void *aio_thread(void *unused) pid = getpid(); + mutex_lock(&lock); + pending_threads--; + mutex_unlock(&lock); + do_spawn_thread(); + while (1) { struct qemu_paiocb *aiocb; ssize_t ret = 0; @@ -381,11 +390,20 @@ static void *aio_thread(void *unused) return NULL; } -static void spawn_thread(void) +static void do_spawn_thread(void) { sigset_t set, oldset; - cur_threads++; + mutex_lock(&lock); + if (!new_threads) { + mutex_unlock(&lock); + return; + } + + new_threads--; + pending_threads++; + + mutex_unlock(&lock); /* block all signals */ if (sigfillset(&set)) die("sigfillset"); @@ -396,6 +414,27 @@ static void spawn_thread(void) if (sigprocmask(SIG_SETMASK, &oldset, NULL)) die("sigprocmask restore"); } +static void spawn_thread_bh_fn(void *opaque) +{ + do_spawn_thread(); +} + +static void spawn_thread(void) +{ + cur_threads++; + new_threads++; + /* If there are threads being created, they will spawn new workers, so + * we don't spend time creating many threads in a loop holding a mutex or + * starving the current vcpu. + * + * If there are no idle threads, ask the main thread to create one, so we + * inherit the correct affinity instead of the vcpu affinity. + */ + if (!pending_threads) { + qemu_bh_schedule(new_thread_bh); + } +} + static void qemu_paio_submit(struct qemu_paiocb *aiocb) { aiocb->ret = -EINPROGRESS; @@ -665,6 +704,7 @@ int paio_init(void) die2(ret, "pthread_attr_setdetachstate"); QTAILQ_INIT(&request_list); + new_thread_bh = qemu_bh_new(spawn_thread_bh_fn, NULL); posix_aio_state = s; return 0; @@ -79,36 +79,34 @@ SECTIONS } .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN (0x10000, 0x1000); /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { @@ -81,14 +81,12 @@ SECTIONS .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN (0x10000, 0x1000); /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } diff --git a/qemu-config.c b/qemu-config.c index 1eb6b9a709..7a7854fd06 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -55,7 +55,8 @@ static QemuOptsList qemu_drive_opts = { },{ .name = "cache", .type = QEMU_OPT_STRING, - .help = "host cache usage (none, writeback, writethrough, unsafe)", + .help = "host cache usage (none, writeback, writethrough, " + "directsync, unsafe)", },{ .name = "aio", .type = QEMU_OPT_STRING, @@ -302,20 +303,21 @@ static QemuOptsList qemu_mon_opts = { }, }; -#ifdef CONFIG_SIMPLE_TRACE static QemuOptsList qemu_trace_opts = { .name = "trace", .implied_opt_name = "trace", .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head), .desc = { { + .name = "events", + .type = QEMU_OPT_STRING, + },{ .name = "file", .type = QEMU_OPT_STRING, }, { /* end of list */ } }, }; -#endif static QemuOptsList qemu_cpudef_opts = { .name = "cpudef", @@ -516,9 +518,7 @@ static QemuOptsList *vm_config_groups[32] = { &qemu_global_opts, &qemu_mon_opts, &qemu_cpudef_opts, -#ifdef CONFIG_SIMPLE_TRACE &qemu_trace_opts, -#endif &qemu_option_rom_opts, &qemu_machine_opts, &qemu_boot_opts, diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c index a80f437c59..2a385a3bb8 100644 --- a/qemu-coroutine-lock.c +++ b/qemu-coroutine-lock.c @@ -115,3 +115,47 @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex) trace_qemu_co_mutex_unlock_return(mutex, self); } + +void qemu_co_rwlock_init(CoRwlock *lock) +{ + memset(lock, 0, sizeof(*lock)); + qemu_co_queue_init(&lock->queue); +} + +void qemu_co_rwlock_rdlock(CoRwlock *lock) +{ + while (lock->writer) { + qemu_co_queue_wait(&lock->queue); + } + lock->reader++; +} + +void qemu_co_rwlock_unlock(CoRwlock *lock) +{ + assert(qemu_in_coroutine()); + if (lock->writer) { + lock->writer = false; + while (!qemu_co_queue_empty(&lock->queue)) { + /* + * Wakeup every body. This will include some + * writers too. + */ + qemu_co_queue_next(&lock->queue); + } + } else { + lock->reader--; + assert(lock->reader >= 0); + /* Wakeup only one waiting writer */ + if (!lock->reader) { + qemu_co_queue_next(&lock->queue); + } + } +} + +void qemu_co_rwlock_wrlock(CoRwlock *lock) +{ + while (lock->writer || lock->reader) { + qemu_co_queue_wait(&lock->queue); + } + lock->writer = true; +} diff --git a/qemu-coroutine.h b/qemu-coroutine.h index 2f2fd95552..b8fc4f4332 100644 --- a/qemu-coroutine.h +++ b/qemu-coroutine.h @@ -156,4 +156,36 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); */ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); +typedef struct CoRwlock { + bool writer; + int reader; + CoQueue queue; +} CoRwlock; + +/** + * Initialises a CoRwlock. This must be called before any other operation + * is used on the CoRwlock + */ +void qemu_co_rwlock_init(CoRwlock *lock); + +/** + * Read locks the CoRwlock. If the lock cannot be taken immediately because + * of a parallel writer, control is transferred to the caller of the current + * coroutine. + */ +void qemu_co_rwlock_rdlock(CoRwlock *lock); + +/** + * Write Locks the mutex. If the lock cannot be taken immediately because + * of a parallel reader, control is transferred to the caller of the current + * coroutine. + */ +void qemu_co_rwlock_wrlock(CoRwlock *lock); + +/** + * Unlocks the read/write lock and schedules the next coroutine that was + * waiting for this lock to be run. + */ +void qemu_co_rwlock_unlock(CoRwlock *lock); + #endif /* QEMU_COROUTINE_H */ @@ -51,7 +51,7 @@ static struct GAState *ga_state; static void quit_handler(int sig) { - g_debug("recieved signal num %d, quitting", sig); + g_debug("received signal num %d, quitting", sig); if (g_main_loop_is_running(ga_state->main_loop)) { g_main_loop_quit(ga_state->main_loop); diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index 1299e83ef2..4be00a5edd 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -28,9 +28,9 @@ STEXI ETEXI DEF("convert", img_convert, - "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename") + "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename") STEXI -@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename} +@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} ETEXI DEF("info", img_info, diff --git a/qemu-img.c b/qemu-img.c index 95f3219571..6a3973163f 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -66,7 +66,8 @@ static void help(void) " 'filename' is a disk image filename\n" " 'fmt' is the disk image format. It is guessed automatically in most cases\n" " 'cache' is the cache mode used to write the output disk image, the valid\n" - " options are: 'none', 'writeback' (default), 'writethrough' and 'unsafe'\n" + " options are: 'none', 'writeback' (default), 'writethrough', 'directsync'\n" + " and 'unsafe'\n" " 'size' is the disk image size in bytes. Optional suffixes\n" " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n" " and T (terabyte, 1024G) are supported. 'b' is ignored.\n" @@ -81,6 +82,8 @@ static void help(void) " rebasing in this case (useful for renaming the backing file)\n" " '-h' with or without a command shows this help and lists the supported formats\n" " '-p' show progress of command (only certain commands)\n" + " '-S' indicates the consecutive number of bytes that must contain only zeros\n" + " for qemu-img to create a sparse image during conversion\n" "\n" "Parameters to snapshot subcommand:\n" " 'snapshot' is the name of the snapshot to create, apply or delete\n" @@ -183,27 +186,6 @@ static int read_password(char *buf, int buf_size) } #endif -static int set_cache_flag(const char *mode, int *flags) -{ - *flags &= ~BDRV_O_CACHE_MASK; - - if (!strcmp(mode, "none") || !strcmp(mode, "off")) { - *flags |= BDRV_O_CACHE_WB; - *flags |= BDRV_O_NOCACHE; - } else if (!strcmp(mode, "writeback")) { - *flags |= BDRV_O_CACHE_WB; - } else if (!strcmp(mode, "unsafe")) { - *flags |= BDRV_O_CACHE_WB; - *flags |= BDRV_O_NO_FLUSH; - } else if (!strcmp(mode, "writethrough")) { - /* this is the default */ - } else { - return -1; - } - - return 0; -} - static int print_block_option_help(const char *filename, const char *fmt) { BlockDriver *drv, *proto_drv; @@ -495,7 +477,7 @@ static int img_commit(int argc, char **argv) filename = argv[optind++]; flags = BDRV_O_RDWR; - ret = set_cache_flag(cache, &flags); + ret = bdrv_parse_cache_flags(cache, &flags); if (ret < 0) { error_report("Invalid cache option: %s", cache); return -1; @@ -591,6 +573,48 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum) } /* + * Like is_allocated_sectors, but if the buffer starts with a used sector, + * up to 'min' consecutive sectors containing zeros are ignored. This avoids + * breaking up write requests for only small sparse areas. + */ +static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum, + int min) +{ + int ret; + int num_checked, num_used; + + if (n < min) { + min = n; + } + + ret = is_allocated_sectors(buf, n, pnum); + if (!ret) { + return ret; + } + + num_used = *pnum; + buf += BDRV_SECTOR_SIZE * *pnum; + n -= *pnum; + num_checked = num_used; + + while (n > 0) { + ret = is_allocated_sectors(buf, n, pnum); + + buf += BDRV_SECTOR_SIZE * *pnum; + n -= *pnum; + num_checked += *pnum; + if (ret) { + num_used = num_checked; + } else if (*pnum >= min) { + break; + } + } + + *pnum = num_used; + return 1; +} + +/* * Compares two buffers sector by sector. Returns 0 if the first sector of both * buffers matches, non-zero otherwise. * @@ -640,6 +664,7 @@ static int img_convert(int argc, char **argv) char *options = NULL; const char *snapshot_name = NULL; float local_progress; + int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */ fmt = NULL; out_fmt = "raw"; @@ -647,7 +672,7 @@ static int img_convert(int argc, char **argv) out_baseimg = NULL; compress = 0; for(;;) { - c = getopt(argc, argv, "f:O:B:s:hce6o:pt:"); + c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:"); if (c == -1) { break; } @@ -682,6 +707,18 @@ static int img_convert(int argc, char **argv) case 's': snapshot_name = optarg; break; + case 'S': + { + int64_t sval; + sval = strtosz_suffix(optarg, NULL, STRTOSZ_DEFSUFFIX_B); + if (sval < 0) { + error_report("Invalid minimum zero buffer size for sparse output specified"); + return 1; + } + + min_sparse = sval / BDRV_SECTOR_SIZE; + break; + } case 'p': progress = 1; break; @@ -819,7 +856,7 @@ static int img_convert(int argc, char **argv) } flags = BDRV_O_RDWR; - ret = set_cache_flag(cache, &flags); + ret = bdrv_parse_cache_flags(cache, &flags); if (ret < 0) { error_report("Invalid cache option: %s", cache); return -1; @@ -834,7 +871,7 @@ static int img_convert(int argc, char **argv) bs_i = 0; bs_offset = 0; bdrv_get_geometry(bs[0], &bs_sectors); - buf = g_malloc(IO_BUF_SIZE); + buf = qemu_blockalign(out_bs, IO_BUF_SIZE); if (compress) { ret = bdrv_get_info(out_bs, &bdi); @@ -890,7 +927,8 @@ static int img_convert(int argc, char **argv) ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow); if (ret < 0) { - error_report("error while reading"); + error_report("error while reading sector %" PRId64 ": %s", + bs_num, strerror(-ret)); goto out; } @@ -908,8 +946,8 @@ static int img_convert(int argc, char **argv) ret = bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors); if (ret != 0) { - error_report("error while compressing sector %" PRId64, - sector_num); + error_report("error while compressing sector %" PRId64 + ": %s", sector_num, strerror(-ret)); goto out; } } @@ -972,7 +1010,8 @@ static int img_convert(int argc, char **argv) ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n); if (ret < 0) { - error_report("error while reading"); + error_report("error while reading sector %" PRId64 ": %s", + sector_num - bs_offset, strerror(-ret)); goto out; } /* NOTE: at the same time we convert, we do not write zero @@ -988,10 +1027,11 @@ static int img_convert(int argc, char **argv) sectors that are entirely 0, since whatever data was already there is garbage, not 0s. */ if (!has_zero_init || out_baseimg || - is_allocated_sectors(buf1, n, &n1)) { + is_allocated_sectors_min(buf1, n, &n1, min_sparse)) { ret = bdrv_write(out_bs, sector_num, buf1, n1); if (ret < 0) { - error_report("error while writing"); + error_report("error while writing sector %" PRId64 + ": %s", sector_num, strerror(-ret)); goto out; } } @@ -1006,7 +1046,7 @@ out: qemu_progress_end(); free_option_parameters(create_options); free_option_parameters(param); - g_free(buf); + qemu_vfree(buf); if (out_bs) { bdrv_delete(out_bs); } @@ -1291,7 +1331,7 @@ static int img_rebase(int argc, char **argv) qemu_progress_print(0, 100); flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0); - ret = set_cache_flag(cache, &flags); + ret = bdrv_parse_cache_flags(cache, &flags); if (ret < 0) { error_report("Invalid cache option: %s", cache); return -1; @@ -1373,8 +1413,8 @@ static int img_rebase(int argc, char **argv) uint8_t * buf_new; float local_progress; - buf_old = g_malloc(IO_BUF_SIZE); - buf_new = g_malloc(IO_BUF_SIZE); + buf_old = qemu_blockalign(bs, IO_BUF_SIZE); + buf_new = qemu_blockalign(bs, IO_BUF_SIZE); bdrv_get_geometry(bs, &num_sectors); @@ -1430,8 +1470,8 @@ static int img_rebase(int argc, char **argv) qemu_progress_print(local_progress, 100); } - g_free(buf_old); - g_free(buf_new); + qemu_vfree(buf_old); + qemu_vfree(buf_new); } /* diff --git a/qemu-img.texi b/qemu-img.texi index 495a1b6695..70fa321dff 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -40,6 +40,11 @@ indicates that target image must be compressed (qcow format only) with or without a command shows help and lists the supported formats @item -p display progress bar (convert and rebase commands only) +@item -S @var{size} +indicates the consecutive number of bytes that must contain only zeros +for qemu-img to create a sparse image during conversion. This value is rounded +down to the nearest 512 bytes. You may use the common size suffixes like +@code{k} for kilobytes. @end table Parameters to snapshot subcommand: @@ -86,7 +91,7 @@ it doesn't need to be specified separately in this case. Commit the changes recorded in @var{filename} in its base image. -@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename} +@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename} using format @var{output_fmt}. It can be optionally compressed (@code{-c} diff --git a/qemu-options.hx b/qemu-options.hx index d86815dc04..659ecb2db7 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -133,7 +133,7 @@ ETEXI DEF("drive", HAS_ARG, QEMU_OPTION_drive, "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n" " [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n" - " [,cache=writethrough|writeback|none|unsafe][,format=f]\n" + " [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n" " [,serial=s][,addr=A][,id=name][,aio=threads|native]\n" " [,readonly=on|off]\n" " use 'file' as a drive image\n", QEMU_ARCH_ALL) @@ -164,7 +164,7 @@ These options have the same definition as they have in @option{-hdachs}. @item snapshot=@var{snapshot} @var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}). @item cache=@var{cache} -@var{cache} is "none", "writeback", "unsafe", or "writethrough" and controls how the host cache is used to access block data. +@var{cache} is "none", "writeback", "unsafe", "directsync" or "writethrough" and controls how the host cache is used to access block data. @item aio=@var{aio} @var{aio} is "threads", or "native" and selects between pthread based disk I/O and native Linux AIO. @item format=@var{format} @@ -199,6 +199,10 @@ The host page cache can be avoided entirely with @option{cache=none}. This will attempt to do disk IO directly to the guests memory. QEMU may still perform an internal copy of the data. +The host page cache can be avoided while only sending write notifications to +the guest when the data has been reported as written by the storage subsystem +using @option{cache=directsync}. + Some block drivers perform badly with @option{cache=writethrough}, most notably, qcow2. If performance is more important than correctness, @option{cache=writeback} should be used with qcow2. @@ -1273,9 +1277,9 @@ or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000). Then @file{@var{dir}} can be accessed in @file{\\smbserver\qemu}. -Note that a SAMBA server must be installed on the host OS in -@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from -Red Hat 9, Fedora Core 3 and OpenSUSE 11.x. +Note that a SAMBA server must be installed on the host OS. +QEMU was tested successfully with smbd versions from Red Hat 9, +Fedora Core 3 and OpenSUSE 11.x. @item hostfwd=[tcp|udp]:[@var{hostaddr}]:@var{hostport}-[@var{guestaddr}]:@var{guestport} Redirect incoming TCP or UDP connections to the host port @var{hostport} to @@ -2432,17 +2436,32 @@ Normally QEMU loads a configuration file from @var{sysconfdir}/qemu.conf and @var{sysconfdir}/target-@var{ARCH}.conf on startup. The @code{-nodefconfig} option will prevent QEMU from loading these configuration files at startup. ETEXI -#ifdef CONFIG_SIMPLE_TRACE DEF("trace", HAS_ARG, QEMU_OPTION_trace, - "-trace\n" - " Specify a trace file to log traces to\n", + "-trace [events=<file>][,file=<file>]\n" + " specify tracing options\n", QEMU_ARCH_ALL) STEXI -@item -trace +HXCOMM This line is not accurate, as some sub-options are backend-specific but +HXCOMM HX does not support conditional compilation of text. +@item -trace [events=@var{file}][,file=@var{file}] @findex -trace -Specify a trace file to log output traces to. + +Specify tracing options. + +@table @option +@item events=@var{file} +Immediately enable events listed in @var{file}. +The file must contain one event name (as listed in the @var{trace-events} file) +per line. + +This option is only available when using the @var{simple} and @var{stderr} +tracing backends. +@item file=@var{file} +Log output traces to @var{file}. + +This option is only available when using the @var{simple} tracing backend. +@end table ETEXI -#endif HXCOMM This is the last statement. Insert new options before this line! STEXI diff --git a/qemu-timer.c b/qemu-timer.c index 19313d3b00..46dd483fdd 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -101,22 +101,6 @@ static int64_t cpu_get_clock(void) } } -#ifndef CONFIG_IOTHREAD -static int64_t qemu_icount_delta(void) -{ - if (!use_icount) { - return 5000 * (int64_t) 1000000; - } else if (use_icount == 1) { - /* When not using an adaptive execution frequency - we tend to get badly out of sync with real time, - so just delay for a reasonable amount of time. */ - return 0; - } else { - return cpu_get_icount() - cpu_get_clock(); - } -} -#endif - /* enable cpu_get_ticks() */ void cpu_enable_ticks(void) { @@ -688,9 +672,7 @@ void configure_icount(const char *option) if (!option) return; -#ifdef CONFIG_IOTHREAD vm_clock->warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL); -#endif if (strcmp(option, "auto") != 0) { icount_time_shift = strtol(option, NULL, 0); @@ -1178,41 +1160,6 @@ void quit_timers(void) int qemu_calculate_timeout(void) { -#ifndef CONFIG_IOTHREAD - int timeout; - - if (!vm_running) - timeout = 5000; - else { - /* XXX: use timeout computed from timers */ - int64_t add; - int64_t delta; - /* Advance virtual time to the next event. */ - delta = qemu_icount_delta(); - if (delta > 0) { - /* If virtual time is ahead of real time then just - wait for IO. */ - timeout = (delta + 999999) / 1000000; - } else { - /* Wait for either IO to occur or the next - timer event. */ - add = qemu_next_icount_deadline(); - /* We advance the timer before checking for IO. - Limit the amount we advance so that early IO - activity won't get the guest too far ahead. */ - if (add > 10000000) - add = 10000000; - delta += add; - qemu_icount += qemu_icount_round (add); - timeout = delta / 1000000; - if (timeout < 0) - timeout = 0; - } - } - - return timeout; -#else /* CONFIG_IOTHREAD */ return 1000; -#endif } diff --git a/qmp-commands.hx b/qmp-commands.hx index 03f67da198..27cc66ebc9 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1201,6 +1201,10 @@ Each json-object contain the following: - "wr_bytes": bytes written (json-int) - "rd_operations": read operations (json-int) - "wr_operations": write operations (json-int) + - "flush_operations": cache flush operations (json-int) + - "wr_total_time_ns": total time spend on writes in nano-seconds (json-int) + - "rd_total_time_ns": total time spend on reads in nano-seconds (json-int) + - "flush_total_time_ns": total time spend on cache flushes in nano-seconds (json-int) - "wr_highest_offset": Highest offset of a sector written since the BlockDriverState has been opened (json-int) - "parent": Contains recursively the statistics of the underlying @@ -1222,6 +1226,10 @@ Example: "wr_operations":751, "rd_bytes":122567168, "rd_operations":36772 + "wr_total_times_ns":313253456 + "rd_total_times_ns":3465673657 + "flush_total_times_ns":49653 + "flush_operations":61, } }, "stats":{ @@ -1230,6 +1238,10 @@ Example: "wr_operations":692, "rd_bytes":122739200, "rd_operations":36604 + "flush_operations":51, + "wr_total_times_ns":313253456 + "rd_total_times_ns":3465673657 + "flush_total_times_ns":49653 } }, { @@ -1240,6 +1252,10 @@ Example: "wr_operations":0, "rd_bytes":0, "rd_operations":0 + "flush_operations":0, + "wr_total_times_ns":0 + "rd_total_times_ns":0 + "flush_total_times_ns":0 } }, { @@ -1250,6 +1266,10 @@ Example: "wr_operations":0, "rd_bytes":0, "rd_operations":0 + "flush_operations":0, + "wr_total_times_ns":0 + "rd_total_times_ns":0 + "flush_total_times_ns":0 } }, { @@ -1260,6 +1280,10 @@ Example: "wr_operations":0, "rd_bytes":0, "rd_operations":0 + "flush_operations":0, + "wr_total_times_ns":0 + "rd_total_times_ns":0 + "flush_total_times_ns":0 } } ] @@ -31,7 +31,7 @@ endif %.o: %.m $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") -LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(1) $(LIBS)," LINK $(TARGET_DIR)$@") +LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(sort $(1)) $(LIBS)," LINK $(TARGET_DIR)$@") %$(EXESUF): %.o $(call LINK,$^) diff --git a/rwhandler.c b/rwhandler.c new file mode 100644 index 0000000000..bb2238ff1e --- /dev/null +++ b/rwhandler.c @@ -0,0 +1,87 @@ +#include "rwhandler.h" +#include "ioport.h" +#include "cpu-all.h" + +#define RWHANDLER_WRITE(name, len, type) \ +static void name(void *opaque, type addr, uint32_t value) \ +{\ + struct ReadWriteHandler *handler = opaque;\ + handler->write(handler, addr, value, len);\ +} + +#define RWHANDLER_READ(name, len, type) \ +static uint32_t name(void *opaque, type addr) \ +{ \ + struct ReadWriteHandler *handler = opaque; \ + return handler->read(handler, addr, len); \ +} + +RWHANDLER_WRITE(cpu_io_memory_simple_writeb, 1, target_phys_addr_t); +RWHANDLER_READ(cpu_io_memory_simple_readb, 1, target_phys_addr_t); +RWHANDLER_WRITE(cpu_io_memory_simple_writew, 2, target_phys_addr_t); +RWHANDLER_READ(cpu_io_memory_simple_readw, 2, target_phys_addr_t); +RWHANDLER_WRITE(cpu_io_memory_simple_writel, 4, target_phys_addr_t); +RWHANDLER_READ(cpu_io_memory_simple_readl, 4, target_phys_addr_t); + +static CPUWriteMemoryFunc * const cpu_io_memory_simple_write[] = { + &cpu_io_memory_simple_writeb, + &cpu_io_memory_simple_writew, + &cpu_io_memory_simple_writel, +}; + +static CPUReadMemoryFunc * const cpu_io_memory_simple_read[] = { + &cpu_io_memory_simple_readb, + &cpu_io_memory_simple_readw, + &cpu_io_memory_simple_readl, +}; + +int cpu_register_io_memory_simple(struct ReadWriteHandler *handler, int endian) +{ + if (!handler->read || !handler->write) { + return -1; + } + return cpu_register_io_memory(cpu_io_memory_simple_read, + cpu_io_memory_simple_write, + handler, endian); +} + +RWHANDLER_WRITE(ioport_simple_writeb, 1, uint32_t); +RWHANDLER_READ(ioport_simple_readb, 1, uint32_t); +RWHANDLER_WRITE(ioport_simple_writew, 2, uint32_t); +RWHANDLER_READ(ioport_simple_readw, 2, uint32_t); +RWHANDLER_WRITE(ioport_simple_writel, 4, uint32_t); +RWHANDLER_READ(ioport_simple_readl, 4, uint32_t); + +int register_ioport_simple(ReadWriteHandler* handler, + pio_addr_t start, int length, int size) +{ + IOPortWriteFunc *write; + IOPortReadFunc *read; + int r; + switch (size) { + case 1: + write = ioport_simple_writeb; + read = ioport_simple_readb; + break; + case 2: + write = ioport_simple_writew; + read = ioport_simple_readw; + break; + default: + write = ioport_simple_writel; + read = ioport_simple_readl; + } + if (handler->write) { + r = register_ioport_write(start, length, size, write, handler); + if (r < 0) { + return r; + } + } + if (handler->read) { + r = register_ioport_read(start, length, size, read, handler); + if (r < 0) { + return r; + } + } + return 0; +} diff --git a/rwhandler.h b/rwhandler.h new file mode 100644 index 0000000000..b2a5790548 --- /dev/null +++ b/rwhandler.h @@ -0,0 +1,27 @@ +#ifndef READ_WRITE_HANDLER_H +#define READ_WRITE_HANDLER_H + +#include "qemu-common.h" +#include "ioport.h" + +typedef struct ReadWriteHandler ReadWriteHandler; + +/* len is guaranteed to be one of 1, 2 or 4, addr is guaranteed to fit in an + * appropriate type (io/memory/etc). They do not need to be range checked. */ +typedef void WriteHandlerFunc(ReadWriteHandler *, pcibus_t addr, + uint32_t value, int len); +typedef uint32_t ReadHandlerFunc(ReadWriteHandler *, pcibus_t addr, int len); + +struct ReadWriteHandler { + WriteHandlerFunc *write; + ReadHandlerFunc *read; +}; + +/* Helpers for when we want to use a single routine with length. */ +/* CPU memory handler: both read and write must be present. */ +int cpu_register_io_memory_simple(ReadWriteHandler *, int endian); +/* io port handler: can supply only read or write handlers. */ +int register_ioport_simple(ReadWriteHandler *, + pio_addr_t start, int length, int size); + +#endif diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 3498425fff..0eba357cc2 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2532,7 +2532,7 @@ sub process { $allowed = 1; } } - if (!$seen) { + if ($seen != ($#chunks + 1)) { WARN("braces {} are necessary for all arms of this statement\n" . $herectx); } } diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 2ad56998ee..f55e5e63f9 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -102,10 +102,10 @@ def process(events, log, analyzer): fn_argcount = len(inspect.getargspec(fn)[0]) - 1 if fn_argcount == event_argcount + 1: # Include timestamp as first argument - return lambda _, rec: fn(*rec[1:2 + fn_argcount]) + return lambda _, rec: fn(*rec[1:2 + event_argcount]) else: # Just arguments, no timestamp - return lambda _, rec: fn(*rec[2:2 + fn_argcount]) + return lambda _, rec: fn(*rec[2:2 + event_argcount]) analyzer.begin() fn_cache = {} diff --git a/scripts/tracetool b/scripts/tracetool index 2155a57df2..743d246289 100755 --- a/scripts/tracetool +++ b/scripts/tracetool @@ -43,7 +43,26 @@ EOF # Get the name of a trace event get_name() { - echo ${1%%\(*} + local name + name=${1%%\(*} + echo "${name##* }" +} + +# Get the given property of a trace event +# 1: trace-events line +# 2: property name +# -> return 0 if property is present, or 1 otherwise +has_property() +{ + local props prop + props=${1%%\(*} + props=${props% *} + for prop in $props; do + if [ "$prop" = "$2" ]; then + return 0 + fi + done + return 1 } # Get the argument list of a trace event, including types and names @@ -101,20 +120,6 @@ get_fmt() echo "$fmt" } -# Get the state of a trace event -get_state() -{ - local str disable state - str=$(get_name "$1") - disable=${str##disable } - if [ "$disable" = "$str" ] ; then - state=1 - else - state=0 - fi - echo "$state" -} - linetoh_begin_nop() { return @@ -158,7 +163,7 @@ linetoc_end_nop() linetoh_begin_simple() { cat <<EOF -#include "simpletrace.h" +#include "trace/simple.h" EOF simple_event_num=0 @@ -174,14 +179,10 @@ cast_args_to_uint64_t() linetoh_simple() { - local name args argc trace_args state + local name args argc trace_args name=$(get_name "$1") args=$(get_args "$1") argc=$(get_argc "$1") - state=$(get_state "$1") - if [ "$state" = "0" ]; then - name=${name##disable } - fi trace_args="$simple_event_num" if [ "$argc" -gt 0 ] @@ -220,14 +221,10 @@ EOF linetoc_simple() { - local name state + local name name=$(get_name "$1") - state=$(get_state "$1") - if [ "$state" = "0" ] ; then - name=${name##disable } - fi cat <<EOF -{.tp_name = "$name", .state=$state}, +{.tp_name = "$name", .state=0}, EOF simple_event_num=$((simple_event_num + 1)) } @@ -244,7 +241,12 @@ linetoh_begin_stderr() { cat <<EOF #include <stdio.h> +#include "trace/stderr.h" + +extern TraceEvent trace_list[]; EOF + + stderr_event_num=0 } linetoh_stderr() @@ -263,29 +265,47 @@ linetoh_stderr() cat <<EOF static inline void trace_$name($args) { - fprintf(stderr, "$name $fmt\n" $argnames); + if (trace_list[$stderr_event_num].state != 0) { + fprintf(stderr, "$name $fmt\n" $argnames); + } } EOF + stderr_event_num=$((stderr_event_num + 1)) + } linetoh_end_stderr() { -return + cat <<EOF +#define NR_TRACE_EVENTS $stderr_event_num +EOF } linetoc_begin_stderr() { -return + cat <<EOF +#include "trace.h" + +TraceEvent trace_list[] = { +EOF + stderr_event_num=0 } linetoc_stderr() { -return + local name + name=$(get_name "$1") + cat <<EOF +{.tp_name = "$name", .state=0}, +EOF + stderr_event_num=$(($stderr_event_num + 1)) } linetoc_end_stderr() { -return + cat <<EOF +}; +EOF } #END OF STDERR @@ -379,14 +399,10 @@ EOF linetoh_dtrace() { - local name args argnames state nameupper + local name args argnames nameupper name=$(get_name "$1") args=$(get_args "$1") argnames=$(get_argnames "$1", ",") - state=$(get_state "$1") - if [ "$state" = "0" ] ; then - name=${name##disable } - fi nameupper=`echo $name | tr '[:lower:]' '[:upper:]'` @@ -430,13 +446,9 @@ EOF linetod_dtrace() { - local name args state + local name args name=$(get_name "$1") args=$(get_args "$1") - state=$(get_state "$1") - if [ "$state" = "0" ] ; then - name=${name##disable } - fi # DTrace provider syntax expects foo() for empty # params, not foo(void) @@ -464,14 +476,10 @@ linetostap_begin_dtrace() linetostap_dtrace() { - local i arg name args arglist state + local i arg name args arglist name=$(get_name "$1") args=$(get_args "$1") arglist=$(get_argnames "$1", "") - state=$(get_state "$1") - if [ "$state" = "0" ] ; then - name=${name##disable } - fi # Define prototype for probe arguments cat <<EOF @@ -516,18 +524,10 @@ convert() # Skip comments and empty lines test -z "${str%%#*}" && continue - # Process the line. The nop backend handles disabled lines. - disable=${str%%disable *} echo - if test -z "$disable"; then - # Pass the disabled state as an arg for the simple - # or DTrace backends which handle it dynamically. - # For all other backends, call lineto$1_nop() - if [ $backend = "simple" -o "$backend" = "dtrace" ]; then - "$process_line" "$str" - else - "lineto$1_nop" "${str##disable }" - fi + # Process the line. The nop backend handles disabled lines. + if has_property "$str" "disable"; then + "lineto$1_nop" "$str" else "$process_line" "$str" fi diff --git a/slirp/ip.h b/slirp/ip.h index 72dbe9a5d9..88c903fccd 100644 --- a/slirp/ip.h +++ b/slirp/ip.h @@ -91,7 +91,7 @@ struct ip { uint8_t ip_p; /* protocol */ uint16_t ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ -} __attribute__((packed)); +} QEMU_PACKED; #define IP_MAXPACKET 65535 /* maximum packet size */ @@ -153,7 +153,7 @@ struct ip_timestamp { n_long ipt_time; } ipt_ta[1]; } ipt_timestamp; -} __attribute__((packed)); +} QEMU_PACKED; /* flag bits for ipt_flg */ #define IPOPT_TS_TSONLY 0 /* timestamps only */ @@ -183,11 +183,11 @@ struct ip_timestamp { struct mbuf_ptr { struct mbuf *mptr; uint32_t dummy; -} __attribute__((packed)); +} QEMU_PACKED; #else struct mbuf_ptr { struct mbuf *mptr; -} __attribute__((packed)); +} QEMU_PACKED; #endif struct qlink { void *next, *prev; @@ -203,7 +203,7 @@ struct ipovly { uint16_t ih_len; /* protocol length */ struct in_addr ih_src; /* source internet address */ struct in_addr ih_dst; /* destination internet address */ -} __attribute__((packed)); +} QEMU_PACKED; /* * Ip reassembly queue structure. Each fragment @@ -219,7 +219,7 @@ struct ipq { uint8_t ipq_p; /* protocol of this fragment */ uint16_t ipq_id; /* sequence id for reassembly */ struct in_addr ipq_src,ipq_dst; -} __attribute__((packed)); +} QEMU_PACKED; /* * Ip header, when holding a fragment. @@ -229,7 +229,7 @@ struct ipq { struct ipasfrag { struct qlink ipf_link; struct ip ipf_ip; -} __attribute__((packed)); +} QEMU_PACKED; #define ipf_off ipf_ip.ip_off #define ipf_tos ipf_ip.ip_tos @@ -248,6 +248,6 @@ struct ipasfrag { struct ipoption { struct in_addr ipopt_dst; /* first-hop dst if source routed */ int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ -} __attribute__((packed)); +} QEMU_PACKED; #endif diff --git a/slirp/slirp.h b/slirp/slirp.h index dcf99d5ca4..28a5c037e6 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -199,7 +199,7 @@ struct arphdr { uint32_t ar_sip; /* sender IP address */ unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ uint32_t ar_tip; /* target IP address */ -} __attribute__((packed)); +} QEMU_PACKED; #define ARP_TABLE_SIZE 16 @@ -67,23 +67,23 @@ SECTIONS .tbss : { *(.tbss) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 1d9b20c706..70ef74b80a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -348,7 +348,7 @@ int kvm_arch_init_vcpu(CPUState *env) struct { struct kvm_cpuid2 cpuid; struct kvm_cpuid_entry2 entries[100]; - } __attribute__((packed)) cpuid_data; + } QEMU_PACKED cpuid_data; KVMState *s = env->kvm_state; uint32_t limit, i, j, cpuid_i; uint32_t unused; diff --git a/target-i386/svm.h b/target-i386/svm.h index a224aead17..04193ed60f 100644 --- a/target-i386/svm.h +++ b/target-i386/svm.h @@ -130,7 +130,7 @@ #define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */ -struct __attribute__ ((__packed__)) vmcb_control_area { +struct QEMU_PACKED vmcb_control_area { uint16_t intercept_cr_read; uint16_t intercept_cr_write; uint16_t intercept_dr_read; @@ -162,14 +162,14 @@ struct __attribute__ ((__packed__)) vmcb_control_area { uint8_t reserved_5[832]; }; -struct __attribute__ ((__packed__)) vmcb_seg { +struct QEMU_PACKED vmcb_seg { uint16_t selector; uint16_t attrib; uint32_t limit; uint64_t base; }; -struct __attribute__ ((__packed__)) vmcb_save_area { +struct QEMU_PACKED vmcb_save_area { struct vmcb_seg es; struct vmcb_seg cs; struct vmcb_seg ss; @@ -214,7 +214,7 @@ struct __attribute__ ((__packed__)) vmcb_save_area { uint64_t last_excp_to; }; -struct __attribute__ ((__packed__)) vmcb { +struct QEMU_PACKED vmcb { struct vmcb_control_area control; struct vmcb_save_area save; }; diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index a81da629de..35302863cb 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -65,6 +65,7 @@ struct CPUMBState; #define MSR_DCE (1<<7) /* 0x080 */ #define MSR_EE (1<<8) /* 0x100 */ #define MSR_EIP (1<<9) /* 0x200 */ +#define MSR_PVR (1<<10) /* 0x400 */ #define MSR_CC (1<<31) /* Machine State Register (MSR) Fields */ diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 1a862d31e3..366fd3e607 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -424,10 +424,15 @@ static inline void msr_read(DisasContext *dc, TCGv d) static inline void msr_write(DisasContext *dc, TCGv v) { + TCGv t; + + t = tcg_temp_new(); dc->cpustate_changed = 1; - tcg_gen_mov_tl(cpu_SR[SR_MSR], v); - /* PVR, we have a processor version register. */ - tcg_gen_ori_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], (1 << 10)); + /* PVR bit is not writable. */ + tcg_gen_andi_tl(t, v, ~MSR_PVR); + tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR); + tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], v); + tcg_temp_free(t); } static void dec_msr(DisasContext *dc) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index c5f70fa759..79e25583ff 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -537,6 +537,10 @@ static inline int cpu_mips_hw_interrupts_pending(CPUState *env) if (!(env->CP0_Status & (1 << CP0St_IE)) || (env->CP0_Status & (1 << CP0St_EXL)) || (env->CP0_Status & (1 << CP0St_ERL)) || + /* Note that the TCStatus IXMT field is initialized to zero, + and only MT capable cores can set it to one. So we don't + need to check for MT capabilities here. */ + (env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)) || (env->hflags & MIPS_HFLAG_DM)) { /* Interrupts are disabled */ return 0; @@ -618,6 +622,14 @@ enum { /* Dummy exception for conditional stores. */ #define EXCP_SC 0x100 +/* + * This is an interrnally generated WAKE request line. + * It is driven by the CPU itself. Raised when the MT + * block wants to wake a VPE from an inactive state and + * cleared when VPE goes from active to inactive. + */ +#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0 + int cpu_mips_exec(CPUMIPSState *s); CPUMIPSState *cpu_mips_init(const char *cpu_model); //~ uint32_t cpu_mips_get_clock (void); @@ -658,6 +670,37 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls) env->tls_value = newtls; } +static inline int mips_vpe_active(CPUState *env) +{ + int active = 1; + + /* Check that the VPE is enabled. */ + if (!(env->mvp->CP0_MVPControl & (1 << CP0MVPCo_EVP))) { + active = 0; + } + /* Check that the VPE is actived. */ + if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))) { + active = 0; + } + + /* Now verify that there are active thread contexts in the VPE. + + This assumes the CPU model will internally reschedule threads + if the active one goes to sleep. If there are no threads available + the active one will be in a sleeping state, and we can turn off + the entire VPE. */ + if (!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_A))) { + /* TC is not activated. */ + active = 0; + } + if (env->active_tc.CP0_TCHalt & 1) { + /* TC is in halt state. */ + active = 0; + } + + return active; +} + static inline int cpu_has_work(CPUState *env) { int has_work = 0; @@ -670,6 +713,18 @@ static inline int cpu_has_work(CPUState *env) has_work = 1; } + /* MIPS-MT has the ability to halt the CPU. */ + if (env->CP0_Config3 & (1 << CP0C3_MT)) { + /* The QEMU model will issue an _WAKE request whenever the CPUs + should be woken up. */ + if (env->interrupt_request & CPU_INTERRUPT_WAKE) { + has_work = 1; + } + + if (!mips_vpe_active(env)) { + has_work = 0; + } + } return has_work; } diff --git a/target-mips/helper.c b/target-mips/helper.c index 024caa23c1..1c58e0cc21 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -482,18 +482,18 @@ void do_interrupt (CPUState *env) unsigned int vector; unsigned int pending = (env->CP0_Cause & CP0Ca_IP_mask) >> 8; + pending &= env->CP0_Status >> 8; /* Compute the Vector Spacing. */ spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & ((1 << 6) - 1); spacing <<= 5; if (env->CP0_Config3 & (1 << CP0C3_VInt)) { /* For VInt mode, the MIPS computes the vector internally. */ - for (vector = 0; vector < 8; vector++) { - if (pending & 1) { + for (vector = 7; vector > 0; vector--) { + if (pending & (1 << vector)) { /* Found it. */ break; } - pending >>= 1; } } else { /* For VEIC mode, the external interrupt controller feeds the diff --git a/target-mips/helper.h b/target-mips/helper.h index 297ab64bda..442f684697 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -52,6 +52,8 @@ DEF_HELPER_2(msachiu, tl, tl, tl) DEF_HELPER_0(mfc0_mvpcontrol, tl) DEF_HELPER_0(mfc0_mvpconf0, tl) DEF_HELPER_0(mfc0_mvpconf1, tl) +DEF_HELPER_0(mftc0_vpecontrol, tl) +DEF_HELPER_0(mftc0_vpeconf0, tl) DEF_HELPER_0(mfc0_random, tl) DEF_HELPER_0(mfc0_tcstatus, tl) DEF_HELPER_0(mftc0_tcstatus, tl) @@ -70,6 +72,10 @@ DEF_HELPER_0(mftc0_tcschefback, tl) DEF_HELPER_0(mfc0_count, tl) DEF_HELPER_0(mftc0_entryhi, tl) DEF_HELPER_0(mftc0_status, tl) +DEF_HELPER_0(mftc0_cause, tl) +DEF_HELPER_0(mftc0_epc, tl) +DEF_HELPER_0(mftc0_ebase, tl) +DEF_HELPER_1(mftc0_configx, tl, tl) DEF_HELPER_0(mfc0_lladdr, tl) DEF_HELPER_1(mfc0_watchlo, tl, i32) DEF_HELPER_1(mfc0_watchhi, tl, i32) @@ -88,7 +94,9 @@ DEF_HELPER_1(dmfc0_watchlo, tl, i32) DEF_HELPER_1(mtc0_index, void, tl) DEF_HELPER_1(mtc0_mvpcontrol, void, tl) DEF_HELPER_1(mtc0_vpecontrol, void, tl) +DEF_HELPER_1(mttc0_vpecontrol, void, tl) DEF_HELPER_1(mtc0_vpeconf0, void, tl) +DEF_HELPER_1(mttc0_vpeconf0, void, tl) DEF_HELPER_1(mtc0_vpeconf1, void, tl) DEF_HELPER_1(mtc0_yqmask, void, tl) DEF_HELPER_1(mtc0_vpeopt, void, tl) @@ -127,7 +135,9 @@ DEF_HELPER_1(mttc0_status, void, tl) DEF_HELPER_1(mtc0_intctl, void, tl) DEF_HELPER_1(mtc0_srsctl, void, tl) DEF_HELPER_1(mtc0_cause, void, tl) +DEF_HELPER_1(mttc0_cause, void, tl) DEF_HELPER_1(mtc0_ebase, void, tl) +DEF_HELPER_1(mttc0_ebase, void, tl) DEF_HELPER_1(mtc0_config0, void, tl) DEF_HELPER_1(mtc0_config2, void, tl) DEF_HELPER_1(mtc0_lladdr, void, tl) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 056011f1cc..96e40c6018 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -749,6 +749,163 @@ void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) #endif #ifndef CONFIG_USER_ONLY +/* SMP helpers. */ +static int mips_vpe_is_wfi(CPUState *c) +{ + /* If the VPE is halted but otherwise active, it means it's waiting for + an interrupt. */ + return c->halted && mips_vpe_active(c); +} + +static inline void mips_vpe_wake(CPUState *c) +{ + /* Dont set ->halted = 0 directly, let it be done via cpu_has_work + because there might be other conditions that state that c should + be sleeping. */ + cpu_interrupt(c, CPU_INTERRUPT_WAKE); +} + +static inline void mips_vpe_sleep(CPUState *c) +{ + /* The VPE was shut off, really go to bed. + Reset any old _WAKE requests. */ + c->halted = 1; + cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE); +} + +static inline void mips_tc_wake(CPUState *c, int tc) +{ + /* FIXME: TC reschedule. */ + if (mips_vpe_active(c) && !mips_vpe_is_wfi(c)) { + mips_vpe_wake(c); + } +} + +static inline void mips_tc_sleep(CPUState *c, int tc) +{ + /* FIXME: TC reschedule. */ + if (!mips_vpe_active(c)) { + mips_vpe_sleep(c); + } +} + +/* tc should point to an int with the value of the global TC index. + This function will transform it into a local index within the + returned CPUState. + + FIXME: This code assumes that all VPEs have the same number of TCs, + which depends on runtime setup. Can probably be fixed by + walking the list of CPUStates. */ +static CPUState *mips_cpu_map_tc(int *tc) +{ + CPUState *other; + int vpe_idx, nr_threads = env->nr_threads; + int tc_idx = *tc; + + if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) { + /* Not allowed to address other CPUs. */ + *tc = env->current_tc; + return env; + } + + vpe_idx = tc_idx / nr_threads; + *tc = tc_idx % nr_threads; + other = qemu_get_cpu(vpe_idx); + return other ? other : env; +} + +/* The per VPE CP0_Status register shares some fields with the per TC + CP0_TCStatus registers. These fields are wired to the same registers, + so changes to either of them should be reflected on both registers. + + Also, EntryHi shares the bottom 8 bit ASID with TCStauts. + + These helper call synchronizes the regs for a given cpu. */ + +/* Called for updates to CP0_Status. */ +static void sync_c0_status(CPUState *cpu, int tc) +{ + int32_t tcstatus, *tcst; + uint32_t v = cpu->CP0_Status; + uint32_t cu, mx, asid, ksu; + uint32_t mask = ((1 << CP0TCSt_TCU3) + | (1 << CP0TCSt_TCU2) + | (1 << CP0TCSt_TCU1) + | (1 << CP0TCSt_TCU0) + | (1 << CP0TCSt_TMX) + | (3 << CP0TCSt_TKSU) + | (0xff << CP0TCSt_TASID)); + + cu = (v >> CP0St_CU0) & 0xf; + mx = (v >> CP0St_MX) & 0x1; + ksu = (v >> CP0St_KSU) & 0x3; + asid = env->CP0_EntryHi & 0xff; + + tcstatus = cu << CP0TCSt_TCU0; + tcstatus |= mx << CP0TCSt_TMX; + tcstatus |= ksu << CP0TCSt_TKSU; + tcstatus |= asid; + + if (tc == cpu->current_tc) { + tcst = &cpu->active_tc.CP0_TCStatus; + } else { + tcst = &cpu->tcs[tc].CP0_TCStatus; + } + + *tcst &= ~mask; + *tcst |= tcstatus; + compute_hflags(cpu); +} + +/* Called for updates to CP0_TCStatus. */ +static void sync_c0_tcstatus(CPUState *cpu, int tc, target_ulong v) +{ + uint32_t status; + uint32_t tcu, tmx, tasid, tksu; + uint32_t mask = ((1 << CP0St_CU3) + | (1 << CP0St_CU2) + | (1 << CP0St_CU1) + | (1 << CP0St_CU0) + | (1 << CP0St_MX) + | (3 << CP0St_KSU)); + + tcu = (v >> CP0TCSt_TCU0) & 0xf; + tmx = (v >> CP0TCSt_TMX) & 0x1; + tasid = v & 0xff; + tksu = (v >> CP0TCSt_TKSU) & 0x3; + + status = tcu << CP0St_CU0; + status |= tmx << CP0St_MX; + status |= tksu << CP0St_KSU; + + cpu->CP0_Status &= ~mask; + cpu->CP0_Status |= status; + + /* Sync the TASID with EntryHi. */ + cpu->CP0_EntryHi &= ~0xff; + cpu->CP0_EntryHi = tasid; + + compute_hflags(cpu); +} + +/* Called for updates to CP0_EntryHi. */ +static void sync_c0_entryhi(CPUState *cpu, int tc) +{ + int32_t *tcst; + uint32_t asid, v = cpu->CP0_EntryHi; + + asid = v & 0xff; + + if (tc == cpu->current_tc) { + tcst = &cpu->active_tc.CP0_TCStatus; + } else { + tcst = &cpu->tcs[tc].CP0_TCStatus; + } + + *tcst &= ~0xff; + *tcst |= asid; +} + /* CP0 helpers */ target_ulong helper_mfc0_mvpcontrol (void) { @@ -778,11 +935,12 @@ target_ulong helper_mfc0_tcstatus (void) target_ulong helper_mftc0_tcstatus(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.CP0_TCStatus; + if (other_tc == other->current_tc) + return other->active_tc.CP0_TCStatus; else - return env->tcs[other_tc].CP0_TCStatus; + return other->tcs[other_tc].CP0_TCStatus; } target_ulong helper_mfc0_tcbind (void) @@ -793,11 +951,12 @@ target_ulong helper_mfc0_tcbind (void) target_ulong helper_mftc0_tcbind(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.CP0_TCBind; + if (other_tc == other->current_tc) + return other->active_tc.CP0_TCBind; else - return env->tcs[other_tc].CP0_TCBind; + return other->tcs[other_tc].CP0_TCBind; } target_ulong helper_mfc0_tcrestart (void) @@ -808,11 +967,12 @@ target_ulong helper_mfc0_tcrestart (void) target_ulong helper_mftc0_tcrestart(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.PC; + if (other_tc == other->current_tc) + return other->active_tc.PC; else - return env->tcs[other_tc].PC; + return other->tcs[other_tc].PC; } target_ulong helper_mfc0_tchalt (void) @@ -823,11 +983,12 @@ target_ulong helper_mfc0_tchalt (void) target_ulong helper_mftc0_tchalt(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.CP0_TCHalt; + if (other_tc == other->current_tc) + return other->active_tc.CP0_TCHalt; else - return env->tcs[other_tc].CP0_TCHalt; + return other->tcs[other_tc].CP0_TCHalt; } target_ulong helper_mfc0_tccontext (void) @@ -838,11 +999,12 @@ target_ulong helper_mfc0_tccontext (void) target_ulong helper_mftc0_tccontext(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.CP0_TCContext; + if (other_tc == other->current_tc) + return other->active_tc.CP0_TCContext; else - return env->tcs[other_tc].CP0_TCContext; + return other->tcs[other_tc].CP0_TCContext; } target_ulong helper_mfc0_tcschedule (void) @@ -853,11 +1015,12 @@ target_ulong helper_mfc0_tcschedule (void) target_ulong helper_mftc0_tcschedule(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.CP0_TCSchedule; + if (other_tc == other->current_tc) + return other->active_tc.CP0_TCSchedule; else - return env->tcs[other_tc].CP0_TCSchedule; + return other->tcs[other_tc].CP0_TCSchedule; } target_ulong helper_mfc0_tcschefback (void) @@ -868,11 +1031,12 @@ target_ulong helper_mfc0_tcschefback (void) target_ulong helper_mftc0_tcschefback(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.CP0_TCScheFBack; + if (other_tc == other->current_tc) + return other->active_tc.CP0_TCScheFBack; else - return env->tcs[other_tc].CP0_TCScheFBack; + return other->tcs[other_tc].CP0_TCScheFBack; } target_ulong helper_mfc0_count (void) @@ -883,33 +1047,32 @@ target_ulong helper_mfc0_count (void) target_ulong helper_mftc0_entryhi(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - int32_t tcstatus; - - if (other_tc == env->current_tc) - tcstatus = env->active_tc.CP0_TCStatus; - else - tcstatus = env->tcs[other_tc].CP0_TCStatus; + CPUState *other = mips_cpu_map_tc(&other_tc); - return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff); + return other->CP0_EntryHi; } -target_ulong helper_mftc0_status(void) +target_ulong helper_mftc0_cause(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - target_ulong t0; - int32_t tcstatus; + int32_t tccause; + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - tcstatus = env->active_tc.CP0_TCStatus; - else - tcstatus = env->tcs[other_tc].CP0_TCStatus; + if (other_tc == other->current_tc) { + tccause = other->CP0_Cause; + } else { + tccause = other->CP0_Cause; + } - t0 = env->CP0_Status & ~0xf1000018; - t0 |= tcstatus & (0xf << CP0TCSt_TCU0); - t0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX); - t0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU); + return tccause; +} - return t0; +target_ulong helper_mftc0_status(void) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + + return other->CP0_Status; } target_ulong helper_mfc0_lladdr (void) @@ -940,14 +1103,15 @@ target_ulong helper_mftc0_debug(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tcstatus; + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - tcstatus = env->active_tc.CP0_Debug_tcstatus; + if (other_tc == other->current_tc) + tcstatus = other->active_tc.CP0_Debug_tcstatus; else - tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus; + tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus; /* XXX: Might be wrong, check with EJTAG spec. */ - return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | + return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } @@ -1034,6 +1198,38 @@ void helper_mtc0_vpecontrol (target_ulong arg1) env->CP0_VPEControl = newval; } +void helper_mttc0_vpecontrol(target_ulong arg1) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + uint32_t mask; + uint32_t newval; + + mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) | + (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC); + newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask); + + /* TODO: Enable/disable TCs. */ + + other->CP0_VPEControl = newval; +} + +target_ulong helper_mftc0_vpecontrol(void) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + /* FIXME: Mask away return zero on read bits. */ + return other->CP0_VPEControl; +} + +target_ulong helper_mftc0_vpeconf0(void) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + + return other->CP0_VPEConf0; +} + void helper_mtc0_vpeconf0 (target_ulong arg1) { uint32_t mask = 0; @@ -1051,6 +1247,20 @@ void helper_mtc0_vpeconf0 (target_ulong arg1) env->CP0_VPEConf0 = newval; } +void helper_mttc0_vpeconf0(target_ulong arg1) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + uint32_t mask = 0; + uint32_t newval; + + mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); + newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask); + + /* TODO: TC exclusive handling due to ERL/EXL. */ + other->CP0_VPEConf0 = newval; +} + void helper_mtc0_vpeconf1 (target_ulong arg1) { uint32_t mask = 0; @@ -1094,21 +1304,20 @@ void helper_mtc0_tcstatus (target_ulong arg1) newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask); - // TODO: Sync with CP0_Status. - env->active_tc.CP0_TCStatus = newval; + sync_c0_tcstatus(env, env->current_tc, newval); } void helper_mttc0_tcstatus (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - // TODO: Sync with CP0_Status. - - if (other_tc == env->current_tc) - env->active_tc.CP0_TCStatus = arg1; + if (other_tc == other->current_tc) + other->active_tc.CP0_TCStatus = arg1; else - env->tcs[other_tc].CP0_TCStatus = arg1; + other->tcs[other_tc].CP0_TCStatus = arg1; + sync_c0_tcstatus(other, other_tc, arg1); } void helper_mtc0_tcbind (target_ulong arg1) @@ -1127,15 +1336,16 @@ void helper_mttc0_tcbind (target_ulong arg1) int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); uint32_t mask = (1 << CP0TCBd_TBE); uint32_t newval; + CPUState *other = mips_cpu_map_tc(&other_tc); - if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) + if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) mask |= (1 << CP0TCBd_CurVPE); - if (other_tc == env->current_tc) { - newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask); - env->active_tc.CP0_TCBind = newval; + if (other_tc == other->current_tc) { + newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask); + other->active_tc.CP0_TCBind = newval; } else { - newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask); - env->tcs[other_tc].CP0_TCBind = newval; + newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask); + other->tcs[other_tc].CP0_TCBind = newval; } } @@ -1150,16 +1360,17 @@ void helper_mtc0_tcrestart (target_ulong arg1) void helper_mttc0_tcrestart (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) { - env->active_tc.PC = arg1; - env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); - env->lladdr = 0ULL; + if (other_tc == other->current_tc) { + other->active_tc.PC = arg1; + other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); + other->lladdr = 0ULL; /* MIPS16 not implemented. */ } else { - env->tcs[other_tc].PC = arg1; - env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS); - env->lladdr = 0ULL; + other->tcs[other_tc].PC = arg1; + other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS); + other->lladdr = 0ULL; /* MIPS16 not implemented. */ } } @@ -1169,18 +1380,30 @@ void helper_mtc0_tchalt (target_ulong arg1) env->active_tc.CP0_TCHalt = arg1 & 0x1; // TODO: Halt TC / Restart (if allocated+active) TC. + if (env->active_tc.CP0_TCHalt & 1) { + mips_tc_sleep(env, env->current_tc); + } else { + mips_tc_wake(env, env->current_tc); + } } void helper_mttc0_tchalt (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); // TODO: Halt TC / Restart (if allocated+active) TC. - if (other_tc == env->current_tc) - env->active_tc.CP0_TCHalt = arg1; + if (other_tc == other->current_tc) + other->active_tc.CP0_TCHalt = arg1; else - env->tcs[other_tc].CP0_TCHalt = arg1; + other->tcs[other_tc].CP0_TCHalt = arg1; + + if (arg1 & 1) { + mips_tc_sleep(other, other_tc); + } else { + mips_tc_wake(other, other_tc); + } } void helper_mtc0_tccontext (target_ulong arg1) @@ -1191,11 +1414,12 @@ void helper_mtc0_tccontext (target_ulong arg1) void helper_mttc0_tccontext (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - env->active_tc.CP0_TCContext = arg1; + if (other_tc == other->current_tc) + other->active_tc.CP0_TCContext = arg1; else - env->tcs[other_tc].CP0_TCContext = arg1; + other->tcs[other_tc].CP0_TCContext = arg1; } void helper_mtc0_tcschedule (target_ulong arg1) @@ -1206,11 +1430,12 @@ void helper_mtc0_tcschedule (target_ulong arg1) void helper_mttc0_tcschedule (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - env->active_tc.CP0_TCSchedule = arg1; + if (other_tc == other->current_tc) + other->active_tc.CP0_TCSchedule = arg1; else - env->tcs[other_tc].CP0_TCSchedule = arg1; + other->tcs[other_tc].CP0_TCSchedule = arg1; } void helper_mtc0_tcschefback (target_ulong arg1) @@ -1221,11 +1446,12 @@ void helper_mtc0_tcschefback (target_ulong arg1) void helper_mttc0_tcschefback (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - env->active_tc.CP0_TCScheFBack = arg1; + if (other_tc == other->current_tc) + other->active_tc.CP0_TCScheFBack = arg1; else - env->tcs[other_tc].CP0_TCScheFBack = arg1; + other->tcs[other_tc].CP0_TCScheFBack = arg1; } void helper_mtc0_entrylo1 (target_ulong arg1) @@ -1306,8 +1532,7 @@ void helper_mtc0_entryhi (target_ulong arg1) old = env->CP0_EntryHi; env->CP0_EntryHi = val; if (env->CP0_Config3 & (1 << CP0C3_MT)) { - uint32_t tcst = env->active_tc.CP0_TCStatus & ~0xff; - env->active_tc.CP0_TCStatus = tcst | (val & 0xff); + sync_c0_entryhi(env, env->current_tc); } /* If the ASID changes, flush qemu's TLB. */ if ((old & 0xFF) != (val & 0xFF)) @@ -1317,16 +1542,10 @@ void helper_mtc0_entryhi (target_ulong arg1) void helper_mttc0_entryhi(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - int32_t tcstatus; + CPUState *other = mips_cpu_map_tc(&other_tc); - env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (arg1 & ~0xff); - if (other_tc == env->current_tc) { - tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (arg1 & 0xff); - env->active_tc.CP0_TCStatus = tcstatus; - } else { - tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (arg1 & 0xff); - env->tcs[other_tc].CP0_TCStatus = tcstatus; - } + other->CP0_EntryHi = arg1; + sync_c0_entryhi(other, other_tc); } void helper_mtc0_compare (target_ulong arg1) @@ -1342,7 +1561,12 @@ void helper_mtc0_status (target_ulong arg1) val = arg1 & mask; old = env->CP0_Status; env->CP0_Status = (env->CP0_Status & ~mask) | val; - compute_hflags(env); + if (env->CP0_Config3 & (1 << CP0C3_MT)) { + sync_c0_status(env, env->current_tc); + } else { + compute_hflags(env); + } + if (qemu_loglevel_mask(CPU_LOG_EXEC)) { qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x", old, old & env->CP0_Cause & CP0Ca_IP_mask, @@ -1360,22 +1584,16 @@ void helper_mtc0_status (target_ulong arg1) void helper_mttc0_status(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus; - - env->CP0_Status = arg1 & ~0xf1000018; - tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (arg1 & (0xf << CP0St_CU0)); - tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((arg1 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX)); - tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((arg1 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU)); - if (other_tc == env->current_tc) - env->active_tc.CP0_TCStatus = tcstatus; - else - env->tcs[other_tc].CP0_TCStatus = tcstatus; + CPUState *other = mips_cpu_map_tc(&other_tc); + + other->CP0_Status = arg1 & ~0xf1000018; + sync_c0_status(other, other_tc); } void helper_mtc0_intctl (target_ulong arg1) { /* vectored interrupts not implemented, no performance counters. */ - env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (arg1 & 0x000002e0); + env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000003e0) | (arg1 & 0x000003e0); } void helper_mtc0_srsctl (target_ulong arg1) @@ -1384,38 +1602,95 @@ void helper_mtc0_srsctl (target_ulong arg1) env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask); } -void helper_mtc0_cause (target_ulong arg1) +static void mtc0_cause(CPUState *cpu, target_ulong arg1) { uint32_t mask = 0x00C00300; - uint32_t old = env->CP0_Cause; + uint32_t old = cpu->CP0_Cause; int i; - if (env->insn_flags & ISA_MIPS32R2) + if (cpu->insn_flags & ISA_MIPS32R2) { mask |= 1 << CP0Ca_DC; + } - env->CP0_Cause = (env->CP0_Cause & ~mask) | (arg1 & mask); + cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask); - if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) { - if (env->CP0_Cause & (1 << CP0Ca_DC)) - cpu_mips_stop_count(env); - else - cpu_mips_start_count(env); + if ((old ^ cpu->CP0_Cause) & (1 << CP0Ca_DC)) { + if (cpu->CP0_Cause & (1 << CP0Ca_DC)) { + cpu_mips_stop_count(cpu); + } else { + cpu_mips_start_count(cpu); + } } /* Set/reset software interrupts */ for (i = 0 ; i < 2 ; i++) { - if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) { - cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i))); + if ((old ^ cpu->CP0_Cause) & (1 << (CP0Ca_IP + i))) { + cpu_mips_soft_irq(cpu, i, cpu->CP0_Cause & (1 << (CP0Ca_IP + i))); } } } +void helper_mtc0_cause(target_ulong arg1) +{ + mtc0_cause(env, arg1); +} + +void helper_mttc0_cause(target_ulong arg1) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + + mtc0_cause(other, arg1); +} + +target_ulong helper_mftc0_epc(void) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + + return other->CP0_EPC; +} + +target_ulong helper_mftc0_ebase(void) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + + return other->CP0_EBase; +} + void helper_mtc0_ebase (target_ulong arg1) { /* vectored interrupts not implemented */ env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); } +void helper_mttc0_ebase(target_ulong arg1) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); +} + +target_ulong helper_mftc0_configx(target_ulong idx) +{ + int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); + + switch (idx) { + case 0: return other->CP0_Config0; + case 1: return other->CP0_Config1; + case 2: return other->CP0_Config2; + case 3: return other->CP0_Config3; + /* 4 and 5 are reserved. */ + case 6: return other->CP0_Config6; + case 7: return other->CP0_Config7; + default: + break; + } + return 0; +} + void helper_mtc0_config0 (target_ulong arg1) { env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007); @@ -1471,13 +1746,15 @@ void helper_mttc0_debug(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); + CPUState *other = mips_cpu_map_tc(&other_tc); /* XXX: Might be wrong, check with EJTAG spec. */ - if (other_tc == env->current_tc) - env->active_tc.CP0_Debug_tcstatus = val; + if (other_tc == other->current_tc) + other->active_tc.CP0_Debug_tcstatus = val; else - env->tcs[other_tc].CP0_Debug_tcstatus = val; - env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | + other->tcs[other_tc].CP0_Debug_tcstatus = val; + other->CP0_Debug = (other->CP0_Debug & + ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } @@ -1510,101 +1787,111 @@ void helper_mtc0_datahi (target_ulong arg1) target_ulong helper_mftgpr(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.gpr[sel]; + if (other_tc == other->current_tc) + return other->active_tc.gpr[sel]; else - return env->tcs[other_tc].gpr[sel]; + return other->tcs[other_tc].gpr[sel]; } target_ulong helper_mftlo(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.LO[sel]; + if (other_tc == other->current_tc) + return other->active_tc.LO[sel]; else - return env->tcs[other_tc].LO[sel]; + return other->tcs[other_tc].LO[sel]; } target_ulong helper_mfthi(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.HI[sel]; + if (other_tc == other->current_tc) + return other->active_tc.HI[sel]; else - return env->tcs[other_tc].HI[sel]; + return other->tcs[other_tc].HI[sel]; } target_ulong helper_mftacx(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.ACX[sel]; + if (other_tc == other->current_tc) + return other->active_tc.ACX[sel]; else - return env->tcs[other_tc].ACX[sel]; + return other->tcs[other_tc].ACX[sel]; } target_ulong helper_mftdsp(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - return env->active_tc.DSPControl; + if (other_tc == other->current_tc) + return other->active_tc.DSPControl; else - return env->tcs[other_tc].DSPControl; + return other->tcs[other_tc].DSPControl; } void helper_mttgpr(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - env->active_tc.gpr[sel] = arg1; + if (other_tc == other->current_tc) + other->active_tc.gpr[sel] = arg1; else - env->tcs[other_tc].gpr[sel] = arg1; + other->tcs[other_tc].gpr[sel] = arg1; } void helper_mttlo(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - env->active_tc.LO[sel] = arg1; + if (other_tc == other->current_tc) + other->active_tc.LO[sel] = arg1; else - env->tcs[other_tc].LO[sel] = arg1; + other->tcs[other_tc].LO[sel] = arg1; } void helper_mtthi(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - env->active_tc.HI[sel] = arg1; + if (other_tc == other->current_tc) + other->active_tc.HI[sel] = arg1; else - env->tcs[other_tc].HI[sel] = arg1; + other->tcs[other_tc].HI[sel] = arg1; } void helper_mttacx(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - env->active_tc.ACX[sel] = arg1; + if (other_tc == other->current_tc) + other->active_tc.ACX[sel] = arg1; else - env->tcs[other_tc].ACX[sel] = arg1; + other->tcs[other_tc].ACX[sel] = arg1; } void helper_mttdsp(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + CPUState *other = mips_cpu_map_tc(&other_tc); - if (other_tc == env->current_tc) - env->active_tc.DSPControl = arg1; + if (other_tc == other->current_tc) + other->active_tc.DSPControl = arg1; else - env->tcs[other_tc].DSPControl = arg1; + other->tcs[other_tc].DSPControl = arg1; } /* MIPS MT functions */ @@ -1622,14 +1909,36 @@ target_ulong helper_emt(void) target_ulong helper_dvpe(void) { - // TODO - return 0; + CPUState *other_cpu = first_cpu; + target_ulong prev = env->mvp->CP0_MVPControl; + + do { + /* Turn off all VPEs except the one executing the dvpe. */ + if (other_cpu != env) { + other_cpu->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); + mips_vpe_sleep(other_cpu); + } + other_cpu = other_cpu->next_cpu; + } while (other_cpu); + return prev; } target_ulong helper_evpe(void) { - // TODO - return 0; + CPUState *other_cpu = first_cpu; + target_ulong prev = env->mvp->CP0_MVPControl; + + do { + if (other_cpu != env + /* If the VPE is WFI, dont distrub it's sleep. */ + && !mips_vpe_is_wfi(other_cpu)) { + /* Enable the VPE. */ + other_cpu->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); + mips_vpe_wake(other_cpu); /* And wake it up. */ + } + other_cpu = other_cpu->next_cpu; + } while (other_cpu); + return prev; } #endif /* !CONFIG_USER_ONLY */ @@ -1977,6 +2286,7 @@ void helper_pmon (int function) void helper_wait (void) { env->halted = 1; + cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE); helper_raise_exception(EXCP_HLT); } diff --git a/target-mips/translate.c b/target-mips/translate.c index 6c4e0d7675..d5b1c765fb 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -5537,6 +5537,19 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, tcg_gen_movi_tl(t0, -1); else if (u == 0) { switch (rt) { + case 1: + switch (sel) { + case 1: + gen_helper_mftc0_vpecontrol(t0); + break; + case 2: + gen_helper_mftc0_vpeconf0(t0); + break; + default: + goto die; + break; + } + break; case 2: switch (sel) { case 1: @@ -5583,6 +5596,46 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, gen_mfc0(env, ctx, t0, rt, sel); break; } + case 13: + switch (sel) { + case 0: + gen_helper_mftc0_cause(t0); + break; + default: + goto die; + break; + } + break; + case 14: + switch (sel) { + case 0: + gen_helper_mftc0_epc(t0); + break; + default: + goto die; + break; + } + break; + case 15: + switch (sel) { + case 1: + gen_helper_mftc0_ebase(t0); + break; + default: + goto die; + break; + } + break; + case 16: + switch (sel) { + case 0 ... 7: + gen_helper_mftc0_configx(t0, tcg_const_tl(sel)); + break; + default: + goto die; + break; + } + break; case 23: switch (sel) { case 0: @@ -5702,6 +5755,19 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, /* NOP */ ; else if (u == 0) { switch (rd) { + case 1: + switch (sel) { + case 1: + gen_helper_mttc0_vpecontrol(t0); + break; + case 2: + gen_helper_mttc0_vpeconf0(t0); + break; + default: + goto die; + break; + } + break; case 2: switch (sel) { case 1: @@ -5748,6 +5814,26 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, gen_mtc0(env, ctx, t0, rd, sel); break; } + case 13: + switch (sel) { + case 0: + gen_helper_mttc0_cause(t0); + break; + default: + goto die; + break; + } + break; + case 15: + switch (sel) { + case 1: + gen_helper_mttc0_ebase(t0); + break; + default: + goto die; + break; + } + break; case 23: switch (sel) { case 0: @@ -12727,6 +12813,32 @@ void cpu_reset (CPUMIPSState *env) /* Count register increments in debug mode, EJTAG version 1 */ env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); env->hflags = MIPS_HFLAG_CP0; + + if (env->CP0_Config3 & (1 << CP0C3_MT)) { + int i; + + /* Only TC0 on VPE 0 starts as active. */ + for (i = 0; i < ARRAY_SIZE(env->tcs); i++) { + env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE; + env->tcs[i].CP0_TCHalt = 1; + } + env->active_tc.CP0_TCHalt = 1; + env->halted = 1; + + if (!env->cpu_index) { + /* VPE0 starts up enabled. */ + env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); + env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); + + /* TC0 starts up unhalted. */ + env->halted = 0; + env->active_tc.CP0_TCHalt = 0; + env->tcs[0].CP0_TCHalt = 0; + /* With thread 0 active. */ + env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A); + env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A); + } + } #endif #if defined(TARGET_MIPS64) if (env->cpu_model->insn_flags & ISA_MIPS3) { diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 5bb421562a..c39138f3c5 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -274,7 +274,7 @@ static const mips_def_t mips_defs[] = (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, - .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 << CP0C3_MT), + .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT), .CP0_LLAddr_rw_bitmask = 0, .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, @@ -580,7 +580,7 @@ static void mvp_init (CPUMIPSState *env, const mips_def_t *def) // (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE) | // (0x04 << CP0MVPC0_PTC); (1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE) | - (0x04 << CP0MVPC0_PTC); + (0x00 << CP0MVPC0_PTC); #if !defined(CONFIG_USER_ONLY) /* Usermode has no TLB support */ env->mvp->CP0_MVPConf0 |= (env->tlb->nb_tlb << CP0MVPC0_PTLBE); diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index f8f0c82c6f..e192b50c73 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -698,7 +698,7 @@ typedef struct LowCore /* align to the top of the prefix area */ uint8_t pad18[0x2000-0x1400]; /* 0x1400 */ -} __attribute__((packed)) LowCore; +} QEMU_PACKED LowCore; /* STSI */ #define STSI_LEVEL_MASK 0x00000000f0000000ULL diff --git a/tcg/optimize.c b/tcg/optimize.c index 7e7f2b2020..9c65474a8c 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -87,13 +87,13 @@ static void reset_temp(TCGArg temp, int nb_temps, int nb_globals) } } -static int op_bits(enum TCGOpcode op) +static int op_bits(TCGOpcode op) { const TCGOpDef *def = &tcg_op_defs[op]; return def->flags & TCG_OPF_64BIT ? 64 : 32; } -static int op_to_movi(int op) +static TCGOpcode op_to_movi(TCGOpcode op) { switch (op_bits(op)) { case 32: @@ -143,7 +143,7 @@ static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val, gen_args[1] = val; } -static int op_to_mov(int op) +static TCGOpcode op_to_mov(TCGOpcode op) { switch (op_bits(op)) { case 32: @@ -157,7 +157,7 @@ static int op_to_mov(int op) } } -static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y) +static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) { switch (op) { CASE_OP_32_64(add): @@ -258,7 +258,7 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y) } } -static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y) +static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y) { TCGArg res = do_constant_folding_2(op, x, y); if (op_bits(op) == 32) { @@ -271,7 +271,8 @@ static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y) static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args, TCGOpDef *tcg_op_defs) { - int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args; + int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args; + TCGOpcode op; const TCGOpDef *def; TCGArg *gen_args; TCGArg tmp; @@ -377,6 +378,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, continue; } break; + default: + break; } /* Propagate constants through copy operations and do constant diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 4462647ef1..87cc1177f6 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -525,14 +525,14 @@ static void *qemu_st_helpers[4] = { static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, data_reg, data_reg2, r0, r1, rbase, mem_index, s_bits, bswap; + int addr_reg, data_reg, data_reg2, r0, r1, rbase, bswap; #ifdef CONFIG_SOFTMMU - int r2; + int mem_index, s_bits, r2; void *label1_ptr, *label2_ptr; -#endif #if TARGET_LONG_BITS == 64 int addr_reg2; #endif +#endif data_reg = *args++; if (opc == 3) @@ -540,13 +540,13 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) else data_reg2 = 0; addr_reg = *args++; + +#ifdef CONFIG_SOFTMMU #if TARGET_LONG_BITS == 64 addr_reg2 = *args++; #endif mem_index = *args; s_bits = opc & 3; - -#ifdef CONFIG_SOFTMMU r0 = 3; r1 = 4; r2 = 0; @@ -722,14 +722,14 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, r0, r1, data_reg, data_reg2, mem_index, bswap, rbase; + int addr_reg, r0, r1, data_reg, data_reg2, bswap, rbase; #ifdef CONFIG_SOFTMMU - int r2, ir; + int mem_index, r2, ir; void *label1_ptr, *label2_ptr; -#endif #if TARGET_LONG_BITS == 64 int addr_reg2; #endif +#endif data_reg = *args++; if (opc == 3) @@ -737,12 +737,12 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) else data_reg2 = 0; addr_reg = *args++; + +#ifdef CONFIG_SOFTMMU #if TARGET_LONG_BITS == 64 addr_reg2 = *args++; #endif mem_index = *args; - -#ifdef CONFIG_SOFTMMU r0 = 3; r1 = 4; r2 = 0; diff --git a/tests/test-i386.c b/tests/test-i386.c index 56ff1103fa..9cb5b51b76 100644 --- a/tests/test-i386.c +++ b/tests/test-i386.c @@ -773,7 +773,7 @@ void test_fops(double a, double b) void fpu_clear_exceptions(void) { - struct __attribute__((packed)) { + struct QEMU_PACKED { uint16_t fpuc; uint16_t dummy1; uint16_t fpus; @@ -924,7 +924,7 @@ void test_fbcd(double a) void test_fenv(void) { - struct __attribute__((packed)) { + struct QEMU_PACKED { uint16_t fpuc; uint16_t dummy1; uint16_t fpus; @@ -934,7 +934,7 @@ void test_fenv(void) uint32_t ignored[4]; long double fpregs[8]; } float_env32; - struct __attribute__((packed)) { + struct QEMU_PACKED { uint16_t fpuc; uint16_t fpus; uint16_t fptag; @@ -1279,7 +1279,7 @@ void test_segs(void) struct { uint32_t offset; uint16_t seg; - } __attribute__((packed)) segoff; + } QEMU_PACKED segoff; ldt.entry_number = 1; ldt.base_addr = (unsigned long)&seg_data1; @@ -1441,7 +1441,7 @@ void test_misc(void) /* XXX: see if Intel Core2 and AMD64 behavior really differ. Here we implemented the Intel way which is not compatible yet with QEMU. */ - static struct __attribute__((packed)) { + static struct QEMU_PACKED { uint64_t offset; uint16_t seg; } desc; diff --git a/tests/test_path.c b/tests/test_path.c index 234ed97088..7265a9445d 100644 --- a/tests/test_path.c +++ b/tests/test_path.c @@ -4,7 +4,7 @@ #include "../cutils.c" #include "../path.c" #include "../trace.c" -#ifdef CONFIG_SIMPLE_TRACE +#ifdef CONFIG_TRACE_SIMPLE #include "../simpletrace.c" #endif diff --git a/trace-events b/trace-events index dc300a29b1..08ffedfdd1 100644 --- a/trace-events +++ b/trace-events @@ -14,12 +14,9 @@ # # [disable] <name>(<type1> <arg1>[, <type2> <arg2>] ...) "<format-string>" # -# Example: qemu_malloc(size_t size) "size %zu" +# Example: g_malloc(size_t size) "size %zu" # # The "disable" keyword will build without the trace event. -# In case of 'simple' trace backend, it will allow the trace event to be -# compiled, but this would be turned off by default. It can be toggled on via -# the monitor. # # The <name> must be a valid as a C function name. # @@ -29,435 +26,439 @@ # The <format-string> should be a sprintf()-compatible format string. # qemu-malloc.c -disable qemu_malloc(size_t size, void *ptr) "size %zu ptr %p" -disable qemu_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p" -disable qemu_free(void *ptr) "ptr %p" +g_malloc(size_t size, void *ptr) "size %zu ptr %p" +g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p" +g_free(void *ptr) "ptr %p" # osdep.c -disable qemu_memalign(size_t alignment, size_t size, void *ptr) "alignment %zu size %zu ptr %p" -disable qemu_vmalloc(size_t size, void *ptr) "size %zu ptr %p" -disable qemu_vfree(void *ptr) "ptr %p" +qemu_memalign(size_t alignment, size_t size, void *ptr) "alignment %zu size %zu ptr %p" +qemu_vmalloc(size_t size, void *ptr) "size %zu ptr %p" +qemu_vfree(void *ptr) "ptr %p" # hw/virtio.c -disable virtqueue_fill(void *vq, const void *elem, unsigned int len, unsigned int idx) "vq %p elem %p len %u idx %u" -disable virtqueue_flush(void *vq, unsigned int count) "vq %p count %u" -disable virtqueue_pop(void *vq, void *elem, unsigned int in_num, unsigned int out_num) "vq %p elem %p in_num %u out_num %u" -disable virtio_queue_notify(void *vdev, int n, void *vq) "vdev %p n %d vq %p" -disable virtio_irq(void *vq) "vq %p" -disable virtio_notify(void *vdev, void *vq) "vdev %p vq %p" +virtqueue_fill(void *vq, const void *elem, unsigned int len, unsigned int idx) "vq %p elem %p len %u idx %u" +virtqueue_flush(void *vq, unsigned int count) "vq %p count %u" +virtqueue_pop(void *vq, void *elem, unsigned int in_num, unsigned int out_num) "vq %p elem %p in_num %u out_num %u" +virtio_queue_notify(void *vdev, int n, void *vq) "vdev %p n %d vq %p" +virtio_irq(void *vq) "vq %p" +virtio_notify(void *vdev, void *vq) "vdev %p vq %p" # hw/virtio-serial-bus.c -disable virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) "port %u, event %u, value %u" -disable virtio_serial_throttle_port(unsigned int port, bool throttle) "port %u, throttle %d" -disable virtio_serial_handle_control_message(uint16_t event, uint16_t value) "event %u, value %u" -disable virtio_serial_handle_control_message_port(unsigned int port) "port %u" +virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) "port %u, event %u, value %u" +virtio_serial_throttle_port(unsigned int port, bool throttle) "port %u, throttle %d" +virtio_serial_handle_control_message(uint16_t event, uint16_t value) "event %u, value %u" +virtio_serial_handle_control_message_port(unsigned int port) "port %u" # hw/virtio-console.c -disable virtio_console_flush_buf(unsigned int port, size_t len, ssize_t ret) "port %u, in_len %zu, out_len %zd" -disable virtio_console_chr_read(unsigned int port, int size) "port %u, size %d" -disable virtio_console_chr_event(unsigned int port, int event) "port %u, event %d" +virtio_console_flush_buf(unsigned int port, size_t len, ssize_t ret) "port %u, in_len %zu, out_len %zd" +virtio_console_chr_read(unsigned int port, int size) "port %u, size %d" +virtio_console_chr_event(unsigned int port, int event) "port %u, event %d" # block.c -disable multiwrite_cb(void *mcb, int ret) "mcb %p ret %d" -disable bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d" -disable bdrv_aio_multiwrite_earlyfail(void *mcb) "mcb %p" -disable bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d" -disable bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p" -disable bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" -disable bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" -disable bdrv_set_locked(void *bs, int locked) "bs %p locked %d" -disable bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" -disable bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" -disable bdrv_co_io(int is_write, void *acb) "is_write %d acb %p" +multiwrite_cb(void *mcb, int ret) "mcb %p ret %d" +bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d" +bdrv_aio_multiwrite_earlyfail(void *mcb) "mcb %p" +bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d" +bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p" +bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" +bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" +bdrv_set_locked(void *bs, int locked) "bs %p locked %d" +bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" +bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" +bdrv_co_io(int is_write, void *acb) "is_write %d acb %p" # hw/virtio-blk.c -disable virtio_blk_req_complete(void *req, int status) "req %p status %d" -disable virtio_blk_rw_complete(void *req, int ret) "req %p ret %d" -disable virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" +virtio_blk_req_complete(void *req, int status) "req %p status %d" +virtio_blk_rw_complete(void *req, int ret) "req %p ret %d" +virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" # posix-aio-compat.c -disable paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d" -disable paio_complete(void *acb, void *opaque, int ret) "acb %p opaque %p ret %d" -disable paio_cancel(void *acb, void *opaque) "acb %p opaque %p" +paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d" +paio_complete(void *acb, void *opaque, int ret) "acb %p opaque %p ret %d" +paio_cancel(void *acb, void *opaque) "acb %p opaque %p" # ioport.c -disable cpu_in(unsigned int addr, unsigned int val) "addr %#x value %u" -disable cpu_out(unsigned int addr, unsigned int val) "addr %#x value %u" +cpu_in(unsigned int addr, unsigned int val) "addr %#x value %u" +cpu_out(unsigned int addr, unsigned int val) "addr %#x value %u" # balloon.c # Since requests are raised via monitor, not many tracepoints are needed. -disable balloon_event(void *opaque, unsigned long addr) "opaque %p addr %lu" +balloon_event(void *opaque, unsigned long addr) "opaque %p addr %lu" # hw/apic.c -disable apic_local_deliver(int vector, uint32_t lvt) "vector %d delivery mode %d" -disable apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) "dest %d dest_mode %d delivery_mode %d vector %d trigger_mode %d" -disable cpu_set_apic_base(uint64_t val) "%016"PRIx64"" -disable cpu_get_apic_base(uint64_t val) "%016"PRIx64"" -disable apic_mem_readl(uint64_t addr, uint32_t val) "%"PRIx64" = %08x" -disable apic_mem_writel(uint64_t addr, uint32_t val) "%"PRIx64" = %08x" +apic_local_deliver(int vector, uint32_t lvt) "vector %d delivery mode %d" +apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) "dest %d dest_mode %d delivery_mode %d vector %d trigger_mode %d" +cpu_set_apic_base(uint64_t val) "%016"PRIx64"" +cpu_get_apic_base(uint64_t val) "%016"PRIx64"" +apic_mem_readl(uint64_t addr, uint32_t val) "%"PRIx64" = %08x" +apic_mem_writel(uint64_t addr, uint32_t val) "%"PRIx64" = %08x" # coalescing -disable apic_reset_irq_delivered(int apic_irq_delivered) "old coalescing %d" -disable apic_get_irq_delivered(int apic_irq_delivered) "returning coalescing %d" -disable apic_set_irq(int apic_irq_delivered) "coalescing %d" +apic_reset_irq_delivered(int apic_irq_delivered) "old coalescing %d" +apic_get_irq_delivered(int apic_irq_delivered) "returning coalescing %d" +apic_set_irq(int apic_irq_delivered) "coalescing %d" # hw/cs4231.c -disable cs4231_mem_readl_dreg(uint32_t reg, uint32_t ret) "read dreg %d: 0x%02x" -disable cs4231_mem_readl_reg(uint32_t reg, uint32_t ret) "read reg %d: 0x%08x" -disable cs4231_mem_writel_reg(uint32_t reg, uint32_t old, uint32_t val) "write reg %d: 0x%08x -> 0x%08x" -disable cs4231_mem_writel_dreg(uint32_t reg, uint32_t old, uint32_t val) "write dreg %d: 0x%02x -> 0x%02x" +cs4231_mem_readl_dreg(uint32_t reg, uint32_t ret) "read dreg %d: 0x%02x" +cs4231_mem_readl_reg(uint32_t reg, uint32_t ret) "read reg %d: 0x%08x" +cs4231_mem_writel_reg(uint32_t reg, uint32_t old, uint32_t val) "write reg %d: 0x%08x -> 0x%08x" +cs4231_mem_writel_dreg(uint32_t reg, uint32_t old, uint32_t val) "write dreg %d: 0x%02x -> 0x%02x" # hw/ds1225y.c -disable nvram_read(uint32_t addr, uint32_t ret) "read addr %d: 0x%02x" -disable nvram_write(uint32_t addr, uint32_t old, uint32_t val) "write addr %d: 0x%02x -> 0x%02x" +nvram_read(uint32_t addr, uint32_t ret) "read addr %d: 0x%02x" +nvram_write(uint32_t addr, uint32_t old, uint32_t val) "write addr %d: 0x%02x -> 0x%02x" # hw/eccmemctl.c -disable ecc_mem_writel_mer(uint32_t val) "Write memory enable %08x" -disable ecc_mem_writel_mdr(uint32_t val) "Write memory delay %08x" -disable ecc_mem_writel_mfsr(uint32_t val) "Write memory fault status %08x" -disable ecc_mem_writel_vcr(uint32_t val) "Write slot configuration %08x" -disable ecc_mem_writel_dr(uint32_t val) "Write diagnostic %08x" -disable ecc_mem_writel_ecr0(uint32_t val) "Write event count 1 %08x" -disable ecc_mem_writel_ecr1(uint32_t val) "Write event count 2 %08x" -disable ecc_mem_readl_mer(uint32_t ret) "Read memory enable %08x" -disable ecc_mem_readl_mdr(uint32_t ret) "Read memory delay %08x" -disable ecc_mem_readl_mfsr(uint32_t ret) "Read memory fault status %08x" -disable ecc_mem_readl_vcr(uint32_t ret) "Read slot configuration %08x" -disable ecc_mem_readl_mfar0(uint32_t ret) "Read memory fault address 0 %08x" -disable ecc_mem_readl_mfar1(uint32_t ret) "Read memory fault address 1 %08x" -disable ecc_mem_readl_dr(uint32_t ret) "Read diagnostic %08x" -disable ecc_mem_readl_ecr0(uint32_t ret) "Read event count 1 %08x" -disable ecc_mem_readl_ecr1(uint32_t ret) "Read event count 2 %08x" -disable ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = %02x" -disable ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x" +ecc_mem_writel_mer(uint32_t val) "Write memory enable %08x" +ecc_mem_writel_mdr(uint32_t val) "Write memory delay %08x" +ecc_mem_writel_mfsr(uint32_t val) "Write memory fault status %08x" +ecc_mem_writel_vcr(uint32_t val) "Write slot configuration %08x" +ecc_mem_writel_dr(uint32_t val) "Write diagnostic %08x" +ecc_mem_writel_ecr0(uint32_t val) "Write event count 1 %08x" +ecc_mem_writel_ecr1(uint32_t val) "Write event count 2 %08x" +ecc_mem_readl_mer(uint32_t ret) "Read memory enable %08x" +ecc_mem_readl_mdr(uint32_t ret) "Read memory delay %08x" +ecc_mem_readl_mfsr(uint32_t ret) "Read memory fault status %08x" +ecc_mem_readl_vcr(uint32_t ret) "Read slot configuration %08x" +ecc_mem_readl_mfar0(uint32_t ret) "Read memory fault address 0 %08x" +ecc_mem_readl_mfar1(uint32_t ret) "Read memory fault address 1 %08x" +ecc_mem_readl_dr(uint32_t ret) "Read diagnostic %08x" +ecc_mem_readl_ecr0(uint32_t ret) "Read event count 1 %08x" +ecc_mem_readl_ecr1(uint32_t ret) "Read event count 2 %08x" +ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = %02x" +ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x" # hw/lance.c -disable lance_mem_readw(uint64_t addr, uint32_t ret) "addr=%"PRIx64"val=0x%04x" -disable lance_mem_writew(uint64_t addr, uint32_t val) "addr=%"PRIx64"val=0x%04x" +lance_mem_readw(uint64_t addr, uint32_t ret) "addr=%"PRIx64"val=0x%04x" +lance_mem_writew(uint64_t addr, uint32_t val) "addr=%"PRIx64"val=0x%04x" # hw/slavio_intctl.c -disable slavio_intctl_mem_readl(uint32_t cpu, uint64_t addr, uint32_t ret) "read cpu %d reg 0x%"PRIx64" = %x" -disable slavio_intctl_mem_writel(uint32_t cpu, uint64_t addr, uint32_t val) "write cpu %d reg 0x%"PRIx64" = %x" -disable slavio_intctl_mem_writel_clear(uint32_t cpu, uint32_t val, uint32_t intreg_pending) "Cleared cpu %d irq mask %x, curmask %x" -disable slavio_intctl_mem_writel_set(uint32_t cpu, uint32_t val, uint32_t intreg_pending) "Set cpu %d irq mask %x, curmask %x" -disable slavio_intctlm_mem_readl(uint64_t addr, uint32_t ret) "read system reg 0x%"PRIx64" = %x" -disable slavio_intctlm_mem_writel(uint64_t addr, uint32_t val) "write system reg 0x%"PRIx64" = %x" -disable slavio_intctlm_mem_writel_enable(uint32_t val, uint32_t intregm_disabled) "Enabled master irq mask %x, curmask %x" -disable slavio_intctlm_mem_writel_disable(uint32_t val, uint32_t intregm_disabled) "Disabled master irq mask %x, curmask %x" -disable slavio_intctlm_mem_writel_target(uint32_t cpu) "Set master irq cpu %d" -disable slavio_check_interrupts(uint32_t pending, uint32_t intregm_disabled) "pending %x disabled %x" -disable slavio_set_irq(uint32_t target_cpu, int irq, uint32_t pil, int level) "Set cpu %d irq %d -> pil %d level %d" -disable slavio_set_timer_irq_cpu(int cpu, int level) "Set cpu %d local timer level %d" +slavio_intctl_mem_readl(uint32_t cpu, uint64_t addr, uint32_t ret) "read cpu %d reg 0x%"PRIx64" = %x" +slavio_intctl_mem_writel(uint32_t cpu, uint64_t addr, uint32_t val) "write cpu %d reg 0x%"PRIx64" = %x" +slavio_intctl_mem_writel_clear(uint32_t cpu, uint32_t val, uint32_t intreg_pending) "Cleared cpu %d irq mask %x, curmask %x" +slavio_intctl_mem_writel_set(uint32_t cpu, uint32_t val, uint32_t intreg_pending) "Set cpu %d irq mask %x, curmask %x" +slavio_intctlm_mem_readl(uint64_t addr, uint32_t ret) "read system reg 0x%"PRIx64" = %x" +slavio_intctlm_mem_writel(uint64_t addr, uint32_t val) "write system reg 0x%"PRIx64" = %x" +slavio_intctlm_mem_writel_enable(uint32_t val, uint32_t intregm_disabled) "Enabled master irq mask %x, curmask %x" +slavio_intctlm_mem_writel_disable(uint32_t val, uint32_t intregm_disabled) "Disabled master irq mask %x, curmask %x" +slavio_intctlm_mem_writel_target(uint32_t cpu) "Set master irq cpu %d" +slavio_check_interrupts(uint32_t pending, uint32_t intregm_disabled) "pending %x disabled %x" +slavio_set_irq(uint32_t target_cpu, int irq, uint32_t pil, int level) "Set cpu %d irq %d -> pil %d level %d" +slavio_set_timer_irq_cpu(int cpu, int level) "Set cpu %d local timer level %d" # hw/slavio_misc.c -disable slavio_misc_update_irq_raise(void) "Raise IRQ" -disable slavio_misc_update_irq_lower(void) "Lower IRQ" -disable slavio_set_power_fail(int power_failing, uint8_t config) "Power fail: %d, config: %d" -disable slavio_cfg_mem_writeb(uint32_t val) "Write config %02x" -disable slavio_cfg_mem_readb(uint32_t ret) "Read config %02x" -disable slavio_diag_mem_writeb(uint32_t val) "Write diag %02x" -disable slavio_diag_mem_readb(uint32_t ret) "Read diag %02x" -disable slavio_mdm_mem_writeb(uint32_t val) "Write modem control %02x" -disable slavio_mdm_mem_readb(uint32_t ret) "Read modem control %02x" -disable slavio_aux1_mem_writeb(uint32_t val) "Write aux1 %02x" -disable slavio_aux1_mem_readb(uint32_t ret) "Read aux1 %02x" -disable slavio_aux2_mem_writeb(uint32_t val) "Write aux2 %02x" -disable slavio_aux2_mem_readb(uint32_t ret) "Read aux2 %02x" -disable apc_mem_writeb(uint32_t val) "Write power management %02x" -disable apc_mem_readb(uint32_t ret) "Read power management %02x" -disable slavio_sysctrl_mem_writel(uint32_t val) "Write system control %08x" -disable slavio_sysctrl_mem_readl(uint32_t ret) "Read system control %08x" -disable slavio_led_mem_writew(uint32_t val) "Write diagnostic LED %04x" -disable slavio_led_mem_readw(uint32_t ret) "Read diagnostic LED %04x" +slavio_misc_update_irq_raise(void) "Raise IRQ" +slavio_misc_update_irq_lower(void) "Lower IRQ" +slavio_set_power_fail(int power_failing, uint8_t config) "Power fail: %d, config: %d" +slavio_cfg_mem_writeb(uint32_t val) "Write config %02x" +slavio_cfg_mem_readb(uint32_t ret) "Read config %02x" +slavio_diag_mem_writeb(uint32_t val) "Write diag %02x" +slavio_diag_mem_readb(uint32_t ret) "Read diag %02x" +slavio_mdm_mem_writeb(uint32_t val) "Write modem control %02x" +slavio_mdm_mem_readb(uint32_t ret) "Read modem control %02x" +slavio_aux1_mem_writeb(uint32_t val) "Write aux1 %02x" +slavio_aux1_mem_readb(uint32_t ret) "Read aux1 %02x" +slavio_aux2_mem_writeb(uint32_t val) "Write aux2 %02x" +slavio_aux2_mem_readb(uint32_t ret) "Read aux2 %02x" +apc_mem_writeb(uint32_t val) "Write power management %02x" +apc_mem_readb(uint32_t ret) "Read power management %02x" +slavio_sysctrl_mem_writel(uint32_t val) "Write system control %08x" +slavio_sysctrl_mem_readl(uint32_t ret) "Read system control %08x" +slavio_led_mem_writew(uint32_t val) "Write diagnostic LED %04x" +slavio_led_mem_readw(uint32_t ret) "Read diagnostic LED %04x" # hw/slavio_timer.c -disable slavio_timer_get_out(uint64_t limit, uint32_t counthigh, uint32_t count) "limit %"PRIx64" count %x%08x" -disable slavio_timer_irq(uint32_t counthigh, uint32_t count) "callback: count %x%08x" -disable slavio_timer_mem_readl_invalid(uint64_t addr) "invalid read address %"PRIx64"" -disable slavio_timer_mem_readl(uint64_t addr, uint32_t ret) "read %"PRIx64" = %08x" -disable slavio_timer_mem_writel(uint64_t addr, uint32_t val) "write %"PRIx64" = %08x" -disable slavio_timer_mem_writel_limit(unsigned int timer_index, uint64_t count) "processor %d user timer set to %016"PRIx64"" -disable slavio_timer_mem_writel_counter_invalid(void) "not user timer" -disable slavio_timer_mem_writel_status_start(unsigned int timer_index) "processor %d user timer started" -disable slavio_timer_mem_writel_status_stop(unsigned int timer_index) "processor %d user timer stopped" -disable slavio_timer_mem_writel_mode_user(unsigned int timer_index) "processor %d changed from counter to user timer" -disable slavio_timer_mem_writel_mode_counter(unsigned int timer_index) "processor %d changed from user timer to counter" -disable slavio_timer_mem_writel_mode_invalid(void) "not system timer" -disable slavio_timer_mem_writel_invalid(uint64_t addr) "invalid write address %"PRIx64"" +slavio_timer_get_out(uint64_t limit, uint32_t counthigh, uint32_t count) "limit %"PRIx64" count %x%08x" +slavio_timer_irq(uint32_t counthigh, uint32_t count) "callback: count %x%08x" +slavio_timer_mem_readl_invalid(uint64_t addr) "invalid read address %"PRIx64"" +slavio_timer_mem_readl(uint64_t addr, uint32_t ret) "read %"PRIx64" = %08x" +slavio_timer_mem_writel(uint64_t addr, uint32_t val) "write %"PRIx64" = %08x" +slavio_timer_mem_writel_limit(unsigned int timer_index, uint64_t count) "processor %d user timer set to %016"PRIx64"" +slavio_timer_mem_writel_counter_invalid(void) "not user timer" +slavio_timer_mem_writel_status_start(unsigned int timer_index) "processor %d user timer started" +slavio_timer_mem_writel_status_stop(unsigned int timer_index) "processor %d user timer stopped" +slavio_timer_mem_writel_mode_user(unsigned int timer_index) "processor %d changed from counter to user timer" +slavio_timer_mem_writel_mode_counter(unsigned int timer_index) "processor %d changed from user timer to counter" +slavio_timer_mem_writel_mode_invalid(void) "not system timer" +slavio_timer_mem_writel_invalid(uint64_t addr) "invalid write address %"PRIx64"" # hw/sparc32_dma.c -disable ledma_memory_read(uint64_t addr) "DMA read addr 0x%"PRIx64"" -disable ledma_memory_write(uint64_t addr) "DMA write addr 0x%"PRIx64"" -disable sparc32_dma_set_irq_raise(void) "Raise IRQ" -disable sparc32_dma_set_irq_lower(void) "Lower IRQ" -disable espdma_memory_read(uint32_t addr) "DMA read addr 0x%08x" -disable espdma_memory_write(uint32_t addr) "DMA write addr 0x%08x" -disable sparc32_dma_mem_readl(uint64_t addr, uint32_t ret) "read dmareg %"PRIx64": 0x%08x" -disable sparc32_dma_mem_writel(uint64_t addr, uint32_t old, uint32_t val) "write dmareg %"PRIx64": 0x%08x -> 0x%08x" -disable sparc32_dma_enable_raise(void) "Raise DMA enable" -disable sparc32_dma_enable_lower(void) "Lower DMA enable" +ledma_memory_read(uint64_t addr) "DMA read addr 0x%"PRIx64"" +ledma_memory_write(uint64_t addr) "DMA write addr 0x%"PRIx64"" +sparc32_dma_set_irq_raise(void) "Raise IRQ" +sparc32_dma_set_irq_lower(void) "Lower IRQ" +espdma_memory_read(uint32_t addr) "DMA read addr 0x%08x" +espdma_memory_write(uint32_t addr) "DMA write addr 0x%08x" +sparc32_dma_mem_readl(uint64_t addr, uint32_t ret) "read dmareg %"PRIx64": 0x%08x" +sparc32_dma_mem_writel(uint64_t addr, uint32_t old, uint32_t val) "write dmareg %"PRIx64": 0x%08x -> 0x%08x" +sparc32_dma_enable_raise(void) "Raise DMA enable" +sparc32_dma_enable_lower(void) "Lower DMA enable" # hw/sun4m.c -disable sun4m_cpu_interrupt(unsigned int level) "Set CPU IRQ %d" -disable sun4m_cpu_reset_interrupt(unsigned int level) "Reset CPU IRQ %d" -disable sun4m_cpu_set_irq_raise(int level) "Raise CPU IRQ %d" -disable sun4m_cpu_set_irq_lower(int level) "Lower CPU IRQ %d" +sun4m_cpu_interrupt(unsigned int level) "Set CPU IRQ %d" +sun4m_cpu_reset_interrupt(unsigned int level) "Reset CPU IRQ %d" +sun4m_cpu_set_irq_raise(int level) "Raise CPU IRQ %d" +sun4m_cpu_set_irq_lower(int level) "Lower CPU IRQ %d" # hw/sun4m_iommu.c -disable sun4m_iommu_mem_readl(uint64_t addr, uint32_t ret) "read reg[%"PRIx64"] = %x" -disable sun4m_iommu_mem_writel(uint64_t addr, uint32_t val) "write reg[%"PRIx64"] = %x" -disable sun4m_iommu_mem_writel_ctrl(uint64_t iostart) "iostart = %"PRIx64"" -disable sun4m_iommu_mem_writel_tlbflush(uint32_t val) "tlb flush %x" -disable sun4m_iommu_mem_writel_pgflush(uint32_t val) "page flush %x" -disable sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "get flags addr %"PRIx64" => pte %"PRIx64", *pte = %x" -disable sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x" -disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64"" +sun4m_iommu_mem_readl(uint64_t addr, uint32_t ret) "read reg[%"PRIx64"] = %x" +sun4m_iommu_mem_writel(uint64_t addr, uint32_t val) "write reg[%"PRIx64"] = %x" +sun4m_iommu_mem_writel_ctrl(uint64_t iostart) "iostart = %"PRIx64"" +sun4m_iommu_mem_writel_tlbflush(uint32_t val) "tlb flush %x" +sun4m_iommu_mem_writel_pgflush(uint32_t val) "page flush %x" +sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "get flags addr %"PRIx64" => pte %"PRIx64", *pte = %x" +sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x" +sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64"" # hw/usb-ehci.c -disable usb_ehci_reset(void) "=== RESET ===" -disable usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x" -disable usb_ehci_mmio_writel(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x" -disable usb_ehci_mmio_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)" -disable usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d" -disable usb_ehci_state(const char *schedule, const char *state) "%s schedule %s" -disable usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x" -disable usb_ehci_qh_fields(uint32_t addr, int rl, int mplen, int eps, int ep, int devaddr) "QH @ %08x - rl %d, mplen %d, eps %d, ep %d, dev %d" -disable usb_ehci_qh_bits(uint32_t addr, int c, int h, int dtc, int i) "QH @ %08x - c %d, h %d, dtc %d, i %d" -disable usb_ehci_qtd_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t altnext) "q %p - QTD @ %08x: next %08x altnext %08x" -disable usb_ehci_qtd_fields(uint32_t addr, int tbytes, int cpage, int cerr, int pid) "QTD @ %08x - tbytes %d, cpage %d, cerr %d, pid %d" -disable usb_ehci_qtd_bits(uint32_t addr, int ioc, int active, int halt, int babble, int xacterr) "QTD @ %08x - ioc %d, active %d, halt %d, babble %d, xacterr %d" -disable usb_ehci_itd(uint32_t addr, uint32_t nxt, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) "ITD @ %08x: next %08x - mplen %d, mult %d, ep %d, dev %d" -disable usb_ehci_port_attach(uint32_t port, const char *device) "attach port #%d - %s" -disable usb_ehci_port_detach(uint32_t port) "detach port #%d" -disable usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d" -disable usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t len, uint32_t bufpos) "write %d, cpage %d, offset 0x%03x, addr 0x%08x, len %d, bufpos %d" -disable usb_ehci_queue_action(void *q, const char *action) "q %p: %s" +usb_ehci_reset(void) "=== RESET ===" +usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x" +usb_ehci_mmio_writel(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x" +usb_ehci_mmio_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)" +usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d" +usb_ehci_state(const char *schedule, const char *state) "%s schedule %s" +usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x" +usb_ehci_qh_fields(uint32_t addr, int rl, int mplen, int eps, int ep, int devaddr) "QH @ %08x - rl %d, mplen %d, eps %d, ep %d, dev %d" +usb_ehci_qh_bits(uint32_t addr, int c, int h, int dtc, int i) "QH @ %08x - c %d, h %d, dtc %d, i %d" +usb_ehci_qtd_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t altnext) "q %p - QTD @ %08x: next %08x altnext %08x" +usb_ehci_qtd_fields(uint32_t addr, int tbytes, int cpage, int cerr, int pid) "QTD @ %08x - tbytes %d, cpage %d, cerr %d, pid %d" +usb_ehci_qtd_bits(uint32_t addr, int ioc, int active, int halt, int babble, int xacterr) "QTD @ %08x - ioc %d, active %d, halt %d, babble %d, xacterr %d" +usb_ehci_itd(uint32_t addr, uint32_t nxt, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) "ITD @ %08x: next %08x - mplen %d, mult %d, ep %d, dev %d" +usb_ehci_port_attach(uint32_t port, const char *device) "attach port #%d - %s" +usb_ehci_port_detach(uint32_t port) "detach port #%d" +usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d" +usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t len, uint32_t bufpos) "write %d, cpage %d, offset 0x%03x, addr 0x%08x, len %d, bufpos %d" +usb_ehci_queue_action(void *q, const char *action) "q %p: %s" # hw/usb-desc.c -disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" -disable usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d" -disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" -disable usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" -disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d" -disable usb_set_addr(int addr) "dev %d" -disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d" -disable usb_clear_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d" -disable usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d" +usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" +usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d" +usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" +usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" +usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d" +usb_set_addr(int addr) "dev %d" +usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d" +usb_clear_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d" +usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d" # hw/scsi-bus.c -disable scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d" -disable scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d" -disable scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d" -disable scsi_req_continue(int target, int lun, int tag) "target %d lun %d tag %d" -disable scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer) "target %d lun %d tag %d command %d dir %d length %d" -disable scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba) "target %d lun %d tag %d command %d lba %"PRIu64"" -disable scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d" -disable scsi_req_build_sense(int target, int lun, int tag, int key, int asc, int ascq) "target %d lun %d tag %d key %#02x asc %#02x ascq %#02x" -disable scsi_report_luns(int target, int lun, int tag) "target %d lun %d tag %d" -disable scsi_inquiry(int target, int lun, int tag, int cdb1, int cdb2) "target %d lun %d tag %d page %#02x/%#02x" -disable scsi_test_unit_ready(int target, int lun, int tag) "target %d lun %d tag %d" -disable scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d" +scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d" +scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d" +scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d" +scsi_req_continue(int target, int lun, int tag) "target %d lun %d tag %d" +scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer) "target %d lun %d tag %d command %d dir %d length %d" +scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba) "target %d lun %d tag %d command %d lba %"PRIu64"" +scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d" +scsi_req_build_sense(int target, int lun, int tag, int key, int asc, int ascq) "target %d lun %d tag %d key %#02x asc %#02x ascq %#02x" +scsi_report_luns(int target, int lun, int tag) "target %d lun %d tag %d" +scsi_inquiry(int target, int lun, int tag, int cdb1, int cdb2) "target %d lun %d tag %d page %#02x/%#02x" +scsi_test_unit_ready(int target, int lun, int tag) "target %d lun %d tag %d" +scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d" # vl.c -disable vm_state_notify(int running, int reason) "running %d reason %d" +vm_state_notify(int running, int reason) "running %d reason %d" # block/qed-l2-cache.c -disable qed_alloc_l2_cache_entry(void *l2_cache, void *entry) "l2_cache %p entry %p" -disable qed_unref_l2_cache_entry(void *entry, int ref) "entry %p ref %d" -disable qed_find_l2_cache_entry(void *l2_cache, void *entry, uint64_t offset, int ref) "l2_cache %p entry %p offset %"PRIu64" ref %d" +qed_alloc_l2_cache_entry(void *l2_cache, void *entry) "l2_cache %p entry %p" +qed_unref_l2_cache_entry(void *entry, int ref) "entry %p ref %d" +qed_find_l2_cache_entry(void *l2_cache, void *entry, uint64_t offset, int ref) "l2_cache %p entry %p offset %"PRIu64" ref %d" # block/qed-table.c -disable qed_read_table(void *s, uint64_t offset, void *table) "s %p offset %"PRIu64" table %p" -disable qed_read_table_cb(void *s, void *table, int ret) "s %p table %p ret %d" -disable qed_write_table(void *s, uint64_t offset, void *table, unsigned int index, unsigned int n) "s %p offset %"PRIu64" table %p index %u n %u" -disable qed_write_table_cb(void *s, void *table, int flush, int ret) "s %p table %p flush %d ret %d" +qed_read_table(void *s, uint64_t offset, void *table) "s %p offset %"PRIu64" table %p" +qed_read_table_cb(void *s, void *table, int ret) "s %p table %p ret %d" +qed_write_table(void *s, uint64_t offset, void *table, unsigned int index, unsigned int n) "s %p offset %"PRIu64" table %p index %u n %u" +qed_write_table_cb(void *s, void *table, int flush, int ret) "s %p table %p flush %d ret %d" # block/qed.c -disable qed_need_check_timer_cb(void *s) "s %p" -disable qed_start_need_check_timer(void *s) "s %p" -disable qed_cancel_need_check_timer(void *s) "s %p" -disable qed_aio_complete(void *s, void *acb, int ret) "s %p acb %p ret %d" -disable qed_aio_setup(void *s, void *acb, int64_t sector_num, int nb_sectors, void *opaque, int is_write) "s %p acb %p sector_num %"PRId64" nb_sectors %d opaque %p is_write %d" -disable qed_aio_next_io(void *s, void *acb, int ret, uint64_t cur_pos) "s %p acb %p ret %d cur_pos %"PRIu64"" -disable qed_aio_read_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" -disable qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" -disable qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" -disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" -disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" +qed_need_check_timer_cb(void *s) "s %p" +qed_start_need_check_timer(void *s) "s %p" +qed_cancel_need_check_timer(void *s) "s %p" +qed_aio_complete(void *s, void *acb, int ret) "s %p acb %p ret %d" +qed_aio_setup(void *s, void *acb, int64_t sector_num, int nb_sectors, void *opaque, int is_write) "s %p acb %p sector_num %"PRId64" nb_sectors %d opaque %p is_write %d" +qed_aio_next_io(void *s, void *acb, int ret, uint64_t cur_pos) "s %p acb %p ret %d cur_pos %"PRIu64"" +qed_aio_read_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" +qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" +qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" +qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" +qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" + +# hw/g364fb.c +g364fb_read(uint64_t addr, uint32_t val) "read addr=0x%"PRIx64": 0x%x" +g364fb_write(uint64_t addr, uint32_t new) "write addr=0x%"PRIx64": 0x%x" # hw/grlib_gptimer.c -disable grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run" -disable grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x" -disable grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x" -disable grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x" -disable grlib_gptimer_hit(int id) "timer:%d HIT" -disable grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" -disable grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" +grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run" +grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x" +grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x" +grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x" +grlib_gptimer_hit(int id) "timer:%d HIT" +grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" +grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" # hw/grlib_irqmp.c -disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x\n" -disable grlib_irqmp_ack(int intno) "interrupt:%d" -disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d" -disable grlib_irqmp_readl_unknown(uint64_t addr) "addr 0x%"PRIx64"" -disable grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" +grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x\n" +grlib_irqmp_ack(int intno) "interrupt:%d" +grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d" +grlib_irqmp_readl_unknown(uint64_t addr) "addr 0x%"PRIx64"" +grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" # hw/grlib_apbuart.c -disable grlib_apbuart_event(int event) "event:%d" -disable grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" +grlib_apbuart_event(int event) "event:%d" +grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" # hw/leon3.c -disable leon3_set_irq(int intno) "Set CPU IRQ %d" -disable leon3_reset_irq(int intno) "Reset CPU IRQ %d" +leon3_set_irq(int intno) "Set CPU IRQ %d" +leon3_reset_irq(int intno) "Reset CPU IRQ %d" # spice-qemu-char.c -disable spice_vmc_write(ssize_t out, int len) "spice wrottn %zd of requested %d" -disable spice_vmc_read(int bytes, int len) "spice read %d of requested %d" -disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p" -disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p" +spice_vmc_write(ssize_t out, int len) "spice wrottn %zd of requested %d" +spice_vmc_read(int bytes, int len) "spice read %d of requested %d" +spice_vmc_register_interface(void *scd) "spice vmc registered interface %p" +spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p" # hw/lm32_pic.c -disable lm32_pic_raise_irq(void) "Raise CPU interrupt" -disable lm32_pic_lower_irq(void) "Lower CPU interrupt" -disable lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d" -disable lm32_pic_set_im(uint32_t im) "im 0x%08x" -disable lm32_pic_set_ip(uint32_t ip) "ip 0x%08x" -disable lm32_pic_get_im(uint32_t im) "im 0x%08x" -disable lm32_pic_get_ip(uint32_t ip) "ip 0x%08x" +lm32_pic_raise_irq(void) "Raise CPU interrupt" +lm32_pic_lower_irq(void) "Lower CPU interrupt" +lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d" +lm32_pic_set_im(uint32_t im) "im 0x%08x" +lm32_pic_set_ip(uint32_t ip) "ip 0x%08x" +lm32_pic_get_im(uint32_t im) "im 0x%08x" +lm32_pic_get_ip(uint32_t ip) "ip 0x%08x" # hw/lm32_juart.c -disable lm32_juart_get_jtx(uint32_t value) "jtx 0x%08x" -disable lm32_juart_set_jtx(uint32_t value) "jtx 0x%08x" -disable lm32_juart_get_jrx(uint32_t value) "jrx 0x%08x" -disable lm32_juart_set_jrx(uint32_t value) "jrx 0x%08x" +lm32_juart_get_jtx(uint32_t value) "jtx 0x%08x" +lm32_juart_set_jtx(uint32_t value) "jtx 0x%08x" +lm32_juart_get_jrx(uint32_t value) "jrx 0x%08x" +lm32_juart_set_jrx(uint32_t value) "jrx 0x%08x" # hw/lm32_timer.c -disable lm32_timer_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -disable lm32_timer_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -disable lm32_timer_hit(void) "timer hit" -disable lm32_timer_irq_state(int level) "irq state %d" +lm32_timer_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +lm32_timer_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +lm32_timer_hit(void) "timer hit" +lm32_timer_irq_state(int level) "irq state %d" # hw/lm32_uart.c -disable lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -disable lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -disable lm32_uart_irq_state(int level) "irq state %d" +lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +lm32_uart_irq_state(int level) "irq state %d" # hw/lm32_sys.c -disable lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" # hw/milkymist-ac97.c -disable milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request" -disable milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply" -disable milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write" -disable milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read" -disable milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u" -disable milkymist_ac97_in_cb_transferred(int transferred) "transferred %d" -disable milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u" -disable milkymist_ac97_out_cb_transferred(int transferred) "transferred %d" +milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request" +milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply" +milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write" +milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read" +milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u" +milkymist_ac97_in_cb_transferred(int transferred) "transferred %d" +milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u" +milkymist_ac97_out_cb_transferred(int transferred) "transferred %d" # hw/milkymist-hpdmc.c -disable milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) "addr=%08x value=%08x" -disable milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=%08x value=%08x" +milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) "addr=%08x value=%08x" +milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=%08x value=%08x" # hw/milkymist-memcard.c -disable milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" # hw/milkymist-minimac2.c -disable milkymist_minimac2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_minimac2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_minimac2_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x" -disable milkymist_minimac2_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x" -disable milkymist_minimac2_tx_frame(uint32_t length) "length %u" -disable milkymist_minimac2_rx_frame(const void *buf, uint32_t length) "buf %p length %u" -disable milkymist_minimac2_drop_rx_frame(const void *buf) "buf %p" -disable milkymist_minimac2_rx_transfer(const void *buf, uint32_t length) "buf %p length %d" -disable milkymist_minimac2_raise_irq_rx(void) "Raise IRQ RX" -disable milkymist_minimac2_lower_irq_rx(void) "Lower IRQ RX" -disable milkymist_minimac2_pulse_irq_tx(void) "Pulse IRQ TX" +milkymist_minimac2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_minimac2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_minimac2_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x" +milkymist_minimac2_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x" +milkymist_minimac2_tx_frame(uint32_t length) "length %u" +milkymist_minimac2_rx_frame(const void *buf, uint32_t length) "buf %p length %u" +milkymist_minimac2_drop_rx_frame(const void *buf) "buf %p" +milkymist_minimac2_rx_transfer(const void *buf, uint32_t length) "buf %p length %d" +milkymist_minimac2_raise_irq_rx(void) "Raise IRQ RX" +milkymist_minimac2_lower_irq_rx(void) "Lower IRQ RX" +milkymist_minimac2_pulse_irq_tx(void) "Pulse IRQ TX" # hw/milkymist-pfpu.c -disable milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_pfpu_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_pfpu_vectout(uint32_t a, uint32_t b, uint32_t dma_ptr) "a %08x b %08x dma_ptr %08x" -disable milkymist_pfpu_pulse_irq(void) "Pulse IRQ" +milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_pfpu_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_pfpu_vectout(uint32_t a, uint32_t b, uint32_t dma_ptr) "a %08x b %08x dma_ptr %08x" +milkymist_pfpu_pulse_irq(void) "Pulse IRQ" # hw/milkymist-softusb.c -disable milkymist_softusb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_softusb_mevt(uint8_t m) "m %d" -disable milkymist_softusb_kevt(uint8_t m) "m %d" -disable milkymist_softusb_mouse_event(int dx, int dy, int dz, int bs) "dx %d dy %d dz %d bs %02x" -disable milkymist_softusb_pulse_irq(void) "Pulse IRQ" +milkymist_softusb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_softusb_mevt(uint8_t m) "m %d" +milkymist_softusb_kevt(uint8_t m) "m %d" +milkymist_softusb_mouse_event(int dx, int dy, int dz, int bs) "dx %d dy %d dz %d bs %02x" +milkymist_softusb_pulse_irq(void) "Pulse IRQ" # hw/milkymist-sysctl.c -disable milkymist_sysctl_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_sysctl_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_sysctl_icap_write(uint32_t value) "value %08x" -disable milkymist_sysctl_start_timer0(void) "Start timer0" -disable milkymist_sysctl_stop_timer0(void) "Stop timer0" -disable milkymist_sysctl_start_timer1(void) "Start timer1" -disable milkymist_sysctl_stop_timer1(void) "Stop timer1" -disable milkymist_sysctl_pulse_irq_timer0(void) "Pulse IRQ Timer0" -disable milkymist_sysctl_pulse_irq_timer1(void) "Pulse IRQ Timer1" +milkymist_sysctl_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_sysctl_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_sysctl_icap_write(uint32_t value) "value %08x" +milkymist_sysctl_start_timer0(void) "Start timer0" +milkymist_sysctl_stop_timer0(void) "Stop timer0" +milkymist_sysctl_start_timer1(void) "Start timer1" +milkymist_sysctl_stop_timer1(void) "Stop timer1" +milkymist_sysctl_pulse_irq_timer0(void) "Pulse IRQ Timer0" +milkymist_sysctl_pulse_irq_timer1(void) "Pulse IRQ Timer1" # hw/milkymist-tmu2.c -disable milkymist_tmu2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_tmu2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_tmu2_start(void) "Start TMU" -disable milkymist_tmu2_pulse_irq(void) "Pulse IRQ" +milkymist_tmu2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_tmu2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_tmu2_start(void) "Start TMU" +milkymist_tmu2_pulse_irq(void) "Pulse IRQ" # hw/milkymist-uart.c -disable milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_uart_pulse_irq_rx(void) "Pulse IRQ RX" -disable milkymist_uart_pulse_irq_tx(void) "Pulse IRQ TX" +milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_uart_pulse_irq_rx(void) "Pulse IRQ RX" +milkymist_uart_pulse_irq_tx(void) "Pulse IRQ TX" # hw/milkymist-vgafb.c -disable milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" -disable milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" # xen-all.c -disable xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx" -disable xen_client_set_memory(uint64_t start_addr, unsigned long size, unsigned long phys_offset, bool log_dirty) "%#"PRIx64" size %#lx, offset %#lx, log_dirty %i" +xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx" +xen_client_set_memory(uint64_t start_addr, unsigned long size, unsigned long phys_offset, bool log_dirty) "%#"PRIx64" size %#lx, offset %#lx, log_dirty %i" # xen-mapcache.c -disable xen_map_cache(uint64_t phys_addr) "want %#"PRIx64"" -disable xen_remap_bucket(uint64_t index) "index %#"PRIx64"" -disable xen_map_cache_return(void* ptr) "%p" -disable xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64"" -disable xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx" +xen_map_cache(uint64_t phys_addr) "want %#"PRIx64"" +xen_remap_bucket(uint64_t index) "index %#"PRIx64"" +xen_map_cache_return(void* ptr) "%p" +xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64"" +xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx" # exec.c -disable qemu_put_ram_ptr(void* addr) "%p" +qemu_put_ram_ptr(void* addr) "%p" # hw/xen_platform.c -disable xen_platform_log(char *s) "xen platform: %s" +xen_platform_log(char *s) "xen platform: %s" # qemu-coroutine.c -disable qemu_coroutine_enter(void *from, void *to, void *opaque) "from %p to %p opaque %p" -disable qemu_coroutine_yield(void *from, void *to) "from %p to %p" -disable qemu_coroutine_terminate(void *co) "self %p" +qemu_coroutine_enter(void *from, void *to, void *opaque) "from %p to %p opaque %p" +qemu_coroutine_yield(void *from, void *to) "from %p to %p" +qemu_coroutine_terminate(void *co) "self %p" # qemu-coroutine-lock.c -disable qemu_co_queue_next_bh(void) "" -disable qemu_co_queue_next(void *next) "next %p" -disable qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p" -disable qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p" -disable qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p" -disable qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p" +qemu_co_queue_next_bh(void) "" +qemu_co_queue_next(void *next) "next %p" +qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p" +qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p" +qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p" +qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p" # hw/escc.c -disable escc_put_queue(char channel, int b) "channel %c put: 0x%02x" -disable escc_get_queue(char channel, int val) "channel %c get 0x%02x" -disable escc_update_irq(int irq) "IRQ = %d" -disable escc_update_parameters(char channel, int speed, int parity, int data_bits, int stop_bits) "channel %c: speed=%d parity=%c data=%d stop=%d" -disable escc_mem_writeb_ctrl(char channel, uint32_t reg, uint32_t val) "Write channel %c, reg[%d] = %2.2x" -disable escc_mem_writeb_data(char channel, uint32_t val) "Write channel %c, ch %d" -disable escc_mem_readb_ctrl(char channel, uint32_t reg, uint8_t val) "Read channel %c, reg[%d] = %2.2x" -disable escc_mem_readb_data(char channel, uint32_t ret) "Read channel %c, ch %d" -disable escc_serial_receive_byte(char channel, int ch) "channel %c put ch %d" -disable escc_sunkbd_event_in(int ch) "Untranslated keycode %2.2x" -disable escc_sunkbd_event_out(int ch) "Translated keycode %2.2x" -disable escc_kbd_command(int val) "Command %d" -disable escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x" +escc_put_queue(char channel, int b) "channel %c put: 0x%02x" +escc_get_queue(char channel, int val) "channel %c get 0x%02x" +escc_update_irq(int irq) "IRQ = %d" +escc_update_parameters(char channel, int speed, int parity, int data_bits, int stop_bits) "channel %c: speed=%d parity=%c data=%d stop=%d" +escc_mem_writeb_ctrl(char channel, uint32_t reg, uint32_t val) "Write channel %c, reg[%d] = %2.2x" +escc_mem_writeb_data(char channel, uint32_t val) "Write channel %c, ch %d" +escc_mem_readb_ctrl(char channel, uint32_t reg, uint8_t val) "Read channel %c, reg[%d] = %2.2x" +escc_mem_readb_data(char channel, uint32_t ret) "Read channel %c, ch %d" +escc_serial_receive_byte(char channel, int ch) "channel %c put ch %d" +escc_sunkbd_event_in(int ch) "Untranslated keycode %2.2x" +escc_sunkbd_event_out(int ch) "Translated keycode %2.2x" +escc_kbd_command(int val) "Command %d" +escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x" diff --git a/trace/control.c b/trace/control.c new file mode 100644 index 0000000000..4c5527d20a --- /dev/null +++ b/trace/control.c @@ -0,0 +1,42 @@ +/* + * Interface for configuring and controlling the state of tracing events. + * + * Copyright (C) 2011 Lluís Vilanova <vilanova@ac.upc.edu> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include "trace/control.h" + + +void trace_backend_init_events(const char *fname) +{ + if (fname == NULL) { + return; + } + + FILE *fp = fopen(fname, "r"); + if (!fp) { + fprintf(stderr, "error: could not open trace events file '%s': %s\n", + fname, strerror(errno)); + exit(1); + } + char line_buf[1024]; + while (fgets(line_buf, sizeof(line_buf), fp)) { + size_t len = strlen(line_buf); + if (len > 1) { /* skip empty lines */ + line_buf[len - 1] = '\0'; + if (!trace_event_set_state(line_buf, true)) { + fprintf(stderr, + "error: trace event '%s' does not exist\n", line_buf); + exit(1); + } + } + } + if (fclose(fp) != 0) { + fprintf(stderr, "error: closing file '%s': %s\n", + fname, strerror(errno)); + exit(1); + } +} diff --git a/trace/control.h b/trace/control.h new file mode 100644 index 0000000000..2acaa4290e --- /dev/null +++ b/trace/control.h @@ -0,0 +1,41 @@ +/* + * Interface for configuring and controlling the state of tracing events. + * + * Copyright (C) 2011 Lluís Vilanova <vilanova@ac.upc.edu> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef TRACE_CONTROL_H +#define TRACE_CONTROL_H + +#include "qemu-common.h" + + +/** Print the state of all events. */ +void trace_print_events(FILE *stream, fprintf_function stream_printf); +/** Set the state of an event. + * + * @return Whether the state changed. + */ +bool trace_event_set_state(const char *name, bool state); + + +/** Initialize the tracing backend. + * + * @events Name of file with events to be enabled at startup; may be NULL. + * Corresponds to commandline option "-trace events=...". + * @file Name of trace output file; may be NULL. + * Corresponds to commandline option "-trace file=...". + * @return Whether the backend could be successfully initialized. + */ +bool trace_backend_init(const char *events, const char *file); + +/** Generic function to initialize the state of events. + * + * @fname Name of file with events to enable; may be NULL. + */ +void trace_backend_init_events(const char *fname); + +#endif /* TRACE_CONTROL_H */ diff --git a/trace/default.c b/trace/default.c new file mode 100644 index 0000000000..c9b27a289b --- /dev/null +++ b/trace/default.c @@ -0,0 +1,41 @@ +/* + * Default implementation for backend initialization from commandline. + * + * Copyright (C) 2011 Lluís Vilanova <vilanova@ac.upc.edu> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include "trace/control.h" + + +void trace_print_events(FILE *stream, fprintf_function stream_printf) +{ + fprintf(stderr, "warning: " + "cannot print the trace events with the current backend\n"); + stream_printf(stream, "error: " + "operation not supported with the current backend\n"); +} + +bool trace_event_set_state(const char *name, bool state) +{ + fprintf(stderr, "warning: " + "cannot set the state of a trace event with the current backend\n"); + return false; +} + +bool trace_backend_init(const char *events, const char *file) +{ + if (events) { + fprintf(stderr, "error: -trace events=...: " + "option not supported by the selected tracing backend\n"); + return false; + } + if (file) { + fprintf(stderr, "error: -trace file=...: " + "option not supported by the selected tracing backend\n"); + return false; + } + return true; +} diff --git a/simpletrace.c b/trace/simple.c index de355e9675..a6093682dd 100644 --- a/simpletrace.c +++ b/trace/simple.c @@ -16,6 +16,7 @@ #include <pthread.h> #include "qemu-timer.h" #include "trace.h" +#include "trace/control.h" /** Trace file header event ID */ #define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */ @@ -302,7 +303,12 @@ void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char } } -void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)) +void st_flush_trace_buffer(void) +{ + flush_trace_file(true); +} + +void trace_print_events(FILE *stream, fprintf_function stream_printf) { unsigned int i; @@ -312,25 +318,20 @@ void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, cons } } -bool st_change_trace_event_state(const char *name, bool enabled) +bool trace_event_set_state(const char *name, bool state) { unsigned int i; for (i = 0; i < NR_TRACE_EVENTS; i++) { if (!strcmp(trace_list[i].tp_name, name)) { - trace_list[i].state = enabled; + trace_list[i].state = state; return true; } } return false; } -void st_flush_trace_buffer(void) -{ - flush_trace_file(true); -} - -bool st_init(const char *file) +bool trace_backend_init(const char *events, const char *file) { pthread_t thread; pthread_attr_t attr; @@ -346,10 +347,12 @@ bool st_init(const char *file) pthread_sigmask(SIG_SETMASK, &oldset, NULL); if (ret != 0) { - return false; + fprintf(stderr, "warning: unable to initialize simple trace backend\n"); + } else { + atexit(st_flush_trace_buffer); + trace_backend_init_events(events); + st_set_trace_file(file); } - atexit(st_flush_trace_buffer); - st_set_trace_file(file); return true; } diff --git a/simpletrace.h b/trace/simple.h index 8d893bd849..466e75b4ff 100644 --- a/simpletrace.h +++ b/trace/simple.h @@ -8,14 +8,13 @@ * */ -#ifndef SIMPLETRACE_H -#define SIMPLETRACE_H +#ifndef TRACE_SIMPLE_H +#define TRACE_SIMPLE_H #include <stdint.h> #include <stdbool.h> #include <stdio.h> -#ifdef CONFIG_SIMPLE_TRACE typedef uint64_t TraceEventID; typedef struct { @@ -31,18 +30,9 @@ void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5); void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6); void st_print_trace(FILE *stream, fprintf_function stream_printf); -void st_print_trace_events(FILE *stream, fprintf_function stream_printf); -bool st_change_trace_event_state(const char *tname, bool tstate); void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf); void st_set_trace_file_enabled(bool enable); bool st_set_trace_file(const char *file); void st_flush_trace_buffer(void); -bool st_init(const char *file); -#else -static inline bool st_init(const char *file) -{ - return true; -} -#endif /* !CONFIG_SIMPLE_TRACE */ -#endif /* SIMPLETRACE_H */ +#endif /* TRACE_SIMPLE_H */ diff --git a/trace/stderr.c b/trace/stderr.c new file mode 100644 index 0000000000..7107c4a131 --- /dev/null +++ b/trace/stderr.c @@ -0,0 +1,37 @@ +#include "trace.h" +#include "trace/control.h" + + +void trace_print_events(FILE *stream, fprintf_function stream_printf) +{ + unsigned int i; + + for (i = 0; i < NR_TRACE_EVENTS; i++) { + stream_printf(stream, "%s [Event ID %u] : state %u\n", + trace_list[i].tp_name, i, trace_list[i].state); + } +} + +bool trace_event_set_state(const char *name, bool state) +{ + unsigned int i; + + for (i = 0; i < NR_TRACE_EVENTS; i++) { + if (!strcmp(trace_list[i].tp_name, name)) { + trace_list[i].state = state; + return true; + } + } + return false; +} + +bool trace_backend_init(const char *events, const char *file) +{ + if (file) { + fprintf(stderr, "error: -trace file=...: " + "option not supported by the selected tracing backend\n"); + return false; + } + trace_backend_init_events(events); + return true; +} diff --git a/trace/stderr.h b/trace/stderr.h new file mode 100644 index 0000000000..d575b613e3 --- /dev/null +++ b/trace/stderr.h @@ -0,0 +1,11 @@ +#ifndef TRACE_STDERR_H +#define TRACE_STDERR_H + +typedef uint64_t TraceEventID; + +typedef struct { + const char *tp_name; + bool state; +} TraceEvent; + +#endif /* ! TRACE_STDERR_H */ @@ -111,6 +111,8 @@ int main(int argc, char **argv) #define main qemu_main #endif /* CONFIG_COCOA */ +#include <glib.h> + #include "hw/hw.h" #include "hw/boards.h" #include "hw/usb.h" @@ -156,7 +158,7 @@ int main(int argc, char **argv) #include "slirp/libslirp.h" #include "trace.h" -#include "simpletrace.h" +#include "trace/control.h" #include "qemu-queue.h" #include "cpus.h" #include "arch_init.h" @@ -1321,6 +1323,75 @@ void qemu_system_vmstop_request(int reason) qemu_notify_event(); } +static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ +static int n_poll_fds; +static int max_priority; + +static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds, + fd_set *xfds, struct timeval *tv) +{ + GMainContext *context = g_main_context_default(); + int i; + int timeout = 0, cur_timeout; + + g_main_context_prepare(context, &max_priority); + + n_poll_fds = g_main_context_query(context, max_priority, &timeout, + poll_fds, ARRAY_SIZE(poll_fds)); + g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds)); + + for (i = 0; i < n_poll_fds; i++) { + GPollFD *p = &poll_fds[i]; + + if ((p->events & G_IO_IN)) { + FD_SET(p->fd, rfds); + *max_fd = MAX(*max_fd, p->fd); + } + if ((p->events & G_IO_OUT)) { + FD_SET(p->fd, wfds); + *max_fd = MAX(*max_fd, p->fd); + } + if ((p->events & G_IO_ERR)) { + FD_SET(p->fd, xfds); + *max_fd = MAX(*max_fd, p->fd); + } + } + + cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000); + if (timeout >= 0 && timeout < cur_timeout) { + tv->tv_sec = timeout / 1000; + tv->tv_usec = (timeout % 1000) * 1000; + } +} + +static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds, + bool err) +{ + GMainContext *context = g_main_context_default(); + + if (!err) { + int i; + + for (i = 0; i < n_poll_fds; i++) { + GPollFD *p = &poll_fds[i]; + + if ((p->events & G_IO_IN) && FD_ISSET(p->fd, rfds)) { + p->revents |= G_IO_IN; + } + if ((p->events & G_IO_OUT) && FD_ISSET(p->fd, wfds)) { + p->revents |= G_IO_OUT; + } + if ((p->events & G_IO_ERR) && FD_ISSET(p->fd, xfds)) { + p->revents |= G_IO_ERR; + } + } + } + + if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) { + g_main_context_dispatch(context); + } +} + int main_loop_wait(int nonblocking) { fd_set rfds, wfds, xfds; @@ -1346,8 +1417,10 @@ int main_loop_wait(int nonblocking) FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&xfds); + qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds); slirp_select_fill(&nfds, &rfds, &wfds, &xfds); + glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv); if (timeout > 0) { qemu_mutex_unlock_iothread(); @@ -1361,6 +1434,7 @@ int main_loop_wait(int nonblocking) qemu_iohandler_poll(&rfds, &wfds, &xfds, ret); slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0)); + glib_select_poll(&rfds, &wfds, &xfds, (ret < 0)); qemu_run_all_timers(); @@ -1371,17 +1445,6 @@ int main_loop_wait(int nonblocking) return ret; } -#ifndef CONFIG_IOTHREAD -static int vm_request_pending(void) -{ - return powerdown_requested || - reset_requested || - shutdown_requested || - debug_requested || - vmstop_requested; -} -#endif - qemu_irq qemu_system_powerdown; static void main_loop(void) @@ -1396,14 +1459,7 @@ static void main_loop(void) qemu_main_loop_start(); for (;;) { -#ifdef CONFIG_IOTHREAD nonblocking = !kvm_enabled() && last_io > 0; -#else - nonblocking = cpu_exec_all(); - if (vm_request_pending()) { - nonblocking = true; - } -#endif #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif @@ -2088,20 +2144,20 @@ static const QEMUOption *lookup_opt(int argc, char **argv, static gpointer malloc_and_trace(gsize n_bytes) { void *ptr = malloc(n_bytes); - trace_qemu_malloc(n_bytes, ptr); + trace_g_malloc(n_bytes, ptr); return ptr; } static gpointer realloc_and_trace(gpointer mem, gsize n_bytes) { void *ptr = realloc(mem, n_bytes); - trace_qemu_realloc(mem, n_bytes, ptr); + trace_g_realloc(mem, n_bytes, ptr); return ptr; } static void free_and_trace(gpointer mem) { - trace_qemu_free(mem); + trace_g_free(mem); free(mem); } @@ -2130,7 +2186,6 @@ int main(int argc, char **argv, char **envp) int show_vnc_port = 0; #endif int defconfig = 1; - const char *trace_file = NULL; const char *log_mask = NULL; const char *log_file = NULL; GMemVTable mem_trace = { @@ -2138,6 +2193,8 @@ int main(int argc, char **argv, char **envp) .realloc = realloc_and_trace, .free = free_and_trace, }; + const char *trace_events = NULL; + const char *trace_file = NULL; atexit(qemu_run_exit_notifiers); error_set_progname(argv[0]); @@ -2928,14 +2985,16 @@ int main(int argc, char **argv, char **envp) } xen_mode = XEN_ATTACH; break; -#ifdef CONFIG_SIMPLE_TRACE case QEMU_OPTION_trace: + { opts = qemu_opts_parse(qemu_find_opts("trace"), optarg, 0); - if (opts) { - trace_file = qemu_opt_get(opts, "file"); + if (!opts) { + exit(1); } + trace_events = qemu_opt_get(opts, "events"); + trace_file = qemu_opt_get(opts, "file"); break; -#endif + } case QEMU_OPTION_readconfig: { int ret = qemu_read_config_file(optarg); @@ -2993,8 +3052,8 @@ int main(int argc, char **argv, char **envp) set_cpu_log(log_mask); } - if (!st_init(trace_file)) { - fprintf(stderr, "warning: unable to initialize simple trace backend\n"); + if (!trace_backend_init(trace_events, trace_file)) { + exit(1); } /* If no data_dir is specified then try to find it relative to the @@ -38,16 +38,16 @@ SECTIONS .rel.plt : { *(.rel.plt) - PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE (__rel_iplt_start = .); *(.rel.iplt) - PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE (__rel_iplt_end = .); } .rela.plt : { *(.rela.plt) - PROVIDE_HIDDEN (__rela_iplt_start = .); + PROVIDE (__rela_iplt_start = .); *(.rela.iplt) - PROVIDE_HIDDEN (__rela_iplt_end = .); + PROVIDE (__rela_iplt_end = .); } .init : { @@ -70,8 +70,6 @@ SECTIONS .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000); @@ -97,8 +95,8 @@ SECTIONS .data1 : { *(.data1) } .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table) } .dynamic : { *(.dynamic) } .ctors : { |