From 3d6d306c104abe37610184f12e9342fcbc078395 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 15 Oct 2010 09:47:53 +0200 Subject: spice-core: fix watching for write events Signed-off-by: Gerd Hoffmann --- ui/spice-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/spice-core.c b/ui/spice-core.c index 6a1cf17..45807ed 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -95,7 +95,7 @@ static void watch_update_mask(SpiceWatch *watch, int event_mask) on_read = watch_read; } if (watch->event_mask & SPICE_WATCH_EVENT_WRITE) { - on_read = watch_write; + on_write = watch_write; } qemu_set_fd_handler(watch->fd, on_read, on_write, watch); } -- cgit v1.1 From f61d69607d58a81944a4bfcfc1f260d09a686460 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 2 Nov 2010 12:21:50 +0100 Subject: spice-core: fix warning when building with spice < 0.6.0 Signed-off-by: Gerd Hoffmann --- ui/spice-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/spice-core.c b/ui/spice-core.c index 45807ed..e97a72d 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -240,7 +240,7 @@ void qemu_spice_init(void) char *x509_key_file = NULL, *x509_cert_file = NULL, *x509_cacert_file = NULL; - int port, tls_port, len, addr_flags, streaming_video; + int port, tls_port, len, addr_flags; spice_image_compression_t compression; spice_wan_compression_t wan_compr; @@ -344,7 +344,7 @@ void qemu_spice_init(void) str = qemu_opt_get(opts, "streaming-video"); if (str) { - streaming_video = parse_stream_video(str); + int streaming_video = parse_stream_video(str); spice_server_set_streaming_video(spice_server, streaming_video); } -- cgit v1.1 From 7466bc49107fbd84336ba680f860d5eadd6def13 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 14 Oct 2010 16:55:01 +0200 Subject: spice-display: replace private lock with qemu mutex. qemu_spice_create_update() must aquire the global qemu mutex to make sure DisplayState doesn't change while we are accessing it. Once this is in place the private lock is pretty pointless as everything it protects is covered by the global qemu mutex now. Drop it. Signed-off-by: Gerd Hoffmann --- ui/spice-display.c | 27 ++++++++++++++------------- ui/spice-display.h | 1 - 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ui/spice-display.c b/ui/spice-display.c index 7b4f5c1..020b423 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -64,10 +64,10 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) /* * Called from spice server thread context (via interface_get_command). - * We do *not* hold the global qemu mutex here, so extra care is needed - * when calling qemu functions. Qemu interfaces used: - * - pflib (is re-entrant). - * - qemu_malloc (underlying glibc malloc is re-entrant). + * + * We must aquire the global qemu mutex here to make sure the + * DisplayState (+DisplaySurface) we are accessing doesn't change + * underneath us. */ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) { @@ -78,11 +78,12 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) uint8_t *src, *dst; int by, bw, bh; + qemu_mutex_lock_iothread(); if (qemu_spice_rect_is_empty(&ssd->dirty)) { + qemu_mutex_unlock_iothread(); return NULL; }; - pthread_mutex_lock(&ssd->lock); dprint(2, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__, ssd->dirty.left, ssd->dirty.right, ssd->dirty.top, ssd->dirty.bottom); @@ -140,7 +141,7 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) cmd->data = (intptr_t)drawable; memset(&ssd->dirty, 0, sizeof(ssd->dirty)); - pthread_mutex_unlock(&ssd->lock); + qemu_mutex_unlock_iothread(); return update; } @@ -184,14 +185,19 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) surface.type = 0; surface.mem = (intptr_t)ssd->buf; surface.group_id = MEMSLOT_GROUP_HOST; + + qemu_mutex_unlock_iothread(); ssd->worker->create_primary_surface(ssd->worker, 0, &surface); + qemu_mutex_lock_iothread(); } void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) { dprint(1, "%s:\n", __FUNCTION__); + qemu_mutex_unlock_iothread(); ssd->worker->destroy_primary_surface(ssd->worker, 0); + qemu_mutex_lock_iothread(); } void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) @@ -201,7 +207,9 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) if (running) { ssd->worker->start(ssd->worker); } else { + qemu_mutex_unlock_iothread(); ssd->worker->stop(ssd->worker); + qemu_mutex_lock_iothread(); } ssd->running = running; } @@ -219,31 +227,25 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, update_area.top = y; update_area.bottom = y + h; - pthread_mutex_lock(&ssd->lock); if (qemu_spice_rect_is_empty(&ssd->dirty)) { ssd->notify++; } qemu_spice_rect_union(&ssd->dirty, &update_area); - pthread_mutex_unlock(&ssd->lock); } void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) { dprint(1, "%s:\n", __FUNCTION__); - pthread_mutex_lock(&ssd->lock); memset(&ssd->dirty, 0, sizeof(ssd->dirty)); qemu_pf_conv_put(ssd->conv); ssd->conv = NULL; - pthread_mutex_unlock(&ssd->lock); qemu_spice_destroy_host_primary(ssd); qemu_spice_create_host_primary(ssd); - pthread_mutex_lock(&ssd->lock); memset(&ssd->dirty, 0, sizeof(ssd->dirty)); ssd->notify++; - pthread_mutex_unlock(&ssd->lock); } void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) @@ -398,7 +400,6 @@ void qemu_spice_display_init(DisplayState *ds) sdpy.ds = ds; sdpy.bufsize = (16 * 1024 * 1024); sdpy.buf = qemu_malloc(sdpy.bufsize); - pthread_mutex_init(&sdpy.lock, NULL); register_displaychangelistener(ds, &display_listener); sdpy.qxl.base.sif = &dpy_interface.base; diff --git a/ui/spice-display.h b/ui/spice-display.h index e17671c..aef0464 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -40,7 +40,6 @@ typedef struct SimpleSpiceDisplay { uint32_t unique; QemuPfConv *conv; - pthread_mutex_t lock; QXLRect dirty; int notify; int running; -- cgit v1.1 From 5dba48a882c126ccc86db6506cfa6dcca97badab Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Oct 2010 14:52:21 +0200 Subject: scsi-disk: Implement rerror option This implements the rerror option for SCSI disks. It also includes minor changes to the write path where the same code is used that was criticized in the review for the changes to the read path required for rerror support. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- blockdev.c | 6 ++-- hw/scsi-disk.c | 100 +++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 69 insertions(+), 37 deletions(-) diff --git a/blockdev.c b/blockdev.c index ff7602b..6cb179a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -314,7 +314,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) on_write_error = BLOCK_ERR_STOP_ENOSPC; if ((buf = qemu_opt_get(opts, "werror")) != NULL) { if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { - fprintf(stderr, "werror is no supported by this format\n"); + fprintf(stderr, "werror is not supported by this format\n"); return NULL; } @@ -326,8 +326,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) on_read_error = BLOCK_ERR_REPORT; if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { - if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) { - fprintf(stderr, "rerror is no supported by this format\n"); + if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) { + fprintf(stderr, "rerror is not supported by this format\n"); return NULL; } diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 9628b39..43a5b59 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -41,7 +41,10 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #define SCSI_DMA_BUF_SIZE 131072 #define SCSI_MAX_INQUIRY_LEN 256 -#define SCSI_REQ_STATUS_RETRY 0x01 +#define SCSI_REQ_STATUS_RETRY 0x01 +#define SCSI_REQ_STATUS_RETRY_TYPE_MASK 0x06 +#define SCSI_REQ_STATUS_RETRY_READ 0x00 +#define SCSI_REQ_STATUS_RETRY_WRITE 0x02 typedef struct SCSIDiskState SCSIDiskState; @@ -70,6 +73,8 @@ struct SCSIDiskState char *serial; }; +static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type); + static SCSIDiskReq *scsi_new_request(SCSIDiskState *s, uint32_t tag, uint32_t lun) { @@ -127,34 +132,30 @@ static void scsi_cancel_io(SCSIDevice *d, uint32_t tag) static void scsi_read_complete(void * opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; + int n; r->req.aiocb = NULL; if (ret) { - DPRINTF("IO error\n"); - r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0); - scsi_command_complete(r, CHECK_CONDITION, NO_SENSE); - return; + if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) { + return; + } } + DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->iov.iov_len); + n = r->iov.iov_len / 512; + r->sector += n; + r->sector_count -= n; r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len); } -/* Read more data from scsi device into buffer. */ -static void scsi_read_data(SCSIDevice *d, uint32_t tag) + +static void scsi_read_request(SCSIDiskReq *r) { - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d); - SCSIDiskReq *r; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); uint32_t n; - r = scsi_find_request(s, tag); - if (!r) { - BADF("Bad read tag 0x%x\n", tag); - /* ??? This is the wrong error. */ - scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR); - return; - } if (r->sector_count == (uint32_t)-1) { DPRINTF("Read buf_len=%zd\n", r->iov.iov_len); r->sector_count = 0; @@ -177,29 +178,54 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag) scsi_read_complete, r); if (r->req.aiocb == NULL) scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR); - r->sector += n; - r->sector_count -= n; } -static int scsi_handle_write_error(SCSIDiskReq *r, int error) +/* Read more data from scsi device into buffer. */ +static void scsi_read_data(SCSIDevice *d, uint32_t tag) { + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d); + SCSIDiskReq *r; + + r = scsi_find_request(s, tag); + if (!r) { + BADF("Bad read tag 0x%x\n", tag); + /* ??? This is the wrong error. */ + scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR); + return; + } + + /* No data transfer may already be in progress */ + assert(r->req.aiocb == NULL); + + scsi_read_request(r); +} + +static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type) +{ + int is_read = (type == SCSI_REQ_STATUS_RETRY_READ); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - BlockErrorAction action = bdrv_get_on_error(s->bs, 0); + BlockErrorAction action = bdrv_get_on_error(s->bs, is_read); if (action == BLOCK_ERR_IGNORE) { - bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, 0); + bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read); return 0; } if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC) || action == BLOCK_ERR_STOP_ANY) { - r->status |= SCSI_REQ_STATUS_RETRY; - bdrv_mon_event(s->bs, BDRV_ACTION_STOP, 0); + + type &= SCSI_REQ_STATUS_RETRY_TYPE_MASK; + r->status |= SCSI_REQ_STATUS_RETRY | type; + + bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read); vm_stop(0); } else { + if (type == SCSI_REQ_STATUS_RETRY_READ) { + r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0); + } scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR); - bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, 0); + bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read); } return 1; @@ -214,8 +240,9 @@ static void scsi_write_complete(void * opaque, int ret) r->req.aiocb = NULL; if (ret) { - if (scsi_handle_write_error(r, -ret)) + if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) { return; + } } n = r->iov.iov_len / 512; @@ -268,8 +295,8 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag) return 1; } - if (r->req.aiocb) - BADF("Data transfer already in progress\n"); + /* No data transfer may already be in progress */ + assert(r->req.aiocb == NULL); scsi_write_request(r); @@ -288,8 +315,18 @@ static void scsi_dma_restart_bh(void *opaque) QTAILQ_FOREACH(req, &s->qdev.requests, next) { r = DO_UPCAST(SCSIDiskReq, req, req); if (r->status & SCSI_REQ_STATUS_RETRY) { - r->status &= ~SCSI_REQ_STATUS_RETRY; - scsi_write_request(r); + int status = r->status; + r->status &= + ~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK); + + switch (status & SCSI_REQ_STATUS_RETRY_TYPE_MASK) { + case SCSI_REQ_STATUS_RETRY_READ: + scsi_read_request(r); + break; + case SCSI_REQ_STATUS_RETRY_WRITE: + scsi_write_request(r); + break; + } } } } @@ -1152,11 +1189,6 @@ static int scsi_disk_initfn(SCSIDevice *dev) return -1; } - if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) { - error_report("Device doesn't support drive option rerror"); - return -1; - } - if (!s->serial) { /* try to fall back to value set with legacy -drive serial=... */ dinfo = drive_get_by_blockdev(s->bs); -- cgit v1.1 From 205ef7961f781496366e0a93a4ec621ad3724bd7 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 21 Oct 2010 16:43:43 +0200 Subject: block: Allow bdrv_flush to return errors This changes bdrv_flush to return 0 on success and -errno in case of failure. It's a requirement for implementing proper error handle in users of bdrv_flush. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- block.c | 21 +++++++++++++++++---- block.h | 2 +- block/blkdebug.c | 4 ++-- block/blkverify.c | 4 ++-- block/cow.c | 4 ++-- block/qcow.c | 4 ++-- block/qcow2.c | 4 ++-- block/raw-posix.c | 4 ++-- block/raw-win32.c | 9 ++++++++- block/raw.c | 4 ++-- block/vdi.c | 4 ++-- block/vmdk.c | 4 ++-- block_int.h | 2 +- 13 files changed, 45 insertions(+), 25 deletions(-) diff --git a/block.c b/block.c index 985d0b7..6b505fb 100644 --- a/block.c +++ b/block.c @@ -1453,14 +1453,27 @@ const char *bdrv_get_device_name(BlockDriverState *bs) return bs->device_name; } -void bdrv_flush(BlockDriverState *bs) +int bdrv_flush(BlockDriverState *bs) { if (bs->open_flags & BDRV_O_NO_FLUSH) { - return; + return 0; + } + + if (bs->drv && bs->drv->bdrv_flush) { + return bs->drv->bdrv_flush(bs); } - if (bs->drv && bs->drv->bdrv_flush) - bs->drv->bdrv_flush(bs); + /* + * Some block drivers always operate in either writethrough or unsafe mode + * and don't support bdrv_flush therefore. Usually qemu doesn't know how + * the server works (because the behaviour is hardcoded or depends on + * server-side configuration), so we can't ensure that everything is safe + * on disk. Returning an error doesn't work because that would break guests + * even if the server operates in writethrough mode. + * + * Let's hope the user knows what he's doing. + */ + return 0; } void bdrv_flush_all(void) diff --git a/block.h b/block.h index a4facf2..78ecfac 100644 --- a/block.h +++ b/block.h @@ -142,7 +142,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque); /* Ensure contents are flushed to disk. */ -void bdrv_flush(BlockDriverState *bs); +int bdrv_flush(BlockDriverState *bs); void bdrv_flush_all(void); void bdrv_close_all(void); diff --git a/block/blkdebug.c b/block/blkdebug.c index 4d6ff0a..cd9eb80 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -397,9 +397,9 @@ static void blkdebug_close(BlockDriverState *bs) } } -static void blkdebug_flush(BlockDriverState *bs) +static int blkdebug_flush(BlockDriverState *bs) { - bdrv_flush(bs->file); + return bdrv_flush(bs->file); } static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs, diff --git a/block/blkverify.c b/block/blkverify.c index b2a12fe..0a8d691 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -116,12 +116,12 @@ static void blkverify_close(BlockDriverState *bs) s->test_file = NULL; } -static void blkverify_flush(BlockDriverState *bs) +static int blkverify_flush(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; /* Only flush test file, the raw file is not important */ - bdrv_flush(s->test_file); + return bdrv_flush(s->test_file); } static int64_t blkverify_getlength(BlockDriverState *bs) diff --git a/block/cow.c b/block/cow.c index eedcc48..4cf543c 100644 --- a/block/cow.c +++ b/block/cow.c @@ -282,9 +282,9 @@ exit: return ret; } -static void cow_flush(BlockDriverState *bs) +static int cow_flush(BlockDriverState *bs) { - bdrv_flush(bs->file); + return bdrv_flush(bs->file); } static QEMUOptionParameter cow_create_options[] = { diff --git a/block/qcow.c b/block/qcow.c index 816103d..9cd547d 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -910,9 +910,9 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, return 0; } -static void qcow_flush(BlockDriverState *bs) +static int qcow_flush(BlockDriverState *bs) { - bdrv_flush(bs->file); + return bdrv_flush(bs->file); } static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs, diff --git a/block/qcow2.c b/block/qcow2.c index b816d87..537c479 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1148,9 +1148,9 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, return 0; } -static void qcow_flush(BlockDriverState *bs) +static int qcow_flush(BlockDriverState *bs) { - bdrv_flush(bs->file); + return bdrv_flush(bs->file); } static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs, diff --git a/block/raw-posix.c b/block/raw-posix.c index d0393e0..d0960b8 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -734,10 +734,10 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) return result; } -static void raw_flush(BlockDriverState *bs) +static int raw_flush(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; - qemu_fdatasync(s->fd); + return qemu_fdatasync(s->fd); } diff --git a/block/raw-win32.c b/block/raw-win32.c index 503ed39..7f32778 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -150,7 +150,14 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num, static void raw_flush(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; - FlushFileBuffers(s->hfile); + int ret; + + ret = FlushFileBuffers(s->hfile); + if (ret != 0) { + return -EIO; + } + + return 0; } static void raw_close(BlockDriverState *bs) diff --git a/block/raw.c b/block/raw.c index 9108779..1980deb 100644 --- a/block/raw.c +++ b/block/raw.c @@ -39,9 +39,9 @@ static void raw_close(BlockDriverState *bs) { } -static void raw_flush(BlockDriverState *bs) +static int raw_flush(BlockDriverState *bs) { - bdrv_flush(bs->file); + return bdrv_flush(bs->file); } static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs, diff --git a/block/vdi.c b/block/vdi.c index f72633c..3b51e53 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -900,10 +900,10 @@ static void vdi_close(BlockDriverState *bs) { } -static void vdi_flush(BlockDriverState *bs) +static int vdi_flush(BlockDriverState *bs) { logout("\n"); - bdrv_flush(bs->file); + return bdrv_flush(bs->file); } diff --git a/block/vmdk.c b/block/vmdk.c index 2d4ba42..872aeba 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -823,9 +823,9 @@ static void vmdk_close(BlockDriverState *bs) qemu_free(s->l2_cache); } -static void vmdk_flush(BlockDriverState *bs) +static int vmdk_flush(BlockDriverState *bs) { - bdrv_flush(bs->file); + return bdrv_flush(bs->file); } diff --git a/block_int.h b/block_int.h index 87e60b8..3c3adb5 100644 --- a/block_int.h +++ b/block_int.h @@ -59,7 +59,7 @@ struct BlockDriver { const uint8_t *buf, int nb_sectors); void (*bdrv_close)(BlockDriverState *bs); int (*bdrv_create)(const char *filename, QEMUOptionParameter *options); - void (*bdrv_flush)(BlockDriverState *bs); + int (*bdrv_flush)(BlockDriverState *bs); int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); int (*bdrv_set_key)(BlockDriverState *bs, const char *key); -- cgit v1.1 From 8af7a3ab51d9780f52b7d2581f144ab127097362 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Oct 2010 12:43:22 +0200 Subject: scsi-disk: Complete failed requests in scsi_disk_emulate_command This pulls the request completion for error cases from the caller to scsi_disk_emulate_command. This should not change semantics, but allows to reuse scsi_handle_write_error() for flushes in the next patch. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- hw/scsi-disk.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 43a5b59..96acfe3 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -784,8 +784,9 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf) return toclen; } -static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf) +static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) { + SCSIRequest *req = &r->req; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); uint64_t nb_sectors; int buflen = 0; @@ -943,12 +944,12 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf) return buflen; not_ready: - scsi_req_set_status(req, CHECK_CONDITION, NOT_READY); - return 0; + scsi_command_complete(r, CHECK_CONDITION, NOT_READY); + return -1; illegal_request: - scsi_req_set_status(req, CHECK_CONDITION, ILLEGAL_REQUEST); - return 0; + scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST); + return -1; } /* Execute a scsi command. Returns the length of the data expected by the @@ -1056,14 +1057,12 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, case REPORT_LUNS: case VERIFY: case REZERO_UNIT: - rc = scsi_disk_emulate_command(&r->req, outbuf); - if (rc > 0) { - r->iov.iov_len = rc; - } else { - scsi_req_complete(&r->req); - scsi_remove_request(r); + rc = scsi_disk_emulate_command(r, outbuf); + if (rc < 0) { return 0; } + + r->iov.iov_len = rc; break; case READ_6: case READ_10: -- cgit v1.1 From 78ced65e6ec6d76059f0d943a82103122d4e6494 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 25 Oct 2010 16:40:17 +0200 Subject: scsi-disk: Implement werror for flushes Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- hw/scsi-disk.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 96acfe3..6815239 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -45,6 +45,7 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #define SCSI_REQ_STATUS_RETRY_TYPE_MASK 0x06 #define SCSI_REQ_STATUS_RETRY_READ 0x00 #define SCSI_REQ_STATUS_RETRY_WRITE 0x02 +#define SCSI_REQ_STATUS_RETRY_FLUSH 0x04 typedef struct SCSIDiskState SCSIDiskState; @@ -74,6 +75,7 @@ struct SCSIDiskState }; static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type); +static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf); static SCSIDiskReq *scsi_new_request(SCSIDiskState *s, uint32_t tag, uint32_t lun) @@ -316,6 +318,8 @@ static void scsi_dma_restart_bh(void *opaque) r = DO_UPCAST(SCSIDiskReq, req, req); if (r->status & SCSI_REQ_STATUS_RETRY) { int status = r->status; + int ret; + r->status &= ~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK); @@ -326,6 +330,11 @@ static void scsi_dma_restart_bh(void *opaque) case SCSI_REQ_STATUS_RETRY_WRITE: scsi_write_request(r); break; + case SCSI_REQ_STATUS_RETRY_FLUSH: + ret = scsi_disk_emulate_command(r, r->iov.iov_base); + if (ret == 0) { + scsi_command_complete(r, GOOD, NO_SENSE); + } } } } @@ -790,6 +799,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); uint64_t nb_sectors; int buflen = 0; + int ret; switch (req->cmd.buf[0]) { case TEST_UNIT_READY: @@ -880,7 +890,12 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) buflen = 8; break; case SYNCHRONIZE_CACHE: - bdrv_flush(s->bs); + ret = bdrv_flush(s->bs); + 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); -- cgit v1.1 From 4a4111851fa75bc91028a26eb75dcdd136d9032d Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 22 Oct 2010 16:17:57 +0200 Subject: vpc: Implement bdrv_flush Signed-off-by: Kevin Wolf --- block/vpc.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index e50509e..416f489 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -439,6 +439,10 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num, return 0; } +static int vpc_flush(BlockDriverState *bs) +{ + return bdrv_flush(bs->file); +} /* * Calculates the number of cylinders, heads and sectors per cylinder @@ -618,14 +622,15 @@ static QEMUOptionParameter vpc_create_options[] = { }; static BlockDriver bdrv_vpc = { - .format_name = "vpc", - .instance_size = sizeof(BDRVVPCState), - .bdrv_probe = vpc_probe, - .bdrv_open = vpc_open, - .bdrv_read = vpc_read, - .bdrv_write = vpc_write, - .bdrv_close = vpc_close, - .bdrv_create = vpc_create, + .format_name = "vpc", + .instance_size = sizeof(BDRVVPCState), + .bdrv_probe = vpc_probe, + .bdrv_open = vpc_open, + .bdrv_read = vpc_read, + .bdrv_write = vpc_write, + .bdrv_flush = vpc_flush, + .bdrv_close = vpc_close, + .bdrv_create = vpc_create, .create_options = vpc_create_options, }; -- cgit v1.1 From 1c02e2a17104fe7fc11893125864dc0daf1e6d5b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 28 Oct 2010 16:16:00 +0200 Subject: qcow2: Invalidate cache after failed read The cache content may be destroyed after a failed read, better not use it any more. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- block/qcow2-cluster.c | 1 + block/qcow2-refcount.c | 1 + 2 files changed, 2 insertions(+) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 4f7dc59b7..b040208 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -188,6 +188,7 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset, ret = bdrv_pread(bs->file, l2_offset, *l2_table, s->l2_size * sizeof(uint64_t)); if (ret < 0) { + qcow2_l2_cache_reset(bs); return ret; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 0efb676..a10453c 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -103,6 +103,7 @@ static int load_refcount_block(BlockDriverState *bs, ret = bdrv_pread(bs->file, refcount_block_offset, s->refcount_block_cache, s->cluster_size); if (ret < 0) { + s->refcount_block_cache_offset = 0; return ret; } -- cgit v1.1 From a31335863648d1e707f59296cffb74205aedba96 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 30 Oct 2010 16:46:27 +0000 Subject: block: avoid a warning on 64 bit hosts with long as int64_t When building on a 64 bit host which uses 'long' for int64_t, GCC emits a warning: CC block/blkverify.o /src/qemu/block/blkverify.c: In function `blkverify_verify_readv': /src/qemu/block/blkverify.c:304: warning: long long int format, long unsigned int arg (arg 3) Rework a77cffe7e916f4dd28f2048982ea2e0d98143b11 to avoid the warning. Signed-off-by: Blue Swirl Signed-off-by: Kevin Wolf --- block/blkverify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/blkverify.c b/block/blkverify.c index 0a8d691..c7522b4 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -300,8 +300,8 @@ static void blkverify_verify_readv(BlkverifyAIOCB *acb) { ssize_t offset = blkverify_iovec_compare(acb->qiov, &acb->raw_qiov); if (offset != -1) { - blkverify_err(acb, "contents mismatch in sector %lld", - acb->sector_num + (offset / BDRV_SECTOR_SIZE)); + blkverify_err(acb, "contents mismatch in sector %" PRId64, + acb->sector_num + (int64_t)(offset / BDRV_SECTOR_SIZE)); } } -- cgit v1.1 From b2df7531f3adc4f0f65067b917cef8c66ba812c5 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 27 Oct 2010 13:04:15 +0200 Subject: ide: Handle immediate bdrv_aio_flush failure If bdrv_aio_flush returns NULL, this should be treated as an error. Signed-off-by: Kevin Wolf --- hw/ide/core.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index bc3e916..484e0ca 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -811,10 +811,16 @@ static void ide_flush_cb(void *opaque, int ret) static void ide_flush_cache(IDEState *s) { - if (s->bs) { - bdrv_aio_flush(s->bs, ide_flush_cb, s); - } else { + BlockDriverAIOCB *acb; + + if (s->bs == NULL) { ide_flush_cb(s, 0); + return; + } + + acb = bdrv_aio_flush(s->bs, ide_flush_cb, s); + if (acb == NULL) { + ide_flush_cb(s, -EIO); } } -- cgit v1.1 From 18a8d4214b861aff0caa5acfa921862d0be05bbb Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 27 Oct 2010 13:10:15 +0200 Subject: virtio-blk: Handle immediate flush failure properly Fix virtio-blk to use the usual completion path that involves werror handling instead of directly completing the request in cases where bdrv_aio_flush returns NULL. Signed-off-by: Kevin Wolf --- hw/virtio-blk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index dbe20707..49528a9 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -273,7 +273,7 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb) acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req); if (!acb) { - virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); + virtio_blk_flush_complete(req, -EIO); } } -- cgit v1.1 From d33ea50a958b2e050d2b28e5f17e3b55e91c6d74 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 27 Oct 2010 13:15:27 +0200 Subject: scsi-disk: Fix immediate failure of bdrv_aio_* Fix scsi-disk to use the usual completion paths that involve rerror/werror handling instead of directly completing the requests in cases where bdrv_aio_readv/writev returns NULL. Signed-off-by: Kevin Wolf --- hw/scsi-disk.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 6815239..dc71957 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -178,8 +178,9 @@ static void scsi_read_request(SCSIDiskReq *r) qemu_iovec_init_external(&r->qiov, &r->iov, 1); r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n, scsi_read_complete, r); - if (r->req.aiocb == NULL) - scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR); + if (r->req.aiocb == NULL) { + scsi_read_complete(r, -EIO); + } } /* Read more data from scsi device into buffer. */ @@ -273,9 +274,9 @@ static void scsi_write_request(SCSIDiskReq *r) qemu_iovec_init_external(&r->qiov, &r->iov, 1); r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n, scsi_write_complete, r); - if (r->req.aiocb == NULL) - scsi_command_complete(r, CHECK_CONDITION, - HARDWARE_ERROR); + if (r->req.aiocb == NULL) { + scsi_write_complete(r, -EIO); + } } else { /* Invoke completion routine to fetch data from host. */ scsi_write_complete(r, 0); -- cgit v1.1 From cfd07e7abb1ef39373cd4ce312b015d61b9eea8d Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Nov 2010 15:10:40 +0000 Subject: Fix win32 build Fix a return value change missed by 205ef7961f781496366e0a93a4ec621ad3724bd7. Signed-off-by: Blue Swirl --- block/raw-win32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/raw-win32.c b/block/raw-win32.c index 7f32778..06c9710 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -147,7 +147,7 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num, return ret_count; } -static void raw_flush(BlockDriverState *bs) +static int raw_flush(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; int ret; -- cgit v1.1 From dc4b9240dc531f1fc8538e9dc968f2e34e169346 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Nov 2010 11:47:44 +0100 Subject: intel-hda: exit cleanup Add pci exit callback for the intel-hda device and cleanup properly. Also add an exit callback to the HDA bus implementation and make sure it is called on qdev_free(). Signed-off-by: Gerd Hoffmann Signed-off-by: malc --- hw/intel-hda.c | 20 ++++++++++++++++++++ hw/intel-hda.h | 1 + 2 files changed, 21 insertions(+) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index ccb059d..78c32da 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -61,9 +61,20 @@ static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base) return info->init(dev); } +static int hda_codec_dev_exit(DeviceState *qdev) +{ + HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev); + + if (dev->info->exit) { + dev->info->exit(dev); + } + return 0; +} + void hda_codec_register(HDACodecDeviceInfo *info) { info->qdev.init = hda_codec_dev_init; + info->qdev.exit = hda_codec_dev_exit; info->qdev.bus_info = &hda_codec_bus_info; qdev_register(&info->qdev); } @@ -1137,6 +1148,14 @@ static int intel_hda_init(PCIDevice *pci) return 0; } +static int intel_hda_exit(PCIDevice *pci) +{ + IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); + + cpu_unregister_io_memory(d->mmio_addr); + return 0; +} + static int intel_hda_post_load(void *opaque, int version) { IntelHDAState* d = opaque; @@ -1219,6 +1238,7 @@ static PCIDeviceInfo intel_hda_info = { .qdev.vmsd = &vmstate_intel_hda, .qdev.reset = intel_hda_reset, .init = intel_hda_init, + .exit = intel_hda_exit, .qdev.props = (Property[]) { DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/intel-hda.h b/hw/intel-hda.h index ba290ec..4e44e38 100644 --- a/hw/intel-hda.h +++ b/hw/intel-hda.h @@ -32,6 +32,7 @@ struct HDACodecDevice { struct HDACodecDeviceInfo { DeviceInfo qdev; int (*init)(HDACodecDevice *dev); + int (*exit)(HDACodecDevice *dev); void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data); void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running); }; -- cgit v1.1 From 129dcd2c66c3f693425f8a50c553146b8f6f4fd6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Nov 2010 11:47:45 +0100 Subject: hda-audio: exit cleanup Add exit callback to the driver. Unregister the sound card properly on exit. [ v2: codestyle: add braces ] Signed-off-by: Gerd Hoffmann Signed-off-by: malc --- hw/hda-audio.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hw/hda-audio.c b/hw/hda-audio.c index 1035774..c699d6f 100644 --- a/hw/hda-audio.c +++ b/hw/hda-audio.c @@ -808,6 +808,28 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc) return 0; } +static int hda_audio_exit(HDACodecDevice *hda) +{ + HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda); + HDAAudioStream *st; + int i; + + dprint(a, 1, "%s\n", __FUNCTION__); + for (i = 0; i < ARRAY_SIZE(a->st); i++) { + st = a->st + i; + if (st->node == NULL) { + continue; + } + if (st->output) { + AUD_close_out(&a->card, st->voice.out); + } else { + AUD_close_in(&a->card, st->voice.in); + } + } + AUD_remove_card(&a->card); + return 0; +} + static int hda_audio_post_load(void *opaque, int version) { HDAAudioState *a = opaque; @@ -879,6 +901,7 @@ static HDACodecDeviceInfo hda_audio_info_output = { .qdev.vmsd = &vmstate_hda_audio, .qdev.props = hda_audio_properties, .init = hda_audio_init_output, + .exit = hda_audio_exit, .command = hda_audio_command, .stream = hda_audio_stream, }; @@ -890,6 +913,7 @@ static HDACodecDeviceInfo hda_audio_info_duplex = { .qdev.vmsd = &vmstate_hda_audio, .qdev.props = hda_audio_properties, .init = hda_audio_init_duplex, + .exit = hda_audio_exit, .command = hda_audio_command, .stream = hda_audio_stream, }; -- cgit v1.1 From af93485cde810f3c2f488533e0b60c99eae5d01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 9 Nov 2010 11:47:46 +0100 Subject: intel-hda: Honor WAKEEN bits. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDA: Honor WAKEEN bits when deciding to raise an interrupt on codec status change. This prevents an interrupt storm with the Haiku HDA driver which does not handle codec status changes in the irq handler. Signed-off-by: François Revol Signed-off-by: Gerd Hoffmann Signed-off-by: malc --- hw/intel-hda.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 78c32da..2c1ef12 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -246,7 +246,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d) if (d->rirb_sts & ICH6_RBSTS_OVERRUN) { sts |= (1 << 30); } - if (d->state_sts) { + if (d->state_sts & d->wake_en) { sts |= (1 << 30); } @@ -628,6 +628,7 @@ static const struct IntelHDAReg regtab[] = { [ ICH6_REG_WAKEEN ] = { .name = "WAKEEN", .size = 2, + .wmask = 0x3fff, .offset = offsetof(IntelHDAState, wake_en), }, [ ICH6_REG_STATESTS ] = { -- cgit v1.1 From 6a0d02f5be44ee17cf0ce843f0658d08e97a68c2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Nov 2010 11:47:47 +0100 Subject: intel-hda: update irq status on WAKEEN changes. When the guest updates the WAKEEN register we must re-calculate the IRQ status. Signed-off-by: Gerd Hoffmann Signed-off-by: malc --- hw/intel-hda.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 2c1ef12..e478e67 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -508,6 +508,11 @@ static void intel_hda_set_g_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint32 } } +static void intel_hda_set_wake_en(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old) +{ + intel_hda_update_irq(d); +} + static void intel_hda_set_state_sts(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old) { intel_hda_update_irq(d); @@ -630,6 +635,7 @@ static const struct IntelHDAReg regtab[] = { .size = 2, .wmask = 0x3fff, .offset = offsetof(IntelHDAState, wake_en), + .whandler = intel_hda_set_wake_en, }, [ ICH6_REG_STATESTS ] = { .name = "STATESTS", -- cgit v1.1 From 17786d52acd3e18e77cd7e823f7d6bad9ece818e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Nov 2010 11:47:48 +0100 Subject: intel-hda: add msi support This patch adds MSI support to the intel hda audio driver. It is enabled by default, use '-device intel-hda,msi=0' to disable it. [ v2: codestyle: add braces ] Signed-off-by: Gerd Hoffmann Signed-off-by: malc --- hw/intel-hda.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index e478e67..5e13dc3 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -19,6 +19,7 @@ #include "hw.h" #include "pci.h" +#include "msi.h" #include "qemu-timer.h" #include "audiodev.h" #include "intel-hda.h" @@ -188,6 +189,7 @@ struct IntelHDAState { /* properties */ uint32_t debug; + uint32_t msi; }; struct IntelHDAReg { @@ -268,6 +270,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d) static void intel_hda_update_irq(IntelHDAState *d) { + int msi = d->msi && msi_enabled(&d->pci); int level; intel_hda_update_int_sts(d); @@ -276,8 +279,15 @@ static void intel_hda_update_irq(IntelHDAState *d) } else { level = 0; } - dprint(d, 2, "%s: level %d\n", __FUNCTION__, level); - qemu_set_irq(d->pci.irq[0], level); + dprint(d, 2, "%s: level %d [%s]\n", __FUNCTION__, + level, msi ? "msi" : "intx"); + if (msi) { + if (level) { + msi_notify(&d->pci, 0); + } + } else { + qemu_set_irq(d->pci.irq[0], level); + } } static int intel_hda_send_command(IntelHDAState *d, uint32_t verb) @@ -1148,6 +1158,9 @@ static int intel_hda_init(PCIDevice *pci) intel_hda_mmio_write, d); pci_register_bar(&d->pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY, intel_hda_map); + if (d->msi) { + msi_init(&d->pci, 0x50, 1, true, false); + } hda_codec_bus_init(&d->pci.qdev, &d->codecs, intel_hda_response, intel_hda_xfer); @@ -1159,10 +1172,24 @@ static int intel_hda_exit(PCIDevice *pci) { IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); + if (d->msi) { + msi_uninit(&d->pci); + } cpu_unregister_io_memory(d->mmio_addr); return 0; } +static void intel_hda_write_config(PCIDevice *pci, uint32_t addr, + uint32_t val, int len) +{ + IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); + + pci_default_write_config(pci, addr, val, len); + if (d->msi) { + msi_write_config(pci, addr, val, len); + } +} + static int intel_hda_post_load(void *opaque, int version) { IntelHDAState* d = opaque; @@ -1246,8 +1273,10 @@ static PCIDeviceInfo intel_hda_info = { .qdev.reset = intel_hda_reset, .init = intel_hda_init, .exit = intel_hda_exit, + .config_write = intel_hda_write_config, .qdev.props = (Property[]) { DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0), + DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1), DEFINE_PROP_END_OF_LIST(), } }; -- cgit v1.1 From acc086837e49b44f15eff6007bb1726844df7aec Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Nov 2010 11:47:49 +0100 Subject: intel-hda: fix codec addressing. The HDA bus supports up to 15 codecs, with addresses 0 ... 14. We get that wrong in two places: * When handing out addresses we accept address 15 as valid. * The bitmasks for two registers (WAKEEN and STATESTS) don't have bit 14 set. This patch fixes it. Signed-off-by: Gerd Hoffmann Signed-off-by: malc --- hw/intel-hda.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 5e13dc3..b34b140 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -56,7 +56,7 @@ static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base) if (dev->cad == -1) { dev->cad = bus->next_cad; } - if (dev->cad > 15) + if (dev->cad >= 15) return -1; bus->next_cad = dev->cad + 1; return info->init(dev); @@ -643,15 +643,15 @@ static const struct IntelHDAReg regtab[] = { [ ICH6_REG_WAKEEN ] = { .name = "WAKEEN", .size = 2, - .wmask = 0x3fff, + .wmask = 0x7fff, .offset = offsetof(IntelHDAState, wake_en), .whandler = intel_hda_set_wake_en, }, [ ICH6_REG_STATESTS ] = { .name = "STATESTS", .size = 2, - .wmask = 0x3fff, - .wclear = 0x3fff, + .wmask = 0x7fff, + .wclear = 0x7fff, .offset = offsetof(IntelHDAState, state_sts), .whandler = intel_hda_set_state_sts, }, -- cgit v1.1 From e2553eb44e4ddd0b22124216d3dd20b6a0fecefb Mon Sep 17 00:00:00 2001 From: malc Date: Tue, 9 Nov 2010 19:14:15 +0300 Subject: Revert "intel-hda: fix codec addressing." Misses braces This reverts commit acc086837e49b44f15eff6007bb1726844df7aec. --- hw/intel-hda.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index b34b140..5e13dc3 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -56,7 +56,7 @@ static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base) if (dev->cad == -1) { dev->cad = bus->next_cad; } - if (dev->cad >= 15) + if (dev->cad > 15) return -1; bus->next_cad = dev->cad + 1; return info->init(dev); @@ -643,15 +643,15 @@ static const struct IntelHDAReg regtab[] = { [ ICH6_REG_WAKEEN ] = { .name = "WAKEEN", .size = 2, - .wmask = 0x7fff, + .wmask = 0x3fff, .offset = offsetof(IntelHDAState, wake_en), .whandler = intel_hda_set_wake_en, }, [ ICH6_REG_STATESTS ] = { .name = "STATESTS", .size = 2, - .wmask = 0x7fff, - .wclear = 0x7fff, + .wmask = 0x3fff, + .wclear = 0x3fff, .offset = offsetof(IntelHDAState, state_sts), .whandler = intel_hda_set_state_sts, }, -- cgit v1.1 From df0db2212d86e98c41774600c44cc960ddc2b68c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Nov 2010 17:28:38 +0100 Subject: intel-hda: fix codec addressing. The HDA bus supports up to 15 codecs, with addresses 0 ... 14. We get that wrong in two places: * When handing out addresses we accept address 15 as valid. * The bitmasks for two registers (WAKEEN and STATESTS) don't have bit 14 set. This patch fixes it. [ v2: codestyle: add braces ] Signed-off-by: Gerd Hoffmann Signed-off-by: malc --- hw/intel-hda.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 5e13dc3..fe31624 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -56,8 +56,9 @@ static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base) if (dev->cad == -1) { dev->cad = bus->next_cad; } - if (dev->cad > 15) + if (dev->cad >= 15) { return -1; + } bus->next_cad = dev->cad + 1; return info->init(dev); } @@ -643,15 +644,15 @@ static const struct IntelHDAReg regtab[] = { [ ICH6_REG_WAKEEN ] = { .name = "WAKEEN", .size = 2, - .wmask = 0x3fff, + .wmask = 0x7fff, .offset = offsetof(IntelHDAState, wake_en), .whandler = intel_hda_set_wake_en, }, [ ICH6_REG_STATESTS ] = { .name = "STATESTS", .size = 2, - .wmask = 0x3fff, - .wclear = 0x3fff, + .wmask = 0x7fff, + .wclear = 0x7fff, .offset = offsetof(IntelHDAState, state_sts), .whandler = intel_hda_set_state_sts, }, -- cgit v1.1 From 3e31375378f40558f1ee7c258f3cc63c85596bfc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Nov 2010 17:29:46 +0100 Subject: spice: add audio Add support for the spice audio interface. With this patch applied audio can be forwarded over the network from/to the spice client. Both recording and playback is supported. The driver is first in the driver list, but the can_be_default flag is set only in case spice is active. So if you have the spice protocol enabled the spice audio driver is the default one, otherwise whatever comes first after spice in the list. Overriding the default using QEMU_AUDIO_DRV works in any case. [ v2: audio codestyle: add spaces before open parenthesis ] [ v2: add const to silence array ] Signed-off-by: Gerd Hoffmann Cc: malc Signed-off-by: malc --- Makefile.objs | 1 + audio/audio.c | 3 + audio/audio_int.h | 1 + audio/spiceaudio.c | 327 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ui/qemu-spice.h | 1 + ui/spice-core.c | 1 + 6 files changed, 334 insertions(+) create mode 100644 audio/spiceaudio.c diff --git a/Makefile.objs b/Makefile.objs index faf485e..15569af 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -102,6 +102,7 @@ common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display. audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o audio-obj-$(CONFIG_SDL) += sdlaudio.o audio-obj-$(CONFIG_OSS) += ossaudio.o +audio-obj-$(CONFIG_SPICE) += spiceaudio.o audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o audio-obj-$(CONFIG_ALSA) += alsaaudio.o audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o diff --git a/audio/audio.c b/audio/audio.c index ad51077..ade342e 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -44,6 +44,9 @@ that we generate the list. */ static struct audio_driver *drvtab[] = { +#ifdef CONFIG_SPICE + &spice_audio_driver, +#endif CONFIG_AUDIO_DRIVERS &no_audio_driver, &wav_audio_driver diff --git a/audio/audio_int.h b/audio/audio_int.h index d8560b6..d66f2c3 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -209,6 +209,7 @@ extern struct audio_driver coreaudio_audio_driver; extern struct audio_driver dsound_audio_driver; extern struct audio_driver esd_audio_driver; extern struct audio_driver pa_audio_driver; +extern struct audio_driver spice_audio_driver; extern struct audio_driver winwave_audio_driver; extern struct mixeng_volume nominal_volume; diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c new file mode 100644 index 0000000..51ba53a --- /dev/null +++ b/audio/spiceaudio.c @@ -0,0 +1,327 @@ +#include "hw/hw.h" +#include "qemu-timer.h" +#include "ui/qemu-spice.h" + +#define AUDIO_CAP "spice" +#include "audio.h" +#include "audio_int.h" + +#define LINE_IN_SAMPLES 1024 +#define LINE_OUT_SAMPLES 1024 + +typedef struct SpiceRateCtl { + int64_t start_ticks; + int64_t bytes_sent; +} SpiceRateCtl; + +typedef struct SpiceVoiceOut { + HWVoiceOut hw; + SpicePlaybackInstance sin; + SpiceRateCtl rate; + int active; + uint32_t *frame; + uint32_t *fpos; + uint32_t fsize; +} SpiceVoiceOut; + +typedef struct SpiceVoiceIn { + HWVoiceIn hw; + SpiceRecordInstance sin; + SpiceRateCtl rate; + int active; + uint32_t samples[LINE_IN_SAMPLES]; +} SpiceVoiceIn; + +static const SpicePlaybackInterface playback_sif = { + .base.type = SPICE_INTERFACE_PLAYBACK, + .base.description = "playback", + .base.major_version = SPICE_INTERFACE_PLAYBACK_MAJOR, + .base.minor_version = SPICE_INTERFACE_PLAYBACK_MINOR, +}; + +static const SpiceRecordInterface record_sif = { + .base.type = SPICE_INTERFACE_RECORD, + .base.description = "record", + .base.major_version = SPICE_INTERFACE_RECORD_MAJOR, + .base.minor_version = SPICE_INTERFACE_RECORD_MINOR, +}; + +static void *spice_audio_init (void) +{ + if (!using_spice) { + return NULL; + } + return &spice_audio_init; +} + +static void spice_audio_fini (void *opaque) +{ + /* nothing */ +} + +static void rate_start (SpiceRateCtl *rate) +{ + memset (rate, 0, sizeof (*rate)); + rate->start_ticks = qemu_get_clock (vm_clock); +} + +static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate) +{ + int64_t now; + int64_t ticks; + int64_t bytes; + int64_t samples; + + now = qemu_get_clock (vm_clock); + ticks = now - rate->start_ticks; + bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ()); + samples = (bytes - rate->bytes_sent) >> info->shift; + if (samples < 0 || samples > 65536) { + fprintf (stderr, "Resetting rate control (%" PRId64 " samples)\n", samples); + rate_start (rate); + samples = 0; + } + rate->bytes_sent += samples << info->shift; + return samples; +} + +/* playback */ + +static int line_out_init (HWVoiceOut *hw, struct audsettings *as) +{ + SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); + struct audsettings settings; + + settings.freq = SPICE_INTERFACE_PLAYBACK_FREQ; + settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN; + settings.fmt = AUD_FMT_S16; + settings.endianness = AUDIO_HOST_ENDIANNESS; + + audio_pcm_init_info (&hw->info, &settings); + hw->samples = LINE_OUT_SAMPLES; + out->active = 0; + + out->sin.base.sif = &playback_sif.base; + qemu_spice_add_interface (&out->sin.base); + return 0; +} + +static void line_out_fini (HWVoiceOut *hw) +{ + SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); + + spice_server_remove_interface (&out->sin.base); +} + +static int line_out_run (HWVoiceOut *hw, int live) +{ + SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); + int rpos, decr; + int samples; + + if (!live) { + return 0; + } + + decr = rate_get_samples (&hw->info, &out->rate); + decr = audio_MIN (live, decr); + + samples = decr; + rpos = hw->rpos; + while (samples) { + int left_till_end_samples = hw->samples - rpos; + int len = audio_MIN (samples, left_till_end_samples); + + if (!out->frame) { + spice_server_playback_get_buffer (&out->sin, &out->frame, &out->fsize); + out->fpos = out->frame; + } + if (out->frame) { + len = audio_MIN (len, out->fsize); + hw->clip (out->fpos, hw->mix_buf + rpos, len); + out->fsize -= len; + out->fpos += len; + if (out->fsize == 0) { + spice_server_playback_put_samples (&out->sin, out->frame); + out->frame = out->fpos = NULL; + } + } + rpos = (rpos + len) % hw->samples; + samples -= len; + } + hw->rpos = rpos; + return decr; +} + +static int line_out_write (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) +{ + SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); + + switch (cmd) { + case VOICE_ENABLE: + if (out->active) { + break; + } + out->active = 1; + rate_start (&out->rate); + spice_server_playback_start (&out->sin); + break; + case VOICE_DISABLE: + if (!out->active) { + break; + } + out->active = 0; + if (out->frame) { + memset (out->fpos, 0, out->fsize << 2); + spice_server_playback_put_samples (&out->sin, out->frame); + out->frame = out->fpos = NULL; + } + spice_server_playback_stop (&out->sin); + break; + } + return 0; +} + +/* record */ + +static int line_in_init (HWVoiceIn *hw, struct audsettings *as) +{ + SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); + struct audsettings settings; + + settings.freq = SPICE_INTERFACE_RECORD_FREQ; + settings.nchannels = SPICE_INTERFACE_RECORD_CHAN; + settings.fmt = AUD_FMT_S16; + settings.endianness = AUDIO_HOST_ENDIANNESS; + + audio_pcm_init_info (&hw->info, &settings); + hw->samples = LINE_IN_SAMPLES; + in->active = 0; + + in->sin.base.sif = &record_sif.base; + qemu_spice_add_interface (&in->sin.base); + return 0; +} + +static void line_in_fini (HWVoiceIn *hw) +{ + SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); + + spice_server_remove_interface (&in->sin.base); +} + +static int line_in_run (HWVoiceIn *hw) +{ + SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); + int num_samples; + int ready; + int len[2]; + uint64_t delta_samp; + const uint32_t *samples; + + if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in (hw))) { + return 0; + } + + delta_samp = rate_get_samples (&hw->info, &in->rate); + num_samples = audio_MIN (num_samples, delta_samp); + + ready = spice_server_record_get_samples (&in->sin, in->samples, num_samples); + samples = in->samples; + if (ready == 0) { + static const uint32_t silence[LINE_IN_SAMPLES]; + samples = silence; + ready = LINE_IN_SAMPLES; + } + + num_samples = audio_MIN (ready, num_samples); + + if (hw->wpos + num_samples > hw->samples) { + len[0] = hw->samples - hw->wpos; + len[1] = num_samples - len[0]; + } else { + len[0] = num_samples; + len[1] = 0; + } + + hw->conv (hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume); + + if (len[1]) { + hw->conv (hw->conv_buf, samples + len[0], len[1], + &nominal_volume); + } + + hw->wpos = (hw->wpos + num_samples) % hw->samples; + + return num_samples; +} + +static int line_in_read (SWVoiceIn *sw, void *buf, int size) +{ + return audio_pcm_sw_read (sw, buf, size); +} + +static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) +{ + SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); + + switch (cmd) { + case VOICE_ENABLE: + if (in->active) { + break; + } + in->active = 1; + rate_start (&in->rate); + spice_server_record_start (&in->sin); + break; + case VOICE_DISABLE: + if (!in->active) { + break; + } + in->active = 0; + spice_server_record_stop (&in->sin); + break; + } + return 0; +} + +static struct audio_option audio_options[] = { + { /* end of list */ }, +}; + +static struct audio_pcm_ops audio_callbacks = { + .init_out = line_out_init, + .fini_out = line_out_fini, + .run_out = line_out_run, + .write = line_out_write, + .ctl_out = line_out_ctl, + + .init_in = line_in_init, + .fini_in = line_in_fini, + .run_in = line_in_run, + .read = line_in_read, + .ctl_in = line_in_ctl, +}; + +struct audio_driver spice_audio_driver = { + .name = "spice", + .descr = "spice audio driver", + .options = audio_options, + .init = spice_audio_init, + .fini = spice_audio_fini, + .pcm_ops = &audio_callbacks, + .max_voices_out = 1, + .max_voices_in = 1, + .voice_size_out = sizeof (SpiceVoiceOut), + .voice_size_in = sizeof (SpiceVoiceIn), +}; + +void qemu_spice_audio_init (void) +{ + spice_audio_driver.can_be_default = 1; +} diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h index 063c7dc..0e3ad9b 100644 --- a/ui/qemu-spice.h +++ b/ui/qemu-spice.h @@ -29,6 +29,7 @@ extern int using_spice; void qemu_spice_init(void); void qemu_spice_input_init(void); +void qemu_spice_audio_init(void); void qemu_spice_display_init(DisplayState *ds); int qemu_spice_add_interface(SpiceBaseInstance *sin); diff --git a/ui/spice-core.c b/ui/spice-core.c index 6a1cf17..6c404b3 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -361,6 +361,7 @@ void qemu_spice_init(void) using_spice = 1; qemu_spice_input_init(); + qemu_spice_audio_init(); qemu_free(x509_key_file); qemu_free(x509_cert_file); -- cgit v1.1 From cf2c1839a955482f2e208d7400594bf076c222f2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 11 Nov 2010 13:07:52 +0100 Subject: add copyright to spiceaudio Signed-off-by: Gerd Hoffmann Signed-off-by: malc --- audio/spiceaudio.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 51ba53a..373e4c4 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * maintained by Gerd Hoffmann + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + #include "hw/hw.h" #include "qemu-timer.h" #include "ui/qemu-spice.h" -- cgit v1.1 From 3b3d448e01ccfc6fdcb6e3d4ebf47418075e3bb4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 23 Aug 2010 12:10:46 +0200 Subject: Add new vgabios binaries to blobs list. aliguori: update VGA BIOS Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- Makefile | 5 +++-- pc-bios/vgabios-cirrus.bin | Bin 35840 -> 35840 bytes pc-bios/vgabios-stdvga.bin | Bin 0 -> 40448 bytes pc-bios/vgabios-vmware.bin | Bin 0 -> 40448 bytes pc-bios/vgabios.bin | Bin 38400 -> 40448 bytes roms/vgabios | 2 +- 6 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 pc-bios/vgabios-stdvga.bin create mode 100644 pc-bios/vgabios-vmware.bin diff --git a/Makefile b/Makefile index 02698e9..6896319 100644 --- a/Makefile +++ b/Makefile @@ -178,8 +178,9 @@ ar de en-us fi fr-be hr it lv nl pl ru th \ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr ifdef INSTALL_BLOBS -BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ -openbios-sparc32 openbios-sparc64 openbios-ppc \ +BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \ +vgabios-stdvga.bin vgabios-vmware.bin \ +ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \ gpxe-eepro100-80861209.rom \ gpxe-eepro100-80861229.rom \ pxe-e1000.bin \ diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin index 4fa8f99..424dd0c 100644 Binary files a/pc-bios/vgabios-cirrus.bin and b/pc-bios/vgabios-cirrus.bin differ diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin new file mode 100644 index 0000000..5123c5f Binary files /dev/null and b/pc-bios/vgabios-stdvga.bin differ diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin new file mode 100644 index 0000000..5e8c06b Binary files /dev/null and b/pc-bios/vgabios-vmware.bin differ diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin index fa6f815..892a2b5 100644 Binary files a/pc-bios/vgabios.bin and b/pc-bios/vgabios.bin differ diff --git a/roms/vgabios b/roms/vgabios index 6e62666..19ea12c 160000 --- a/roms/vgabios +++ b/roms/vgabios @@ -1 +1 @@ -Subproject commit 6e62666cfc19e7fd45dd0d7c3ad62fd8d0b5f67a +Subproject commit 19ea12c230ded95928ecaef0db47a82231c2e485 -- cgit v1.1 From 543f8e3468e6df32bfde8f84ac36d05a7604e082 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 6 May 2010 11:13:11 +0200 Subject: switch stdvga to pci vgabios Make stdvga provide the new vgabios binary (with pcibios support) using the PCI option rom bar. Seabios will happily load it from there. The new vga bios will also lookup the framebuffer address in pci config space, so the magic bochs lfb @ 0xe0000000 is not needed any more -> zap it. Without the patch: # dmesg | grep framebuffer vesafb: framebuffer at 0xe0000000, mapped to 0xf7e80000, using 1875k, total 8192k # lspci -vs2 00:02.0 VGA compatible controller: Technical Corp. Device 1111 (prog-if 00 [VGA controller]) Subsystem: Qumranet, Inc. Device 1100 Physical Slot: 2 Flags: fast devsel Memory at f0000000 (32-bit, prefetchable) [size=8M] Expansion ROM at [disabled] With patch applied: # dmesg | grep framebuffer vesafb: framebuffer at 0xf0000000, mapped to 0xf7e80000, using 1875k, total 8192k # lspci -vs2 00:02.0 VGA compatible controller: Technical Corp. Device 1111 (prog-if 00 [VGA controller]) Subsystem: Qumranet, Inc. Device 1100 Physical Slot: 2 Flags: fast devsel Memory at f0000000 (32-bit, prefetchable) [size=8M] Expansion ROM at f0800000 [disabled] [size=64K] cheers, Gerd Signed-off-by: Gerd Hoffmann --- hw/vga-pci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 2315f70..eef0e3c 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -103,11 +103,10 @@ static int pci_vga_initfn(PCIDevice *dev) bios_total_size <<= 1; pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size, PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map); + } else { + if (dev->romfile == NULL) + dev->romfile = qemu_strdup("vgabios-stdvga.bin"); } - - vga_init_vbe(s); - /* ROM BIOS */ - rom_add_vga(VGABIOS_FILENAME); return 0; } -- cgit v1.1 From 4eccfec4943db1106c79a01069e18dd4f463219b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 6 May 2010 11:14:11 +0200 Subject: switch vmware_vga to pci vgabios Signed-off-by: Gerd Hoffmann --- hw/vmware_vga.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 3d25c14..9337fdb 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -114,14 +114,12 @@ struct pci_vmsvga_state_s { # define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT # define SVGA_IO_MUL 1 # define SVGA_FIFO_SIZE 0x10000 -# define SVGA_MEM_BASE 0xe0000000 # define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2 #else # define SVGA_ID SVGA_ID_1 # define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT # define SVGA_IO_MUL 4 # define SVGA_FIFO_SIZE 0x10000 -# define SVGA_MEM_BASE 0xe0000000 # define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA #endif @@ -1219,10 +1217,6 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size) vga_init(&s->vga); vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga); - vga_init_vbe(&s->vga); - - rom_add_vga(VGABIOS_FILENAME); - vmsvga_reset(s); } @@ -1320,6 +1314,7 @@ static PCIDeviceInfo vmsvga_info = { .qdev.size = sizeof(struct pci_vmsvga_state_s), .qdev.vmsd = &vmstate_vmware_vga, .init = pci_vmsvga_initfn, + .romfile = "vgabios-vmware.bin", }; static void vmsvga_register(void) -- cgit v1.1 From 788954270d339b4b271e1a537a481e7068ba3591 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 15 Oct 2010 11:45:13 +0200 Subject: more stdvga cleanups. video.x is gone now. It was the only user of the vga bios_offset + bios_size logic. Zap it. Signed-off-by: Gerd Hoffmann --- hw/mips_malta.c | 2 +- hw/pc.c | 2 +- hw/pc.h | 3 +-- hw/ppc_newworld.c | 2 +- hw/ppc_oldworld.c | 2 +- hw/ppc_prep.c | 2 +- hw/sun4u.c | 2 +- hw/vga-pci.c | 42 ++++++++---------------------------------- hw/vga.c | 2 -- hw/vga_int.h | 2 -- 10 files changed, 15 insertions(+), 46 deletions(-) diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 8026071..6be8aa7 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -977,7 +977,7 @@ void mips_malta_init (ram_addr_t ram_size, } else if (vmsvga_enabled) { pci_vmsvga_init(pci_bus); } else if (std_vga_enabled) { - pci_vga_init(pci_bus, 0, 0); + pci_vga_init(pci_bus); } } diff --git a/hw/pc.c b/hw/pc.c index 69b13bf..0e44df8 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -993,7 +993,7 @@ void pc_vga_init(PCIBus *pci_bus) fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__); } else if (std_vga_enabled) { if (pci_bus) { - pci_vga_init(pci_bus, 0, 0); + pci_vga_init(pci_bus); } else { isa_vga_init(); } diff --git a/hw/pc.h b/hw/pc.h index 63b0249..6852790 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -154,8 +154,7 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; int isa_vga_init(void); -int pci_vga_init(PCIBus *bus, - unsigned long vga_bios_offset, int vga_bios_size); +int pci_vga_init(PCIBus *bus); int isa_vga_mm_init(target_phys_addr_t vram_base, target_phys_addr_t ctrl_base, int it_shift); diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 4369337..305b2d4 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -316,7 +316,7 @@ static void ppc_core99_init (ram_addr_t ram_size, machine_arch = ARCH_MAC99; } /* init basic PC hardware */ - pci_vga_init(pci_bus, 0, 0); + pci_vga_init(pci_bus); escc_mem_index = escc_init(0x80013000, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index a2f9ddf..5efc93d 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -227,7 +227,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, } pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs); pci_bus = pci_grackle_init(0xfec00000, pic); - pci_vga_init(pci_bus, 0, 0); + pci_vga_init(pci_bus); escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index a6915f7..b1f9cc7 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -694,7 +694,7 @@ static void ppc_prep_init (ram_addr_t ram_size, cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory); /* init basic PC hardware */ - pci_vga_init(pci_bus, 0, 0); + pci_vga_init(pci_bus); // openpic = openpic_init(0x00000000, 0xF0000000, 1); // pit = pit_init(0x40, i8259[0]); rtc_init(2000, NULL); diff --git a/hw/sun4u.c b/hw/sun4u.c index 45a46d6..5292ac6 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -767,7 +767,7 @@ static void sun4uv_init(ram_addr_t RAM_size, pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2, &pci_bus3); isa_mem_base = APB_PCI_IO_BASE; - pci_vga_init(pci_bus, 0, 0); + pci_vga_init(pci_bus); // XXX Should be pci_bus3 pci_ebus_init(pci_bus, -1); diff --git a/hw/vga-pci.c b/hw/vga-pci.c index eef0e3c..b09789c 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -52,14 +52,11 @@ static void vga_map(PCIDevice *pci_dev, int region_num, { PCIVGAState *d = (PCIVGAState *)pci_dev; VGACommonState *s = &d->vga; - if (region_num == PCI_ROM_SLOT) { - cpu_register_physical_memory(addr, s->bios_size, s->bios_offset); - } else { - cpu_register_physical_memory(addr, s->vram_size, s->vram_offset); - s->map_addr = addr; - s->map_end = addr + s->vram_size; - vga_dirty_log_start(s); - } + + cpu_register_physical_memory(addr, s->vram_size, s->vram_offset); + s->map_addr = addr; + s->map_end = addr + s->vram_size; + vga_dirty_log_start(s); } static void pci_vga_write_config(PCIDevice *d, @@ -95,31 +92,12 @@ static int pci_vga_initfn(PCIDevice *dev) pci_register_bar(&d->dev, 0, VGA_RAM_SIZE, PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map); - if (s->bios_size) { - unsigned int bios_total_size; - /* must be a power of two */ - bios_total_size = 1; - while (bios_total_size < s->bios_size) - bios_total_size <<= 1; - pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size, - PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map); - } else { - if (dev->romfile == NULL) - dev->romfile = qemu_strdup("vgabios-stdvga.bin"); - } return 0; } -int pci_vga_init(PCIBus *bus, - unsigned long vga_bios_offset, int vga_bios_size) +int pci_vga_init(PCIBus *bus) { - PCIDevice *dev; - - dev = pci_create(bus, -1, "VGA"); - qdev_prop_set_uint32(&dev->qdev, "bios-offset", vga_bios_offset); - qdev_prop_set_uint32(&dev->qdev, "bios-size", vga_bios_size); - qdev_init_nofail(&dev->qdev); - + pci_create_simple(bus, -1, "VGA"); return 0; } @@ -129,11 +107,7 @@ static PCIDeviceInfo vga_info = { .qdev.vmsd = &vmstate_vga_pci, .init = pci_vga_initfn, .config_write = pci_vga_write_config, - .qdev.props = (Property[]) { - DEFINE_PROP_HEX32("bios-offset", PCIVGAState, vga.bios_offset, 0), - DEFINE_PROP_HEX32("bios-size", PCIVGAState, vga.bios_size, 0), - DEFINE_PROP_END_OF_LIST(), - } + .romfile = "vgabios-stdvga.bin", }; static void vga_register(void) diff --git a/hw/vga.c b/hw/vga.c index 966185e..c057f4f 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1934,8 +1934,6 @@ void vga_common_reset(VGACommonState *s) s->map_addr = 0; s->map_end = 0; s->lfb_vram_mapped = 0; - s->bios_offset = 0; - s->bios_size = 0; s->sr_index = 0; memset(s->sr, '\0', sizeof(s->sr)); s->gr_index = 0; diff --git a/hw/vga_int.h b/hw/vga_int.h index 6a46a43..bc1327f 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -112,8 +112,6 @@ typedef struct VGACommonState { uint32_t map_addr; uint32_t map_end; uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */ - uint32_t bios_offset; - uint32_t bios_size; uint32_t latch; uint8_t sr_index; uint8_t sr[256]; -- cgit v1.1 From 43849424cff82803011fad21074531a1101e514e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 27 Oct 2010 20:03:43 +0200 Subject: tap: clear vhost_net backend on cleanup Frontends calling tap_get_vhost_net get an invalid pointer after the peer backend has been deleted. Jason Wang reports this leading to a crash in ack_features when we remove the vhost-net bakend of a virtio nic. The fix is simply to clear the backend pointer. Signed-off-by: Michael S. Tsirkin --- net/tap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/tap.c b/net/tap.c index 4afb314..937d942 100644 --- a/net/tap.c +++ b/net/tap.c @@ -279,6 +279,7 @@ static void tap_cleanup(VLANClientState *nc) if (s->vhost_net) { vhost_net_cleanup(s->vhost_net); + s->vhost_net = NULL; } qemu_purge_queued_packets(nc); -- cgit v1.1 From f6584ee20338a74ef3b05b38b8f9dc5e7a7276a6 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Sun, 24 Oct 2010 14:27:55 +0200 Subject: Add support for async page fault to qemu Add save/restore of MSR for migration and cpuid bit. Signed-off-by: Gleb Natapov Signed-off-by: Marcelo Tosatti --- target-i386/cpu.h | 1 + target-i386/cpuid.c | 2 +- target-i386/kvm.c | 14 ++++++++++++++ target-i386/machine.c | 26 ++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 2440d65..06e40f3 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -681,6 +681,7 @@ typedef struct CPUX86State { #endif uint64_t system_time_msr; uint64_t wall_clock_msr; + uint64_t async_pf_en_msr; uint64_t tsc; diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 650a719..165045e 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -73,7 +73,7 @@ static const char *ext3_feature_name[] = { }; static const char *kvm_feature_name[] = { - "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, NULL, NULL, NULL, NULL, + "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, "kvm_asyncpf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/target-i386/kvm.c b/target-i386/kvm.c index ae0a034..7dfc357 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -162,6 +162,9 @@ struct kvm_para_features { #ifdef KVM_CAP_PV_MMU { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, #endif +#ifdef KVM_CAP_ASYNC_PF + { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF }, +#endif { -1, -1 } }; @@ -838,6 +841,9 @@ static int kvm_put_msrs(CPUState *env, int level) kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME, env->system_time_msr); kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr); +#ifdef KVM_CAP_ASYNC_PF + kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr); +#endif } #ifdef KVM_CAP_MCE if (env->mcg_cap) { @@ -1064,6 +1070,9 @@ static int kvm_get_msrs(CPUState *env) #endif msrs[n++].index = MSR_KVM_SYSTEM_TIME; msrs[n++].index = MSR_KVM_WALL_CLOCK; +#ifdef KVM_CAP_ASYNC_PF + msrs[n++].index = MSR_KVM_ASYNC_PF_EN; +#endif #ifdef KVM_CAP_MCE if (env->mcg_cap) { @@ -1135,6 +1144,11 @@ static int kvm_get_msrs(CPUState *env) } #endif break; +#ifdef KVM_CAP_ASYNC_PF + case MSR_KVM_ASYNC_PF_EN: + env->async_pf_en_msr = msrs[i].data; + break; +#endif } } diff --git a/target-i386/machine.c b/target-i386/machine.c index 5f8376c..d78eceb 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -373,6 +373,24 @@ static int cpu_post_load(void *opaque, int version_id) return 0; } +static bool async_pf_msr_needed(void *opaque) +{ + CPUState *cpu = opaque; + + return cpu->async_pf_en_msr != 0; +} + +static const VMStateDescription vmstate_async_pf_msr = { + .name = "cpu/async_pf_msr", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT64(async_pf_en_msr, CPUState), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_cpu = { .name = "cpu", .version_id = CPU_SAVE_VERSION, @@ -475,6 +493,14 @@ static const VMStateDescription vmstate_cpu = { VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUState, CPU_NB_REGS, 12), VMSTATE_END_OF_LIST() /* The above list is not sorted /wrt version numbers, watch out! */ + }, + .subsections = (VMStateSubsection []) { + { + .vmsd = &vmstate_async_pf_msr, + .needed = async_pf_msr_needed, + } , { + /* empty */ + } } }; -- cgit v1.1 From 27a6375de3edece2e5d115847d54c01e52331f7e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 31 Oct 2010 19:06:47 +0200 Subject: tap: make set_offload a nop after netdev cleanup virtio-net expects set_offload to succeed after peer cleanup. Since we don't have an open fd anymore, make it so. Fixes warning about the failure of offload setting. Reported-by: Jason Wang Signed-off-by: Michael S. Tsirkin --- net/tap.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/tap.c b/net/tap.c index 937d942..eada34a 100644 --- a/net/tap.c +++ b/net/tap.c @@ -269,8 +269,11 @@ void tap_set_offload(VLANClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo) { TAPState *s = DO_UPCAST(TAPState, nc, nc); + if (s->fd < 0) { + return; + } - return tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo); + tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo); } static void tap_cleanup(VLANClientState *nc) @@ -290,6 +293,7 @@ static void tap_cleanup(VLANClientState *nc) tap_read_poll(s, 0); tap_write_poll(s, 0); close(s->fd); + s->fd = -1; } static void tap_poll(VLANClientState *nc, bool enable) -- cgit v1.1 From 1f892feb37dabedbb2492c6b499b0c1b22631a1f Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 5 Nov 2010 14:52:08 -0600 Subject: e1000: Fix TCP checksum overflow with TSO When adding the length to the pseudo header, we're not properly accounting for overflow. From: Mark Wu Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin --- hw/e1000.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/e1000.c b/hw/e1000.c index 532efdc..677165f 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -384,9 +384,12 @@ xmit_seg(E1000State *s) } else // UDP cpu_to_be16wu((uint16_t *)(tp->data+css+4), len); if (tp->sum_needed & E1000_TXD_POPTS_TXSM) { + unsigned int phsum; // add pseudo-header length before checksum calculation sp = (uint16_t *)(tp->data + tp->tucso); - cpu_to_be16wu(sp, be16_to_cpup(sp) + len); + phsum = be16_to_cpup(sp) + len; + phsum = (phsum >> 16) + (phsum & 0xffff); + cpu_to_be16wu(sp, phsum); } tp->tso_frames++; } -- cgit v1.1 From a6a9239cd87d1bcdade909cf71413686fb70f8d0 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 4 Oct 2010 15:53:11 -0600 Subject: PCI: Bus number from the bridge, not the device pcibus_dev_print() was erroneously retrieving the device bus number from the secondary bus number offset of the device instead of the bridge above the device. This ends of landing in the 2nd byte of the 3rd BAR for devices, which thankfully is usually zero. Note: pcibus_get_dev_path() copied this code, inheriting the same bug. pcibus_get_dev_path() is used for ramblock naming, so changing it can effect migration. However, I've only seen this byte be non-zero for an assigned device, which can't migrate anyway, so hopefully we won't run into any issues. This patch does not touch pcibus_get_dev_path, as bus number is guest assigned for nested buses, so using it for migration is broken anyway. Fix it properly later. Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 962886e..8f6fcf8 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1806,8 +1806,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent) monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, " "pci id %04x:%04x (sub %04x:%04x)\n", - indent, "", ctxt, - d->config[PCI_SECONDARY_BUS], + indent, "", ctxt, pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn), pci_get_word(d->config + PCI_VENDOR_ID), pci_get_word(d->config + PCI_DEVICE_ID), -- cgit v1.1 From 4cff0a5994d0300e6e77e90d3354aa517a120539 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Nov 2010 16:21:35 +0900 Subject: pci: allow hotplug removal of cold-plugged devices This patch fixes hot unplug of cold plugged devices (those present at system start), which got broken by 5beb8ad503c88a76f2b8106c3b74b4ce485a60e1 . Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin Acked-by: Cam Macdonell Tested-by: Cam Macdonell Reported-by: Cam Macdonell . --- hw/acpi_piix4.c | 14 ++++++++++---- hw/pci.c | 10 +++++++--- hw/pci.h | 10 +++++++++- hw/pcie.c | 10 ++++++---- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 66c7885..f549089 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -585,7 +585,8 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val) PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val); } -static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state); +static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, + PCIHotplugState state); static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s) { @@ -615,18 +616,23 @@ static void disable_device(PIIX4PMState *s, int slot) s->pci0_status.down |= (1 << slot); } -static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state) +static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, + PCIHotplugState state) { int slot = PCI_SLOT(dev->devfn); PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, DO_UPCAST(PCIDevice, qdev, qdev)); - if (!dev->qdev.hotplugged) + /* Don't send event when device is enabled during qemu machine creation: + * it is present on boot, no hotplug event is necessary. We do send an + * event when the device is disabled later. */ + if (state == PCI_COLDPLUG_ENABLED) { return 0; + } s->pci0_status.up = 0; s->pci0_status.down = 0; - if (state) { + if (state == PCI_HOTPLUG_ENABLED) { enable_device(s, slot); } else { disable_device(s, slot); diff --git a/hw/pci.c b/hw/pci.c index 8f6fcf8..438c0d1 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1558,8 +1558,11 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base) pci_add_option_rom(pci_dev); if (bus->hotplug) { - /* lower layer must check qdev->hotplugged */ - rc = bus->hotplug(bus->hotplug_qdev, pci_dev, 1); + /* Let buses differentiate between hotplug and when device is + * enabled during qemu machine creation. */ + rc = bus->hotplug(bus->hotplug_qdev, pci_dev, + qdev->hotplugged ? PCI_HOTPLUG_ENABLED: + PCI_COLDPLUG_ENABLED); if (rc != 0) { int r = pci_unregister_device(&pci_dev->qdev); assert(!r); @@ -1573,7 +1576,8 @@ static int pci_unplug_device(DeviceState *qdev) { PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev); - return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, 0); + return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, + PCI_HOTPLUG_DISABLED); } void pci_qdev_register(PCIDeviceInfo *info) diff --git a/hw/pci.h b/hw/pci.h index 7100804..09b3e4c 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -214,7 +214,15 @@ int pci_device_load(PCIDevice *s, QEMUFile *f); typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); -typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev, int state); + +typedef enum { + PCI_HOTPLUG_DISABLED, + PCI_HOTPLUG_ENABLED, + PCI_COLDPLUG_ENABLED, +} PCIHotplugState; + +typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev, + PCIHotplugState state); void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, const char *name, int devfn_min); PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min); diff --git a/hw/pcie.c b/hw/pcie.c index 35918f7..f461c1c 100644 --- a/hw/pcie.c +++ b/hw/pcie.c @@ -192,14 +192,16 @@ static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event) } static int pcie_cap_slot_hotplug(DeviceState *qdev, - PCIDevice *pci_dev, int state) + PCIDevice *pci_dev, PCIHotplugState state) { PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev); uint8_t *exp_cap = d->config + d->exp.exp_cap; uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA); - if (!pci_dev->qdev.hotplugged) { - assert(state); /* this case only happens at machine creation. */ + /* Don't send event when device is enabled during qemu machine creation: + * it is present on boot, no hotplug event is necessary. We do send an + * event when the device is disabled later. */ + if (state == PCI_COLDPLUG_ENABLED) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); return 0; @@ -219,7 +221,7 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev, */ assert(PCI_FUNC(pci_dev->devfn) == 0); - if (state) { + if (state == PCI_HOTPLUG_ENABLED) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); -- cgit v1.1 From b538e53ee7e8b9e2920d3286b480276cef209fd4 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 5 Nov 2010 16:01:29 -0600 Subject: apic: Don't iterate past last used apic local_apics are allocated sequentially and never removed, so we can stop any iterations that go to MAX_APICS as soon as we hit the first NULL. Looking at a small guest running a virtio-net workload with oprofile, this drops apic_get_delivery_bitmask() from #3 in the profile to down in the noise. Signed-off-by: Alex Williamson Signed-off-by: Anthony Liguori --- hw/apic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/apic.c b/hw/apic.c index 63d62c7..5f4a87c 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -437,6 +437,8 @@ static int apic_find_dest(uint8_t dest) apic = local_apics[i]; if (apic && apic->id == dest) return i; + if (!apic) + break; } return -1; @@ -472,6 +474,8 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, set_bit(deliver_bitmask, i); } } + } else { + break; } } } -- cgit v1.1 From 9696846600cac4bd0dfd6835e45e69d25ec2b11e Mon Sep 17 00:00:00 2001 From: Adam Lackorzynski Date: Thu, 4 Nov 2010 23:22:15 +0100 Subject: multiboot: Prevent loading of x86_64 images A via -kernel supplied x86_64 ELF image is being started in 32bit mode. Detect and exit if a 64bit image has been supplied. Signed-off-by: Adam Lackorzynski Acked-by: Alexander Graf Signed-off-by: Anthony Liguori --- hw/multiboot.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/multiboot.c b/hw/multiboot.c index f9097a2..e710bbb 100644 --- a/hw/multiboot.c +++ b/hw/multiboot.c @@ -171,6 +171,12 @@ int load_multiboot(void *fw_cfg, uint64_t elf_low, elf_high; int kernel_size; fclose(f); + + if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) { + fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n"); + exit(1); + } + kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry, &elf_low, &elf_high, 0, ELF_MACHINE, 0); if (kernel_size < 0) { -- cgit v1.1 From 4addb1127f6327c7ebcbd150a6b589e7677adc92 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 8 Nov 2010 19:33:07 +0000 Subject: Add a DTrace tracing backend targetted for SystemTAP compatability This introduces a new tracing backend that targets the SystemTAP implementation of DTrace userspace tracing. The core functionality should be applicable and standard across any DTrace implementation on Solaris, OS-X, *BSD, but the Makefile rules will likely need some small additional changes to cope with OS specific build requirements. This backend builds a little differently from the other tracing backends. Specifically there is no 'trace.c' file, because the 'dtrace' command line tool generates a '.o' file directly from the dtrace probe definition file. The probe definition is usually named with a '.d' extension but QEMU uses '.d' files for its external makefile dependancy tracking, so this uses '.dtrace' as the extension for the probe definition file. The 'tracetool' program gains the ability to generate a trace.h file for DTrace, and also to generate the trace.d file containing the dtrace probe definition. Example usage of a dtrace probe in systemtap looks like: probe process("qemu").mark("qemu_malloc") { printf("Malloc %d %p\n", $arg1, $arg2); } * .gitignore: Ignore trace-dtrace.* * Makefile: Extra rules for generating DTrace files * Makefile.obj: Don't build trace.o for DTrace, use trace-dtrace.o generated by 'dtrace' instead * tracetool: Support for generating DTrace data files Signed-off-by: Daniel P. Berrange Signed-off-by: Anthony Liguori --- .gitignore | 2 + Makefile | 23 ++++++++++++ Makefile.objs | 4 ++ configure | 14 ++++++- tracetool | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 148 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index a43e4d1..3efb4ec 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ config-host.* config-target.* trace.h trace.c +trace-dtrace.h +trace-dtrace.dtrace *-timestamp *-softmmu *-darwin-user diff --git a/Makefile b/Makefile index 6896319..747e47c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ # Makefile for QEMU. GENERATED_HEADERS = config-host.h trace.h qemu-options.def +ifeq ($(TRACE_BACKEND),dtrace) +GENERATED_HEADERS += trace-dtrace.h +endif ifneq ($(wildcard config-host.mak),) # Put the all: rule here so that config-host.mak can contain dependencies. @@ -108,7 +111,11 @@ ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS) bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS) +ifeq ($(TRACE_BACKEND),dtrace) +trace.h: trace.h-timestamp trace-dtrace.h +else trace.h: trace.h-timestamp +endif trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h @@ -120,6 +127,20 @@ trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak trace.o: trace.c $(GENERATED_HEADERS) +trace-dtrace.h: trace-dtrace.dtrace + $(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h") + +# Normal practice is to name DTrace probe file with a '.d' extension +# but that gets picked up by QEMU's Makefile as an external dependancy +# rule file. So we use '.dtrace' instead +trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp +trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak + $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace") + @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace + +trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) + $(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o") + simpletrace.o: simpletrace.c $(GENERATED_HEADERS) version.o: $(SRC_PATH)/version.rc config-host.mak @@ -157,6 +178,8 @@ clean: 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 rm -f qemu-img-cmds.h 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 $(MAKE) -C tests clean for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ diff --git a/Makefile.objs b/Makefile.objs index 15569af..23b17ce 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -286,11 +286,15 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o ###################################################################### # trace +ifeq ($(TRACE_BACKEND),dtrace) +trace-obj-y = trace-dtrace.o +else trace-obj-y = trace.o ifeq ($(TRACE_BACKEND),simple) trace-obj-y += simpletrace.o user-obj-y += qemu-timer-common.o endif +endif vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/configure b/configure index 7025d2b..f8dad3e 100755 --- a/configure +++ b/configure @@ -929,7 +929,7 @@ echo " --enable-docs enable documentation build" echo " --disable-docs disable documentation build" echo " --disable-vhost-net disable vhost-net acceleration support" echo " --enable-vhost-net enable vhost-net acceleration support" -echo " --trace-backend=B Trace backend nop simple ust" +echo " --trace-backend=B Trace backend nop simple ust dtrace" echo " --trace-file=NAME Full PATH,NAME of file to store traces" echo " Default:trace-" echo " --disable-spice disable spice" @@ -2193,6 +2193,18 @@ EOF exit 1 fi fi + +########################################## +# For 'dtrace' backend, test if 'dtrace' command is present +if test "$trace_backend" = "dtrace"; then + if ! has 'dtrace' ; then + echo + echo "Error: dtrace command is not found in PATH $PATH" + echo + exit 1 + fi +fi + ########################################## # End of CC checks # After here, no more $cc or $ld runs diff --git a/tracetool b/tracetool index 7010858..5b6636a 100755 --- a/tracetool +++ b/tracetool @@ -20,10 +20,12 @@ Backends: --nop Tracing disabled --simple Simple built-in backend --ust LTTng User Space Tracing backend + --dtrace DTrace/SystemTAP backend Output formats: -h Generate .h file -c Generate .c file + -d Generate .d file (DTrace only) EOF exit 1 } @@ -46,8 +48,9 @@ get_args() # Get the argument name list of a trace event get_argnames() { - local nfields field name + local nfields field name sep nfields=0 + sep="$2" for field in $(get_args "$1"); do nfields=$((nfields + 1)) @@ -58,7 +61,7 @@ get_argnames() name=${field%,} test "$field" = "$name" && continue - printf "%s" "$name, " + printf "%s%s " $name $sep done # Last argument name @@ -73,7 +76,7 @@ get_argc() { local name argc argc=0 - for name in $(get_argnames "$1"); do + for name in $(get_argnames "$1", ","); do argc=$((argc + 1)) done echo $argc @@ -154,7 +157,7 @@ EOF cast_args_to_uint64_t() { local arg - for arg in $(get_argnames "$1"); do + for arg in $(get_argnames "$1", ","); do printf "%s" "(uint64_t)(uintptr_t)$arg" done } @@ -247,7 +250,7 @@ linetoh_ust() local name args argnames name=$(get_name "$1") args=$(get_args "$1") - argnames=$(get_argnames "$1") + argnames=$(get_argnames "$1", ",") cat < Date: Mon, 8 Nov 2010 19:33:08 +0000 Subject: Add support for generating a systemtap tapset static probes This introduces generation of a qemu.stp/qemu-system-XXX.stp files which provides tapsets with friendly names for static probes & their arguments. Instead of probe process("qemu").mark("qemu_malloc") { printf("Malloc %d %p\n", $arg1, $arg2); } It is now possible todo probe qemu.system.i386.qemu_malloc { printf("Malloc %d %p\n", size, ptr); } There is one tapset defined per target arch. * Makefile: Generate a qemu.stp file for systemtap * tracetool: Support for generating systemtap tapsets Signed-off-by: Daniel P. Berrange Signed-off-by: Anthony Liguori --- Makefile.target | 19 +++++++++++- configure | 7 +++++ tracetool | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/Makefile.target b/Makefile.target index 91e6e74..a5e6410 100644 --- a/Makefile.target +++ b/Makefile.target @@ -40,7 +40,20 @@ kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS) config-target.h: config-target.h-timestamp config-target.h-timestamp: config-target.mak -all: $(PROGS) +ifdef CONFIG_SYSTEMTAP_TRACE +trace: $(QEMU_PROG).stp + +$(QEMU_PROG).stp: + $(call quiet-command,sh $(SRC_PATH)/tracetool \ + --$(TRACE_BACKEND) \ + --bindir $(bindir) \ + --target $(TARGET_ARCH) \ + -s < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") +else +trace: +endif + +all: $(PROGS) trace # Dummy command so that make thinks it has done something @true @@ -348,6 +361,10 @@ ifneq ($(STRIP),) $(STRIP) $(patsubst %,"$(DESTDIR)$(bindir)/%",$(PROGS)) endif endif +ifdef CONFIG_SYSTEMTAP_TRACE + $(INSTALL_DIR) "$(DESTDIR)$(datadir)/../systemtap/tapset" + $(INSTALL_DATA) $(QEMU_PROG).stp "$(DESTDIR)$(datadir)/../systemtap/tapset" +endif # Include automatically generated dependency files -include $(wildcard *.d */*.d) diff --git a/configure b/configure index f8dad3e..e560f87 100755 --- a/configure +++ b/configure @@ -2192,6 +2192,10 @@ EOF echo exit 1 fi + trace_backend_stap="no" + if has 'stap' ; then + trace_backend_stap="yes" + fi fi ########################################## @@ -2645,6 +2649,9 @@ fi if test "$trace_backend" = "simple"; then trace_file="\"$trace_file-%u\"" fi +if test "$trace_backend" = "dtrace" -a "$trace_backend_stap" = "yes" ; then + echo "CONFIG_SYSTEMTAP_TRACE=y" >> $config_host_mak +fi echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak echo "TOOLS=$tools" >> $config_host_mak diff --git a/tracetool b/tracetool index 5b6636a..d797ab7 100755 --- a/tracetool +++ b/tracetool @@ -26,6 +26,12 @@ Output formats: -h Generate .h file -c Generate .c file -d Generate .d file (DTrace only) + -s Generate .stp file (DTrace with SystemTAP only) + +Options: + --bindir [bindir] QEMU binary install location + --target [arch] QEMU target architecture + EOF exit 1 } @@ -390,6 +396,54 @@ linetod_end_dtrace() EOF } +linetos_begin_dtrace() +{ + return +} + +linetos_dtrace() +{ + local name args arglist state + name=$(get_name "$1") + args=$(get_args "$1") + arglist=$(get_argnames "$1", "") + state=$(get_state "$1") + if [ "$state" = "0" ] ; then + name=${name##disable } + fi + + if [ "$target" = "i386" ] + then + binary="qemu" + else + binary="qemu-system-$target" + fi + + # Define prototype for probe arguments + cat < Date: Tue, 9 Nov 2010 09:36:53 +0200 Subject: Out off array access in usb-net Properly check array bounds before accessing array element. Signed-off-by: Gleb Natapov Signed-off-by: Anthony Liguori --- hw/usb-net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb-net.c b/hw/usb-net.c index 70f9263..58c672f 100644 --- a/hw/usb-net.c +++ b/hw/usb-net.c @@ -1142,7 +1142,7 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value, break; default: - if (usb_net_stringtable[value & 0xff]) { + if (ARRAY_SIZE(usb_net_stringtable) > (value & 0xff)) { ret = set_usb_string(data, usb_net_stringtable[value & 0xff]); break; -- cgit v1.1 From 43ad7e3e986dea82831debad68e68cff552b6746 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 11 Nov 2010 16:10:04 +0100 Subject: Add missing braces This patch adds missing braces around if/else statements that call macros which are likely to result in errors if the macro is changed. It also makes the code comply better with CODING_STYLE. Signed-off-by: Jes Sorensen Signed-off-by: Anthony Liguori --- hw/e1000.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index 677165f..7811699 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -447,9 +447,10 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) // data descriptor tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8; tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0; - } else + } else { // legacy descriptor tp->cptse = 0; + } if (vlan_enabled(s) && is_vlan_txd(txd_lower) && (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) { @@ -685,8 +686,9 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size) (void *)(buf + vlan_offset), size); desc.length = cpu_to_le16(size + fcs_len(s)); desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM; - } else // as per intel docs; skip descriptors with null buf addr + } else { // as per intel docs; skip descriptors with null buf addr DBGOUT(RX, "Null RX descriptor!!\n"); + } cpu_physical_memory_write(base, (void *)&desc, sizeof(desc)); if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) @@ -858,13 +860,14 @@ e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) #ifdef TARGET_WORDS_BIGENDIAN val = bswap32(val); #endif - if (index < NWRITEOPS && macreg_writeops[index]) + if (index < NWRITEOPS && macreg_writeops[index]) { macreg_writeops[index](s, index, val); - else if (index < NREADOPS && macreg_readops[index]) + } else if (index < NREADOPS && macreg_readops[index]) { DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val); - else + } else { DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08x\n", index<<2, val); + } } static void -- cgit v1.1 From 0f5160d1ea8bcd69d539f8a87a1b350d98fa5d52 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 10 Nov 2010 10:06:23 +0100 Subject: usb-linux: Store devpath into USBHostDevice when usb_fs_type == USB_FS_SYS This allows us to recreate the sysfspath used during scanning later (which will be used in a later patch in this series). Signed-off-by: Anthony Liguori --- usb-linux.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/usb-linux.c b/usb-linux.c index c3c38ec..0b154c2 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -62,8 +62,8 @@ struct usb_ctrlrequest { uint16_t wLength; }; -typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id, - int vendor_id, int product_id, +typedef int USBScanFunc(void *opaque, int bus_num, int addr, int devpath, + int class_id, int vendor_id, int product_id, const char *product_name, int speed); //#define DEBUG @@ -141,6 +141,7 @@ typedef struct USBHostDevice { /* Host side address */ int bus_num; int addr; + int devpath; struct USBAutoFilter match; QTAILQ_ENTRY(USBHostDevice) next; @@ -885,7 +886,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s) } static int usb_host_open(USBHostDevice *dev, int bus_num, - int addr, const char *prod_name) + int addr, int devpath, const char *prod_name) { int fd = -1, ret; struct usbdevfs_connectinfo ci; @@ -911,6 +912,7 @@ static int usb_host_open(USBHostDevice *dev, int bus_num, dev->bus_num = bus_num; dev->addr = addr; + dev->devpath = devpath; dev->fd = fd; /* read the device description */ @@ -1173,7 +1175,7 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func) if (line[0] == 'T' && line[1] == ':') { if (device_count && (vendor_id || product_id)) { /* New device. Add the previously discovered device. */ - ret = func(opaque, bus_num, addr, class_id, vendor_id, + ret = func(opaque, bus_num, addr, 0, class_id, vendor_id, product_id, product_name, speed); if (ret) { goto the_end; @@ -1226,7 +1228,7 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func) } if (device_count && (vendor_id || product_id)) { /* Add the last device. */ - ret = func(opaque, bus_num, addr, class_id, vendor_id, + ret = func(opaque, bus_num, addr, 0, class_id, vendor_id, product_id, product_name, speed); } the_end: @@ -1275,7 +1277,7 @@ static int usb_host_scan_sys(void *opaque, USBScanFunc *func) { DIR *dir = NULL; char line[1024]; - int bus_num, addr, speed, class_id, product_id, vendor_id; + int bus_num, addr, devpath, speed, class_id, product_id, vendor_id; int ret = 0; char product_name[512]; struct dirent *de; @@ -1292,7 +1294,9 @@ static int usb_host_scan_sys(void *opaque, USBScanFunc *func) if (!strncmp(de->d_name, "usb", 3)) { tmpstr += 3; } - bus_num = atoi(tmpstr); + if (sscanf(tmpstr, "%d-%d", &bus_num, &devpath) < 1) { + goto the_end; + } if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) { goto the_end; @@ -1343,7 +1347,7 @@ static int usb_host_scan_sys(void *opaque, USBScanFunc *func) speed = USB_SPEED_FULL; } - ret = func(opaque, bus_num, addr, class_id, vendor_id, + ret = func(opaque, bus_num, addr, devpath, class_id, vendor_id, product_id, product_name, speed); if (ret) { goto the_end; @@ -1434,7 +1438,7 @@ static int usb_host_scan(void *opaque, USBScanFunc *func) static QEMUTimer *usb_auto_timer; -static int usb_host_auto_scan(void *opaque, int bus_num, int addr, +static int usb_host_auto_scan(void *opaque, int bus_num, int addr, int devpath, int class_id, int vendor_id, int product_id, const char *product_name, int speed) { @@ -1470,7 +1474,7 @@ static int usb_host_auto_scan(void *opaque, int bus_num, int addr, } DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr); - usb_host_open(s, bus_num, addr, product_name); + usb_host_open(s, bus_num, addr, devpath, product_name); } return 0; @@ -1630,7 +1634,7 @@ static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id, } static int usb_host_info_device(void *opaque, int bus_num, int addr, - int class_id, + int devpath, int class_id, int vendor_id, int product_id, const char *product_name, int speed) -- cgit v1.1 From 71d71bbdeb39544ac1602c5e307d9e14c78f9d5d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 10 Nov 2010 10:06:24 +0100 Subject: usb-linux: introduce a usb_linux_get_configuration function The next patch in this series introduces multiple ways to get the configuration dependent upon usb_fs_type, it is cleaner to put this into its own function. Signed-off-by: Anthony Liguori --- usb-linux.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/usb-linux.c b/usb-linux.c index 0b154c2..111fe1c 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -775,13 +775,11 @@ static int usb_host_handle_packet(USBDevice *s, USBPacket *p) } } -/* returns 1 on problem encountered or 0 for success */ -static int usb_linux_update_endp_table(USBHostDevice *s) +static int usb_linux_get_configuration(USBHostDevice *s) { - uint8_t *descriptors; - uint8_t devep, type, configuration, alt_interface; + uint8_t configuration; struct usb_ctrltransfer ct; - int interface, ret, length, i; + int ret; ct.bRequestType = USB_DIR_IN; ct.bRequest = USB_REQ_GET_CONFIGURATION; @@ -793,15 +791,31 @@ static int usb_linux_update_endp_table(USBHostDevice *s) ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct); if (ret < 0) { - perror("usb_linux_update_endp_table"); - return 1; + perror("usb_linux_get_configuration"); + return -1; } /* in address state */ if (configuration == 0) { - return 1; + return -1; } + return configuration; +} + +/* returns 1 on problem encountered or 0 for success */ +static int usb_linux_update_endp_table(USBHostDevice *s) +{ + uint8_t *descriptors; + uint8_t devep, type, configuration, alt_interface; + struct usb_ctrltransfer ct; + int interface, ret, length, i; + + i = usb_linux_get_configuration(s); + if (i < 0) + return 1; + configuration = i; + /* get the desired configuration, interface, and endpoint descriptors * from device description */ descriptors = &s->descr[18]; -- cgit v1.1 From 2cc59d8cb0ebcfa9cf3476c0528e50478997ab0c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 10 Nov 2010 10:06:25 +0100 Subject: usb-linux: Get the active configuration from sysfs rather then asking the dev Some devices seem to choke on receiving a USB_REQ_GET_CONFIGURATION ctrl msg (witnessed with a digital picture frame usb id 1908:1320). When usb_fs_type == USB_FS_SYS, the active configuration can be read directly from sysfs, which allows using this device through qemu's usb redirection. More in general it seems a good idea to not send needless control msg's to devices, esp. as the code in question is called every time a set_interface is done. Which happens multiple times during virtual machine startup, and when device drivers are activating the usb device. Signed-off-by: Anthony Liguori --- usb-linux.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/usb-linux.c b/usb-linux.c index 111fe1c..ccf7073 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -152,6 +152,8 @@ static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs) static int usb_host_close(USBHostDevice *dev); static int parse_filter(const char *spec, struct USBAutoFilter *f); static void usb_host_auto_check(void *unused); +static int usb_host_read_file(char *line, size_t line_size, + const char *device_file, const char *device_name); static int is_isoc(USBHostDevice *s, int ep) { @@ -781,6 +783,23 @@ static int usb_linux_get_configuration(USBHostDevice *s) struct usb_ctrltransfer ct; int ret; + if (usb_fs_type == USB_FS_SYS) { + char device_name[32], line[1024]; + int configuration; + + sprintf(device_name, "%d-%d", s->bus_num, s->devpath); + + if (!usb_host_read_file(line, sizeof(line), "bConfigurationValue", + device_name)) { + goto usbdevfs; + } + if (sscanf(line, "%d", &configuration) != 1) { + goto usbdevfs; + } + return configuration; + } + +usbdevfs: ct.bRequestType = USB_DIR_IN; ct.bRequest = USB_REQ_GET_CONFIGURATION; ct.wValue = 0; -- cgit v1.1 From 0290b57bdfec83ca78b6d119ea9847bb17943328 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 3 Nov 2010 14:29:44 +0000 Subject: Delete IOHandlers after potentially running them Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori --- vl.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index c58583d..9ee6479 100644 --- a/vl.c +++ b/vl.c @@ -1249,17 +1249,18 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { - if (ioh->deleted) { - QLIST_REMOVE(ioh, next); - qemu_free(ioh); - continue; - } - if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { + if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { ioh->fd_read(ioh->opaque); } - if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { + if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { ioh->fd_write(ioh->opaque); } + + /* Do this last in case read/write handlers marked it for deletion */ + if (ioh->deleted) { + QLIST_REMOVE(ioh, next); + qemu_free(ioh); + } } } -- cgit v1.1 From b88417062d5f73e2e8137e94b360ca4412942f33 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Nov 2010 20:07:07 +0000 Subject: Fix compilation failure with simple trace when srcdir==objdir Fix a makefile error that meant that qemu would not compile if the source and object directories were the same. Signed-off-by: Peter Maydell Signed-off-by: Anthony Liguori --- Makefile.target | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Makefile.target b/Makefile.target index a5e6410..652c7d2 100644 --- a/Makefile.target +++ b/Makefile.target @@ -30,6 +30,7 @@ endif endif PROGS=$(QEMU_PROG) +STPFILES= ifndef CONFIG_HAIKU LIBS+=-lm @@ -41,19 +42,17 @@ config-target.h: config-target.h-timestamp config-target.h-timestamp: config-target.mak ifdef CONFIG_SYSTEMTAP_TRACE -trace: $(QEMU_PROG).stp +STPFILES+=$(QEMU_PROG).stp $(QEMU_PROG).stp: $(call quiet-command,sh $(SRC_PATH)/tracetool \ --$(TRACE_BACKEND) \ --bindir $(bindir) \ --target $(TARGET_ARCH) \ - -s < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") -else -trace: + -s < $(SRC_PATH)/trace-events > $@," GEN $@") endif -all: $(PROGS) trace +all: $(PROGS) $(STPFILES) # Dummy command so that make thinks it has done something @true @@ -363,7 +362,7 @@ endif endif ifdef CONFIG_SYSTEMTAP_TRACE $(INSTALL_DIR) "$(DESTDIR)$(datadir)/../systemtap/tapset" - $(INSTALL_DATA) $(QEMU_PROG).stp "$(DESTDIR)$(datadir)/../systemtap/tapset" + $(INSTALL_DATA) $(STPFILES) "$(DESTDIR)$(datadir)/../systemtap/tapset" endif # Include automatically generated dependency files -- cgit v1.1 From 67d4b0c1907455f42ad8cea445ff10b81b49eebc Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 5 Nov 2010 15:40:38 -0600 Subject: pc: e820 qemu_cfg tables need to be packed We can't let the compiler define the alignment for qemu_cfg data. Signed-off-by: Alex Williamson Signed-off-by: Anthony Liguori --- hw/pc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 0e44df8..e7f7ac6 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -75,12 +75,12 @@ struct e820_entry { uint64_t address; uint64_t length; uint32_t type; -}; +} __attribute((__packed__, __aligned__(4))); struct e820_table { uint32_t count; struct e820_entry entry[E820_NR_ENTRIES]; -}; +} __attribute((__packed__, __aligned__(4))); static struct e820_table e820_table; -- cgit v1.1 From 8ca209ad90bdb678932a6b18caf32b461dbe5eee Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Sun, 7 Nov 2010 20:57:00 -0700 Subject: pc: Fix e820 fw_cfg for big endian Signed-off-by: Alex Williamson Signed-off-by: Anthony Liguori --- hw/pc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index e7f7ac6..c34d194 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -467,19 +467,19 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) int e820_add_entry(uint64_t address, uint64_t length, uint32_t type) { - int index = e820_table.count; + int index = le32_to_cpu(e820_table.count); struct e820_entry *entry; if (index >= E820_NR_ENTRIES) return -EBUSY; - entry = &e820_table.entry[index]; + entry = &e820_table.entry[index++]; - entry->address = address; - entry->length = length; - entry->type = type; + entry->address = cpu_to_le64(address); + entry->length = cpu_to_le64(length); + entry->type = cpu_to_le32(type); - e820_table.count++; - return e820_table.count; + e820_table.count = cpu_to_le32(index); + return index; } static void *bochs_bios_init(void) -- cgit v1.1 From 1d00a07de980ecf643c7d7699dfc48e94bec15ae Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 27 Oct 2010 17:43:34 -0200 Subject: QMP: Revamp the Python class example This commit simplifies and fixes a number of problems in the Python QEMUMonitorProtocol example class. It's almost a rewrite and it DOES BREAK the qmp-shell script (which is going to be fixed in the next commit). However, I'm not going to split this in different commits because it could get up to 10 commits, it's really not worth it for a simple demo class. Highlights: o TCP sockets support o QMP events support o Add documentation o Fix a number of unhandled errors o Simplify methods that send commands to the Monitor Signed-off-by: Luiz Capitulino --- QMP/qmp.py | 157 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 106 insertions(+), 51 deletions(-) diff --git a/QMP/qmp.py b/QMP/qmp.py index 4062f84..14ce8b0 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -1,6 +1,6 @@ # QEMU Monitor Protocol Python class # -# Copyright (C) 2009 Red Hat Inc. +# Copyright (C) 2009, 2010 Red Hat Inc. # # Authors: # Luiz Capitulino @@ -8,7 +8,9 @@ # This work is licensed under the terms of the GNU GPL, version 2. See # the COPYING file in the top-level directory. -import socket, json +import json +import errno +import socket class QMPError(Exception): pass @@ -16,61 +18,114 @@ class QMPError(Exception): class QMPConnectError(QMPError): pass +class QMPCapabilitiesError(QMPError): + pass + class QEMUMonitorProtocol: + def __init__(self, address): + """ + Create a QEMUMonitorProtocol class. + + @param address: QEMU address, can be either a unix socket path (string) + or a tuple in the form ( address, port ) for a TCP + connection + @note No connection is established, this is done by the connect() method + """ + self.__events = [] + self.__address = address + self.__sock = self.__get_sock() + self.__sockfile = self.__sock.makefile() + + def __get_sock(self): + if isinstance(self.__address, tuple): + family = socket.AF_INET + else: + family = socket.AF_UNIX + return socket.socket(family, socket.SOCK_STREAM) + + def __json_read(self): + while True: + data = self.__sockfile.readline() + if not data: + return + resp = json.loads(data) + if 'event' in resp: + self.__events.append(resp) + continue + return resp + + error = socket.error + def connect(self): - self.sock.connect(self.filename) - data = self.__json_read() - if data == None: - raise QMPConnectError - if not data.has_key('QMP'): + """ + Connect to the QMP Monitor and perform capabilities negotiation. + + @return QMP greeting dict + @raise socket.error on socket connection errors + @raise QMPConnectError if the greeting is not received + @raise QMPCapabilitiesError if fails to negotiate capabilities + """ + self.__sock.connect(self.__address) + greeting = self.__json_read() + if greeting is None or not greeting.has_key('QMP'): raise QMPConnectError - return data['QMP']['capabilities'] + # Greeting seems ok, negotiate capabilities + resp = self.cmd('qmp_capabilities') + if "return" in resp: + return greeting + raise QMPCapabilitiesError - def close(self): - self.sock.close() + def cmd_obj(self, qmp_cmd): + """ + Send a QMP command to the QMP Monitor. - def send_raw(self, line): - self.sock.send(str(line)) + @param qmp_cmd: QMP command to be sent as a Python dict + @return QMP response as a Python dict or None if the connection has + been closed + """ + try: + self.__sock.sendall(json.dumps(qmp_cmd)) + except socket.error, err: + if err[0] == errno.EPIPE: + return + raise socket.error(err) return self.__json_read() - def send(self, cmdline): - cmd = self.__build_cmd(cmdline) - self.__json_send(cmd) - resp = self.__json_read() - if resp == None: - return - elif resp.has_key('error'): - return resp['error'] - else: - return resp['return'] - - def __build_cmd(self, cmdline): - cmdargs = cmdline.split() - qmpcmd = { 'execute': cmdargs[0], 'arguments': {} } - for arg in cmdargs[1:]: - opt = arg.split('=') - try: - value = int(opt[1]) - except ValueError: - value = opt[1] - qmpcmd['arguments'][opt[0]] = value - return qmpcmd - - def __json_send(self, cmd): - # XXX: We have to send any additional char, otherwise - # the Server won't read our input - self.sock.send(json.dumps(cmd) + ' ') + def cmd(self, name, args=None, id=None): + """ + Build a QMP command and send it to the QMP Monitor. - def __json_read(self): + @param name: command name (string) + @param args: command arguments (dict) + @param id: command id (dict, list, string or int) + """ + qmp_cmd = { 'execute': name } + if args: + qmp_cmd['arguments'] = args + if id: + qmp_cmd['id'] = id + return self.cmd_obj(qmp_cmd) + + def get_events(self): + """ + Get a list of available QMP events. + """ + self.__sock.setblocking(0) try: - while True: - line = json.loads(self.sockfile.readline()) - if not 'event' in line: - return line - except ValueError: - return - - def __init__(self, filename): - self.filename = filename - self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self.sockfile = self.sock.makefile() + self.__json_read() + except socket.error, err: + if err[0] == errno.EAGAIN: + # No data available + pass + self.__sock.setblocking(1) + return self.__events + + def clear_events(self): + """ + Clear current list of pending events. + """ + self.__events = [] + + def close(self): + self.__sock.close() + self.__sockfile.close() -- cgit v1.1 From 9bed0d0d1c5667a2e1124c8e44d31ac254ca2efb Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 27 Oct 2010 17:57:51 -0200 Subject: QMP: Revamp the qmp-shell script This commit updates the qmp-shell script to use the new interface introduced by the last commit. Additionally, the following fixes/features are also introduced: o TCP sockets support o Update/add documentation o Simple command-line completion o Fix a number of unhandled errors Signed-off-by: Luiz Capitulino --- QMP/qmp-shell | 179 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 144 insertions(+), 35 deletions(-) diff --git a/QMP/qmp-shell b/QMP/qmp-shell index a5b72d1..1fb7e76 100755 --- a/QMP/qmp-shell +++ b/QMP/qmp-shell @@ -1,8 +1,8 @@ #!/usr/bin/python # -# Simple QEMU shell on top of QMP +# Low-level QEMU shell on top of QMP. # -# Copyright (C) 2009 Red Hat Inc. +# Copyright (C) 2009, 2010 Red Hat Inc. # # Authors: # Luiz Capitulino @@ -14,60 +14,169 @@ # # Start QEMU with: # -# $ qemu [...] -monitor control,unix:./qmp,server +# # qemu [...] -qmp unix:./qmp-sock,server # # Run the shell: # -# $ qmp-shell ./qmp +# $ qmp-shell ./qmp-sock # # Commands have the following format: # -# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] +# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] # # For example: # -# (QEMU) info item=network +# (QEMU) device_add driver=e1000 id=net1 +# {u'return': {}} +# (QEMU) import qmp import readline -from sys import argv,exit +import sys -def shell_help(): - print 'bye exit from the shell' +class QMPCompleter(list): + def complete(self, text, state): + for cmd in self: + if cmd.startswith(text): + if not state: + return cmd + else: + state -= 1 -def main(): - if len(argv) != 2: - print 'qemu-shell ' - exit(1) +class QMPShellError(Exception): + pass + +class QMPShellBadPort(QMPShellError): + pass + +# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and +# _execute_cmd()). Let's design a better one. +class QMPShell(qmp.QEMUMonitorProtocol): + def __init__(self, address): + qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address)) + self._greeting = None + self._completer = None + + def __get_address(self, arg): + """ + Figure out if the argument is in the port:host form, if it's not it's + probably a file path. + """ + addr = arg.split(':') + if len(addr) == 2: + try: + port = int(addr[1]) + except ValueError: + raise QMPShellBadPort + return ( addr[0], port ) + # socket path + return arg + + def _fill_completion(self): + for cmd in self.cmd('query-commands')['return']: + self._completer.append(cmd['name']) + + def __completer_setup(self): + self._completer = QMPCompleter() + self._fill_completion() + readline.set_completer(self._completer.complete) + readline.parse_and_bind("tab: complete") + # XXX: default delimiters conflict with some command names (eg. query-), + # clearing everything as it doesn't seem to matter + readline.set_completer_delims('') + + def __build_cmd(self, cmdline): + """ + Build a QMP input object from a user provided command-line in the + following format: + + < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] + """ + cmdargs = cmdline.split() + qmpcmd = { 'execute': cmdargs[0], 'arguments': {} } + for arg in cmdargs[1:]: + opt = arg.split('=') + try: + value = int(opt[1]) + except ValueError: + value = opt[1] + qmpcmd['arguments'][opt[0]] = value + return qmpcmd + + def _execute_cmd(self, cmdline): + try: + qmpcmd = self.__build_cmd(cmdline) + except: + print 'command format: ', + print '[arg-name1=arg1] ... [arg-nameN=argN]' + return True + resp = self.cmd_obj(qmpcmd) + if resp is None: + print 'Disconnected' + return False + print resp + return True + + def connect(self): + self._greeting = qmp.QEMUMonitorProtocol.connect(self) + self.__completer_setup() - qemu = qmp.QEMUMonitorProtocol(argv[1]) - qemu.connect() - qemu.send("qmp_capabilities") + def show_banner(self, msg='Welcome to the QMP low-level shell!'): + print msg + version = self._greeting['QMP']['version']['qemu'] + print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro']) - print 'Connected!' + def read_exec_command(self, prompt): + """ + Read and execute a command. - while True: + @return True if execution was ok, return False if disconnected. + """ try: - cmd = raw_input('(QEMU) ') + cmdline = raw_input(prompt) except EOFError: print - break - if cmd == '': - continue - elif cmd == 'bye': - break - elif cmd == 'help': - shell_help() + return False + if cmdline == '': + for ev in self.get_events(): + print ev + self.clear_events() + return True else: - try: - resp = qemu.send(cmd) - if resp == None: - print 'Disconnected' - break - print resp - except IndexError: - print '-> command format: ', - print '[arg-name1=arg1] ... [arg-nameN=argN]' + return self._execute_cmd(cmdline) + +def die(msg): + sys.stderr.write('ERROR: %s\n' % msg) + sys.exit(1) + +def fail_cmdline(option=None): + if option: + sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option) + sys.stderr.write('qemu-shell [ -H ] < UNIX socket path> | < TCP address:port >\n') + sys.exit(1) + +def main(): + try: + if len(sys.argv) == 2: + qemu = QMPShell(sys.argv[1]) + else: + fail_cmdline() + except QMPShellBadPort: + die('bad port number in command-line') + + try: + qemu.connect() + except qmp.QMPConnectError: + die('Didn\'t get QMP greeting message') + except qmp.QMPCapabilitiesError: + die('Could not negotiate capabilities') + except qemu.error: + die('Could not connect to %s' % sys.argv[1]) + + qemu.show_banner() + while qemu.read_exec_command('(QEMU) '): + pass + qemu.close() if __name__ == '__main__': main() -- cgit v1.1 From 4cdbc094ca3865696c1456f1586818766bf9aae6 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 27 Oct 2010 18:03:01 -0200 Subject: QMP: Drop vm-info example script It's broken and not really useful, let's just drop it. Signed-off-by: Luiz Capitulino --- QMP/README | 5 +---- QMP/vm-info | 33 --------------------------------- 2 files changed, 1 insertion(+), 37 deletions(-) delete mode 100755 QMP/vm-info diff --git a/QMP/README b/QMP/README index 80503f2..c95a08c 100644 --- a/QMP/README +++ b/QMP/README @@ -19,10 +19,7 @@ o qmp-spec.txt QEMU Monitor Protocol current specification o qmp-commands.txt QMP supported commands (auto-generated at build-time) o qmp-events.txt List of available asynchronous events -There are also two simple Python scripts available: - -o qmp-shell A shell -o vm-info Show some information about the Virtual Machine +There is also a simple Python script called 'qmp-shell' available. IMPORTANT: It's strongly recommended to read the 'Stability Considerations' section in the qmp-commands.txt file before making any serious use of QMP. diff --git a/QMP/vm-info b/QMP/vm-info deleted file mode 100755 index be5b038..0000000 --- a/QMP/vm-info +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python -# -# Print Virtual Machine information -# -# Usage: -# -# Start QEMU with: -# -# $ qemu [...] -monitor control,unix:./qmp,server -# -# Run vm-info: -# -# $ vm-info ./qmp -# -# Luiz Capitulino - -import qmp -from sys import argv,exit - -def main(): - if len(argv) != 2: - print 'vm-info ' - exit(1) - - qemu = qmp.QEMUMonitorProtocol(argv[1]) - qemu.connect() - qemu.send("qmp_capabilities") - - for cmd in [ 'version', 'kvm', 'status', 'uuid', 'balloon' ]: - print cmd + ': ' + str(qemu.send('query-' + cmd)) - -if __name__ == '__main__': - main() -- cgit v1.1 From 999bd67c879cbd8bf0fe2b4ff0fb308a9a48ec72 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 22 Oct 2010 16:09:05 -0200 Subject: qemu-char: Introduce Memory driver This driver handles in-memory chardev operations. That's, all writes to this driver are stored in an internal buffer and it doesn't talk to the external world in any way. Right now it's very simple: it supports only writes. But it can be easily extended to support more operations. This is going to be used by the monitor's "HMP passthrough via QMP" feature, which needs to run monitor handlers without a backing device. Signed-off-by: Luiz Capitulino --- qemu-char.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-char.h | 7 +++++++ 2 files changed, 71 insertions(+) diff --git a/qemu-char.c b/qemu-char.c index 88997f9..edc9ad6 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2275,6 +2275,70 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) return NULL; } +/***********************************************************/ +/* Memory chardev */ +typedef struct { + size_t outbuf_size; + size_t outbuf_capacity; + uint8_t *outbuf; +} MemoryDriver; + +static int mem_chr_write(CharDriverState *chr, const uint8_t *buf, int len) +{ + MemoryDriver *d = chr->opaque; + + /* TODO: the QString implementation has the same code, we should + * introduce a generic way to do this in cutils.c */ + if (d->outbuf_capacity < d->outbuf_size + len) { + /* grow outbuf */ + d->outbuf_capacity += len; + d->outbuf_capacity *= 2; + d->outbuf = qemu_realloc(d->outbuf, d->outbuf_capacity); + } + + memcpy(d->outbuf + d->outbuf_size, buf, len); + d->outbuf_size += len; + + return len; +} + +void qemu_chr_init_mem(CharDriverState *chr) +{ + MemoryDriver *d; + + d = qemu_malloc(sizeof(*d)); + d->outbuf_size = 0; + d->outbuf_capacity = 4096; + d->outbuf = qemu_mallocz(d->outbuf_capacity); + + memset(chr, 0, sizeof(*chr)); + chr->opaque = d; + chr->chr_write = mem_chr_write; +} + +QString *qemu_chr_mem_to_qs(CharDriverState *chr) +{ + MemoryDriver *d = chr->opaque; + return qstring_from_substr((char *) d->outbuf, 0, d->outbuf_size - 1); +} + +/* NOTE: this driver can not be closed with qemu_chr_close()! */ +void qemu_chr_close_mem(CharDriverState *chr) +{ + MemoryDriver *d = chr->opaque; + + qemu_free(d->outbuf); + qemu_free(chr->opaque); + chr->opaque = NULL; + chr->chr_write = NULL; +} + +size_t qemu_chr_mem_osize(const CharDriverState *chr) +{ + const MemoryDriver *d = chr->opaque; + return d->outbuf_size; +} + QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) { char host[65], port[33], width[8], height[8]; diff --git a/qemu-char.h b/qemu-char.h index 18ad12b..e6ee6c4 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -6,6 +6,7 @@ #include "qemu-option.h" #include "qemu-config.h" #include "qobject.h" +#include "qstring.h" /* character device */ @@ -100,6 +101,12 @@ CharDriverState *qemu_chr_open_eventfd(int eventfd); extern int term_escape_char; +/* memory chardev */ +void qemu_chr_init_mem(CharDriverState *chr); +void qemu_chr_close_mem(CharDriverState *chr); +QString *qemu_chr_mem_to_qs(CharDriverState *chr); +size_t qemu_chr_mem_osize(const CharDriverState *chr); + /* async I/O support */ int qemu_set_fd_handler2(int fd, -- cgit v1.1 From 0268d97c51207f35a5a01239ad92ef2c35dcd5ba Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 22 Oct 2010 10:08:02 -0200 Subject: QMP: Introduce Human Monitor passthrough command This command allows QMP clients to execute HMP commands. Please, check the documentation added to the qmp-commands.hx file for additional details about the interface and its limitations. Signed-off-by: Luiz Capitulino --- monitor.c | 38 ++++++++++++++++++++++++++++++++++++++ qmp-commands.hx | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/monitor.c b/monitor.c index 8cee35d..ec31eac 100644 --- a/monitor.c +++ b/monitor.c @@ -491,6 +491,44 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params, return 0; } +static int mon_set_cpu(int cpu_index); +static void handle_user_command(Monitor *mon, const char *cmdline); + +static int do_hmp_passthrough(Monitor *mon, const QDict *params, + QObject **ret_data) +{ + int ret = 0; + Monitor *old_mon, hmp; + CharDriverState mchar; + + memset(&hmp, 0, sizeof(hmp)); + qemu_chr_init_mem(&mchar); + hmp.chr = &mchar; + + old_mon = cur_mon; + cur_mon = &hmp; + + if (qdict_haskey(params, "cpu-index")) { + ret = mon_set_cpu(qdict_get_int(params, "cpu-index")); + if (ret < 0) { + cur_mon = old_mon; + qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); + goto out; + } + } + + handle_user_command(&hmp, qdict_get_str(params, "command-line")); + cur_mon = old_mon; + + if (qemu_chr_mem_osize(hmp.chr) > 0) { + *ret_data = QOBJECT(qemu_chr_mem_to_qs(hmp.chr)); + } + +out: + qemu_chr_close_mem(hmp.chr); + return ret; +} + static int compare_cmd(const char *name, const char *list) { const char *p, *pstart; diff --git a/qmp-commands.hx b/qmp-commands.hx index 793cf1c..e5f157f 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -761,6 +761,51 @@ Example: Note: This command must be issued before issuing any other command. +EQMP + + { + .name = "human-monitor-command", + .args_type = "command-line:s,cpu-index:i?", + .params = "", + .help = "", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_hmp_passthrough, + }, + +SQMP +human-monitor-command +--------------------- + +Execute a Human Monitor command. + +Arguments: + +- command-line: the command name and its arguments, just like the + Human Monitor's shell (json-string) +- cpu-index: select the CPU number to be used by commands which access CPU + data, like 'info registers'. The Monitor selects CPU 0 if this + argument is not provided (json-int, optional) + +Example: + +-> { "execute": "human-monitor-command", "arguments": { "command-line": "info kvm" } } +<- { "return": "kvm support: enabled\r\n" } + +Notes: + +(1) The Human Monitor is NOT an stable interface, this means that command + names, arguments and responses can change or be removed at ANY time. + Applications that rely on long term stability guarantees should NOT + use this command + +(2) Limitations: + + o This command is stateless, this means that commands that depend + on state information (such as getfd) might not work + + o Commands that prompt the user for data (eg. 'cont' when the block + device is encrypted) don't currently work + 3. Query Commands ================= -- cgit v1.1 From 11217a757e7dda66fd2e78b10ea0cd8d6b290e42 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 28 Oct 2010 13:28:37 -0200 Subject: QMP/qmp-shell: Introduce HMP mode In which qmp-shell will exclusively use the HMP passthrough feature, this is useful for testing. Example: # ./qmp-shell -H qmp-sock Welcome to the HMP shell! Connected to QEMU 0.13.50 (QEMU) info network VLAN 0 devices: user.0: net=10.0.2.0, restricted=n e1000.0: model=e1000,macaddr=52:54:00:12:34:56 Devices not on any VLAN: (QEMU) Signed-off-by: Luiz Capitulino --- QMP/qmp-shell | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/QMP/qmp-shell b/QMP/qmp-shell index 1fb7e76..42dabc8 100755 --- a/QMP/qmp-shell +++ b/QMP/qmp-shell @@ -145,6 +145,76 @@ class QMPShell(qmp.QEMUMonitorProtocol): else: return self._execute_cmd(cmdline) +class HMPShell(QMPShell): + def __init__(self, address): + QMPShell.__init__(self, address) + self.__cpu_index = 0 + + def __cmd_completion(self): + for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'): + if cmd and cmd[0] != '[' and cmd[0] != '\t': + name = cmd.split()[0] # drop help text + if name == 'info': + continue + if name.find('|') != -1: + # Command in the form 'foobar|f' or 'f|foobar', take the + # full name + opt = name.split('|') + if len(opt[0]) == 1: + name = opt[1] + else: + name = opt[0] + self._completer.append(name) + self._completer.append('help ' + name) # help completion + + def __info_completion(self): + for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'): + if cmd: + self._completer.append('info ' + cmd.split()[1]) + + def __other_completion(self): + # special cases + self._completer.append('help info') + + def _fill_completion(self): + self.__cmd_completion() + self.__info_completion() + self.__other_completion() + + def __cmd_passthrough(self, cmdline, cpu_index = 0): + return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments': + { 'command-line': cmdline, + 'cpu-index': cpu_index } }) + + def _execute_cmd(self, cmdline): + if cmdline.split()[0] == "cpu": + # trap the cpu command, it requires special setting + try: + idx = int(cmdline.split()[1]) + if not 'return' in self.__cmd_passthrough('info version', idx): + print 'bad CPU index' + return True + self.__cpu_index = idx + except ValueError: + print 'cpu command takes an integer argument' + return True + resp = self.__cmd_passthrough(cmdline, self.__cpu_index) + if resp is None: + print 'Disconnected' + return False + assert 'return' in resp or 'error' in resp + if 'return' in resp: + # Success + if len(resp['return']) > 0: + print resp['return'], + else: + # Error + print '%s: %s' % (resp['error']['class'], resp['error']['desc']) + return True + + def show_banner(self): + QMPShell.show_banner(self, msg='Welcome to the HMP shell!') + def die(msg): sys.stderr.write('ERROR: %s\n' % msg) sys.exit(1) @@ -156,9 +226,16 @@ def fail_cmdline(option=None): sys.exit(1) def main(): + addr = '' try: if len(sys.argv) == 2: qemu = QMPShell(sys.argv[1]) + addr = sys.argv[1] + elif len(sys.argv) == 3: + if sys.argv[1] != '-H': + fail_cmdline(sys.argv[1]) + qemu = HMPShell(sys.argv[2]) + addr = sys.argv[2] else: fail_cmdline() except QMPShellBadPort: @@ -171,7 +248,7 @@ def main(): except qmp.QMPCapabilitiesError: die('Could not negotiate capabilities') except qemu.error: - die('Could not connect to %s' % sys.argv[1]) + die('Could not connect to %s' % addr) qemu.show_banner() while qemu.read_exec_command('(QEMU) '): -- cgit v1.1 From a6f9dd02f75685934ca52f038b6fcb38b661c283 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 10 Nov 2010 15:59:57 -0200 Subject: Makefile: Fix check dependency breakage Commit b152aa84d52882bb1846485a89baf13aa07c86bc broke the unit-tests build, fix it. Signed-off-by: Luiz Capitulino --- Makefile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 747e47c..4e120a2 100644 --- a/Makefile +++ b/Makefile @@ -163,12 +163,14 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS) -check-qint: check-qint.o qint.o qemu-malloc.o $(trace-obj-y) -check-qstring: check-qstring.o qstring.o qemu-malloc.o $(trace-obj-y) -check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o $(trace-obj-y) -check-qlist: check-qlist.o qlist.o qint.o qemu-malloc.o $(trace-obj-y) -check-qfloat: check-qfloat.o qfloat.o qemu-malloc.o $(trace-obj-y) -check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o qemu-malloc.o $(trace-obj-y) +CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y) + +check-qint: check-qint.o qint.o $(CHECK_PROG_DEPS) +check-qstring: check-qstring.o qstring.o $(CHECK_PROG_DEPS) +check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(CHECK_PROG_DEPS) +check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS) +check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS) +check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS) clean: # avoid old build problems by removing potentially incorrect old files -- cgit v1.1 From 39deb1e496de81957167daebf5cf5d1fbd5e47c2 Mon Sep 17 00:00:00 2001 From: malc Date: Thu, 18 Nov 2010 14:30:12 +0300 Subject: audio: Only use audio timer when necessary Originally proposed by Gerd Hoffmann. Signed-off-by: malc Acked-by: Gerd Hoffmann --- audio/audio.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index ade342e..1707446 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1096,15 +1096,6 @@ static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info) /* * Timer */ -static void audio_timer (void *opaque) -{ - AudioState *s = opaque; - - audio_run ("timer"); - qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks); -} - - static int audio_is_timer_needed (void) { HWVoiceIn *hwi = NULL; @@ -1119,10 +1110,8 @@ static int audio_is_timer_needed (void) return 0; } -static void audio_reset_timer (void) +static void audio_reset_timer (AudioState *s) { - AudioState *s = &glob_audio_state; - if (audio_is_timer_needed ()) { qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1); } @@ -1131,6 +1120,12 @@ static void audio_reset_timer (void) } } +static void audio_timer (void *opaque) +{ + audio_run ("timer"); + audio_reset_timer (opaque); +} + /* * Public API */ @@ -1195,7 +1190,7 @@ void AUD_set_active_out (SWVoiceOut *sw, int on) hw->enabled = 1; if (s->vm_running) { hw->pcm_ops->ctl_out (hw, VOICE_ENABLE, conf.try_poll_out); - audio_reset_timer (); + audio_reset_timer (s); } } } @@ -1240,6 +1235,7 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) hw->enabled = 1; if (s->vm_running) { hw->pcm_ops->ctl_in (hw, VOICE_ENABLE, conf.try_poll_in); + audio_reset_timer (s); } } sw->total_hw_samples_acquired = hw->total_samples_captured; @@ -1761,7 +1757,7 @@ static void audio_vm_change_state_handler (void *opaque, int running, while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) { hwi->pcm_ops->ctl_in (hwi, op, conf.try_poll_in); } - audio_reset_timer (); + audio_reset_timer (s); } static void audio_atexit (void) -- cgit v1.1 From 371c338ecae44bb28cc19138484256b1df831e99 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 17 Nov 2010 18:05:58 -0600 Subject: Revert "Add support for generating a systemtap tapset static probes" This reverts commit 2834c3e0140c3b0ed4422909dfa0607b7213d95d. Conflicts: Makefile.target --- Makefile.target | 17 +---------- configure | 7 ----- tracetool | 92 --------------------------------------------------------- 3 files changed, 1 insertion(+), 115 deletions(-) diff --git a/Makefile.target b/Makefile.target index 652c7d2..31c968c 100644 --- a/Makefile.target +++ b/Makefile.target @@ -41,18 +41,7 @@ kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS) config-target.h: config-target.h-timestamp config-target.h-timestamp: config-target.mak -ifdef CONFIG_SYSTEMTAP_TRACE -STPFILES+=$(QEMU_PROG).stp - -$(QEMU_PROG).stp: - $(call quiet-command,sh $(SRC_PATH)/tracetool \ - --$(TRACE_BACKEND) \ - --bindir $(bindir) \ - --target $(TARGET_ARCH) \ - -s < $(SRC_PATH)/trace-events > $@," GEN $@") -endif - -all: $(PROGS) $(STPFILES) +all: $(PROGS) # Dummy command so that make thinks it has done something @true @@ -360,10 +349,6 @@ ifneq ($(STRIP),) $(STRIP) $(patsubst %,"$(DESTDIR)$(bindir)/%",$(PROGS)) endif endif -ifdef CONFIG_SYSTEMTAP_TRACE - $(INSTALL_DIR) "$(DESTDIR)$(datadir)/../systemtap/tapset" - $(INSTALL_DATA) $(STPFILES) "$(DESTDIR)$(datadir)/../systemtap/tapset" -endif # Include automatically generated dependency files -include $(wildcard *.d */*.d) diff --git a/configure b/configure index e560f87..f8dad3e 100755 --- a/configure +++ b/configure @@ -2192,10 +2192,6 @@ EOF echo exit 1 fi - trace_backend_stap="no" - if has 'stap' ; then - trace_backend_stap="yes" - fi fi ########################################## @@ -2649,9 +2645,6 @@ fi if test "$trace_backend" = "simple"; then trace_file="\"$trace_file-%u\"" fi -if test "$trace_backend" = "dtrace" -a "$trace_backend_stap" = "yes" ; then - echo "CONFIG_SYSTEMTAP_TRACE=y" >> $config_host_mak -fi echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak echo "TOOLS=$tools" >> $config_host_mak diff --git a/tracetool b/tracetool index d797ab7..5b6636a 100755 --- a/tracetool +++ b/tracetool @@ -26,12 +26,6 @@ Output formats: -h Generate .h file -c Generate .c file -d Generate .d file (DTrace only) - -s Generate .stp file (DTrace with SystemTAP only) - -Options: - --bindir [bindir] QEMU binary install location - --target [arch] QEMU target architecture - EOF exit 1 } @@ -396,54 +390,6 @@ linetod_end_dtrace() EOF } -linetos_begin_dtrace() -{ - return -} - -linetos_dtrace() -{ - local name args arglist state - name=$(get_name "$1") - args=$(get_args "$1") - arglist=$(get_argnames "$1", "") - state=$(get_state "$1") - if [ "$state" = "0" ] ; then - name=${name##disable } - fi - - if [ "$target" = "i386" ] - then - binary="qemu" - else - binary="qemu-system-$target" - fi - - # Define prototype for probe arguments - cat < Date: Wed, 17 Nov 2010 18:06:06 -0600 Subject: Revert "Add a DTrace tracing backend targetted for SystemTAP compatability" This reverts commit 4addb1127f6327c7ebcbd150a6b589e7677adc92. --- .gitignore | 2 - Makefile | 23 ------------ Makefile.objs | 4 -- configure | 14 +------ tracetool | 116 +++++----------------------------------------------------- 5 files changed, 11 insertions(+), 148 deletions(-) diff --git a/.gitignore b/.gitignore index 3efb4ec..a43e4d1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,6 @@ config-host.* config-target.* trace.h trace.c -trace-dtrace.h -trace-dtrace.dtrace *-timestamp *-softmmu *-darwin-user diff --git a/Makefile b/Makefile index 747e47c..6896319 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,6 @@ # Makefile for QEMU. GENERATED_HEADERS = config-host.h trace.h qemu-options.def -ifeq ($(TRACE_BACKEND),dtrace) -GENERATED_HEADERS += trace-dtrace.h -endif ifneq ($(wildcard config-host.mak),) # Put the all: rule here so that config-host.mak can contain dependencies. @@ -111,11 +108,7 @@ ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS) bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS) -ifeq ($(TRACE_BACKEND),dtrace) -trace.h: trace.h-timestamp trace-dtrace.h -else trace.h: trace.h-timestamp -endif trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h @@ -127,20 +120,6 @@ trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak trace.o: trace.c $(GENERATED_HEADERS) -trace-dtrace.h: trace-dtrace.dtrace - $(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h") - -# Normal practice is to name DTrace probe file with a '.d' extension -# but that gets picked up by QEMU's Makefile as an external dependancy -# rule file. So we use '.dtrace' instead -trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp -trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak - $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace") - @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace - -trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) - $(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o") - simpletrace.o: simpletrace.c $(GENERATED_HEADERS) version.o: $(SRC_PATH)/version.rc config-host.mak @@ -178,8 +157,6 @@ clean: 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 rm -f qemu-img-cmds.h 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 $(MAKE) -C tests clean for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ diff --git a/Makefile.objs b/Makefile.objs index 23b17ce..15569af 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -286,15 +286,11 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o ###################################################################### # trace -ifeq ($(TRACE_BACKEND),dtrace) -trace-obj-y = trace-dtrace.o -else trace-obj-y = trace.o ifeq ($(TRACE_BACKEND),simple) trace-obj-y += simpletrace.o user-obj-y += qemu-timer-common.o endif -endif vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/configure b/configure index f8dad3e..7025d2b 100755 --- a/configure +++ b/configure @@ -929,7 +929,7 @@ echo " --enable-docs enable documentation build" echo " --disable-docs disable documentation build" echo " --disable-vhost-net disable vhost-net acceleration support" echo " --enable-vhost-net enable vhost-net acceleration support" -echo " --trace-backend=B Trace backend nop simple ust dtrace" +echo " --trace-backend=B Trace backend nop simple ust" echo " --trace-file=NAME Full PATH,NAME of file to store traces" echo " Default:trace-" echo " --disable-spice disable spice" @@ -2193,18 +2193,6 @@ EOF exit 1 fi fi - -########################################## -# For 'dtrace' backend, test if 'dtrace' command is present -if test "$trace_backend" = "dtrace"; then - if ! has 'dtrace' ; then - echo - echo "Error: dtrace command is not found in PATH $PATH" - echo - exit 1 - fi -fi - ########################################## # End of CC checks # After here, no more $cc or $ld runs diff --git a/tracetool b/tracetool index 5b6636a..7010858 100755 --- a/tracetool +++ b/tracetool @@ -20,12 +20,10 @@ Backends: --nop Tracing disabled --simple Simple built-in backend --ust LTTng User Space Tracing backend - --dtrace DTrace/SystemTAP backend Output formats: -h Generate .h file -c Generate .c file - -d Generate .d file (DTrace only) EOF exit 1 } @@ -48,9 +46,8 @@ get_args() # Get the argument name list of a trace event get_argnames() { - local nfields field name sep + local nfields field name nfields=0 - sep="$2" for field in $(get_args "$1"); do nfields=$((nfields + 1)) @@ -61,7 +58,7 @@ get_argnames() name=${field%,} test "$field" = "$name" && continue - printf "%s%s " $name $sep + printf "%s" "$name, " done # Last argument name @@ -76,7 +73,7 @@ get_argc() { local name argc argc=0 - for name in $(get_argnames "$1", ","); do + for name in $(get_argnames "$1"); do argc=$((argc + 1)) done echo $argc @@ -157,7 +154,7 @@ EOF cast_args_to_uint64_t() { local arg - for arg in $(get_argnames "$1", ","); do + for arg in $(get_argnames "$1"); do printf "%s" "(uint64_t)(uintptr_t)$arg" done } @@ -250,7 +247,7 @@ linetoh_ust() local name args argnames name=$(get_name "$1") args=$(get_args "$1") - argnames=$(get_argnames "$1", ",") + argnames=$(get_argnames "$1") cat < Date: Fri, 12 Nov 2010 13:20:24 +0000 Subject: Add a DTrace tracing backend targetted for SystemTAP compatability This introduces a new tracing backend that targets the SystemTAP implementation of DTrace userspace tracing. The core functionality should be applicable and standard across any DTrace implementation on Solaris, OS-X, *BSD, but the Makefile rules will likely need some small additional changes to cope with OS specific build requirements. This backend builds a little differently from the other tracing backends. Specifically there is no 'trace.c' file, because the 'dtrace' command line tool generates a '.o' file directly from the dtrace probe definition file. The probe definition is usually named with a '.d' extension but QEMU uses '.d' files for its external makefile dependancy tracking, so this uses '.dtrace' as the extension for the probe definition file. The 'tracetool' program gains the ability to generate a trace.h file for DTrace, and also to generate the trace.d file containing the dtrace probe definition. Example usage of a dtrace probe in systemtap looks like: probe process("qemu").mark("qemu_malloc") { printf("Malloc %d %p\n", $arg1, $arg2); } * .gitignore: Ignore trace-dtrace.* * Makefile: Extra rules for generating DTrace files * Makefile.obj: Don't build trace.o for DTrace, use trace-dtrace.o generated by 'dtrace' instead * tracetool: Support for generating DTrace data files Reviewed-by: Stefan Hajnoczi Signed-off-by: Daniel P. Berrange Signed-off-by: Anthony Liguori --- .gitignore | 2 + Makefile | 23 +++++++++++ Makefile.objs | 4 ++ configure | 14 ++++++- tracetool | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 154 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index a43e4d1..3efb4ec 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ config-host.* config-target.* trace.h trace.c +trace-dtrace.h +trace-dtrace.dtrace *-timestamp *-softmmu *-darwin-user diff --git a/Makefile b/Makefile index 6896319..747e47c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ # Makefile for QEMU. GENERATED_HEADERS = config-host.h trace.h qemu-options.def +ifeq ($(TRACE_BACKEND),dtrace) +GENERATED_HEADERS += trace-dtrace.h +endif ifneq ($(wildcard config-host.mak),) # Put the all: rule here so that config-host.mak can contain dependencies. @@ -108,7 +111,11 @@ ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS) bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS) +ifeq ($(TRACE_BACKEND),dtrace) +trace.h: trace.h-timestamp trace-dtrace.h +else trace.h: trace.h-timestamp +endif trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h @@ -120,6 +127,20 @@ trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak trace.o: trace.c $(GENERATED_HEADERS) +trace-dtrace.h: trace-dtrace.dtrace + $(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h") + +# Normal practice is to name DTrace probe file with a '.d' extension +# but that gets picked up by QEMU's Makefile as an external dependancy +# rule file. So we use '.dtrace' instead +trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp +trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak + $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace") + @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace + +trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) + $(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o") + simpletrace.o: simpletrace.c $(GENERATED_HEADERS) version.o: $(SRC_PATH)/version.rc config-host.mak @@ -157,6 +178,8 @@ clean: 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 rm -f qemu-img-cmds.h 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 $(MAKE) -C tests clean for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ diff --git a/Makefile.objs b/Makefile.objs index 15569af..23b17ce 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -286,11 +286,15 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o ###################################################################### # trace +ifeq ($(TRACE_BACKEND),dtrace) +trace-obj-y = trace-dtrace.o +else trace-obj-y = trace.o ifeq ($(TRACE_BACKEND),simple) trace-obj-y += simpletrace.o user-obj-y += qemu-timer-common.o endif +endif vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/configure b/configure index 7025d2b..f8dad3e 100755 --- a/configure +++ b/configure @@ -929,7 +929,7 @@ echo " --enable-docs enable documentation build" echo " --disable-docs disable documentation build" echo " --disable-vhost-net disable vhost-net acceleration support" echo " --enable-vhost-net enable vhost-net acceleration support" -echo " --trace-backend=B Trace backend nop simple ust" +echo " --trace-backend=B Trace backend nop simple ust dtrace" echo " --trace-file=NAME Full PATH,NAME of file to store traces" echo " Default:trace-" echo " --disable-spice disable spice" @@ -2193,6 +2193,18 @@ EOF exit 1 fi fi + +########################################## +# For 'dtrace' backend, test if 'dtrace' command is present +if test "$trace_backend" = "dtrace"; then + if ! has 'dtrace' ; then + echo + echo "Error: dtrace command is not found in PATH $PATH" + echo + exit 1 + fi +fi + ########################################## # End of CC checks # After here, no more $cc or $ld runs diff --git a/tracetool b/tracetool index 7010858..1ade103 100755 --- a/tracetool +++ b/tracetool @@ -20,10 +20,12 @@ Backends: --nop Tracing disabled --simple Simple built-in backend --ust LTTng User Space Tracing backend + --dtrace DTrace/SystemTAP backend Output formats: -h Generate .h file -c Generate .c file + -d Generate .d file (DTrace only) EOF exit 1 } @@ -46,8 +48,9 @@ get_args() # Get the argument name list of a trace event get_argnames() { - local nfields field name + local nfields field name sep nfields=0 + sep="$2" for field in $(get_args "$1"); do nfields=$((nfields + 1)) @@ -58,7 +61,7 @@ get_argnames() name=${field%,} test "$field" = "$name" && continue - printf "%s" "$name, " + printf "%s%s " $name $sep done # Last argument name @@ -73,7 +76,7 @@ get_argc() { local name argc argc=0 - for name in $(get_argnames "$1"); do + for name in $(get_argnames "$1", ","); do argc=$((argc + 1)) done echo $argc @@ -154,7 +157,7 @@ EOF cast_args_to_uint64_t() { local arg - for arg in $(get_argnames "$1"); do + for arg in $(get_argnames "$1", ","); do printf "%s" "(uint64_t)(uintptr_t)$arg" done } @@ -247,7 +250,7 @@ linetoh_ust() local name args argnames name=$(get_name "$1") args=$(get_args "$1") - argnames=$(get_argnames "$1") + argnames=$(get_argnames "$1", ",") cat < Date: Fri, 12 Nov 2010 13:20:25 +0000 Subject: Add support for generating a systemtap tapset static probes This introduces generation of a qemu.stp/qemu-system-XXX.stp files which provides tapsets with friendly names for static probes & their arguments. Instead of probe process("qemu").mark("qemu_malloc") { printf("Malloc %d %p\n", $arg1, $arg2); } It is now possible todo probe qemu.system.i386.qemu_malloc { printf("Malloc %d %p\n", size, ptr); } There is one tapset defined per target arch, for both user and system emulators. * Makefile.target: Generate stp files for each target * tracetool: Support for generating systemtap tapsets * configure: Check for whether systemtap is available with the DTrace backend Reviewed-by: Stefan Hajnoczi Signed-off-by: Daniel P. Berrange Signed-off-by: Anthony Liguori --- Makefile.target | 29 ++++++++++++- configure | 7 ++++ tracetool | 128 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 146 insertions(+), 18 deletions(-) diff --git a/Makefile.target b/Makefile.target index 31c968c..2800f47 100644 --- a/Makefile.target +++ b/Makefile.target @@ -41,7 +41,27 @@ kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS) config-target.h: config-target.h-timestamp config-target.h-timestamp: config-target.mak -all: $(PROGS) +ifdef CONFIG_SYSTEMTAP_TRACE +stap: $(QEMU_PROG).stp + +ifdef CONFIG_USER_ONLY +TARGET_TYPE=user +else +TARGET_TYPE=system +endif + +$(QEMU_PROG).stp: + $(call quiet-command,sh $(SRC_PATH)/tracetool \ + --$(TRACE_BACKEND) \ + --binary $(bindir)/$(QEMU_PROG) \ + --target-arch $(TARGET_ARCH) \ + --target-type $(TARGET_TYPE) \ + --stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") +else +stap: +endif + +all: $(PROGS) stap # Dummy command so that make thinks it has done something @true @@ -341,6 +361,9 @@ clean: rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o rm -f *.d */*.d tcg/*.o ide/*.o rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c +ifdef CONFIG_SYSTEMTAP_TRACE + rm -f *.stp +endif install: all ifneq ($(PROGS),) @@ -349,6 +372,10 @@ ifneq ($(STRIP),) $(STRIP) $(patsubst %,"$(DESTDIR)$(bindir)/%",$(PROGS)) endif endif +ifdef CONFIG_SYSTEMTAP_TRACE + $(INSTALL_DIR) "$(DESTDIR)$(datadir)/../systemtap/tapset" + $(INSTALL_DATA) $(QEMU_PROG).stp "$(DESTDIR)$(datadir)/../systemtap/tapset" +endif # Include automatically generated dependency files -include $(wildcard *.d */*.d) diff --git a/configure b/configure index f8dad3e..2917874 100755 --- a/configure +++ b/configure @@ -2203,6 +2203,10 @@ if test "$trace_backend" = "dtrace"; then echo exit 1 fi + trace_backend_stap="no" + if has 'stap' ; then + trace_backend_stap="yes" + fi fi ########################################## @@ -2645,6 +2649,9 @@ fi if test "$trace_backend" = "simple"; then trace_file="\"$trace_file-%u\"" fi +if test "$trace_backend" = "dtrace" -a "$trace_backend_stap" = "yes" ; then + echo "CONFIG_SYSTEMTAP_TRACE=y" >> $config_host_mak +fi echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak echo "TOOLS=$tools" >> $config_host_mak diff --git a/tracetool b/tracetool index 1ade103..fce491c 100755 --- a/tracetool +++ b/tracetool @@ -23,9 +23,16 @@ Backends: --dtrace DTrace/SystemTAP backend Output formats: - -h Generate .h file - -c Generate .c file - -d Generate .d file (DTrace only) + -h Generate .h file + -c Generate .c file + -d Generate .d file (DTrace only) + --stap Generate .stp file (DTrace with SystemTAP only) + +Options: + --binary [path] Full path to QEMU binary + --target-arch [arch] QEMU emulator target arch + --target-type [type] QEMU emulator target type ('system' or 'user') + EOF exit 1 } @@ -396,6 +403,51 @@ linetod_end_dtrace() EOF } +linetostap_begin_dtrace() +{ + return +} + +linetostap_dtrace() +{ + local i arg name args arglist state + 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 < Date: Mon, 8 Nov 2010 17:02:54 -0200 Subject: block: fix shift in dirty bitmap calculation Otherwise upper 32 bits of bitmap entries are not correctly calculated. Reviewed-by: Kevin Wolf Signed-off-by: Marcelo Tosatti Signed-off-by: Anthony Liguori --- block.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/block.c b/block.c index 6b505fb..53a10de 100644 --- a/block.c +++ b/block.c @@ -930,14 +930,14 @@ static void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num, bit = start % (sizeof(unsigned long) * 8); val = bs->dirty_bitmap[idx]; if (dirty) { - if (!(val & (1 << bit))) { + if (!(val & (1UL << bit))) { bs->dirty_count++; - val |= 1 << bit; + val |= 1UL << bit; } } else { - if (val & (1 << bit)) { + if (val & (1UL << bit)) { bs->dirty_count--; - val &= ~(1 << bit); + val &= ~(1UL << bit); } } bs->dirty_bitmap[idx] = val; @@ -2685,8 +2685,8 @@ int bdrv_get_dirty(BlockDriverState *bs, int64_t sector) if (bs->dirty_bitmap && (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bs)) { - return bs->dirty_bitmap[chunk / (sizeof(unsigned long) * 8)] & - (1 << (chunk % (sizeof(unsigned long) * 8))); + return !!(bs->dirty_bitmap[chunk / (sizeof(unsigned long) * 8)] & + (1UL << (chunk % (sizeof(unsigned long) * 8)))); } else { return 0; } -- cgit v1.1 From 4dcafbb1eba2ee201ec86027982659b669f99c70 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 8 Nov 2010 17:02:55 -0200 Subject: block: set sector dirty on AIO write completion Sectors are marked dirty in the bitmap on AIO submission. This is wrong since data has not reached storage. Set a given sector as dirty in the dirty bitmap on AIO completion, so that reading a sector marked as dirty is guaranteed to return uptodate data. Reviewed-by: Kevin Wolf Signed-off-by: Marcelo Tosatti Signed-off-by: Anthony Liguori --- block.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/block.c b/block.c index 53a10de..63effd8 100644 --- a/block.c +++ b/block.c @@ -2031,12 +2031,49 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, return ret; } +typedef struct BlockCompleteData { + BlockDriverCompletionFunc *cb; + void *opaque; + BlockDriverState *bs; + int64_t sector_num; + int nb_sectors; +} BlockCompleteData; + +static void block_complete_cb(void *opaque, int ret) +{ + BlockCompleteData *b = opaque; + + if (b->bs->dirty_bitmap) { + set_dirty_bitmap(b->bs, b->sector_num, b->nb_sectors, 1); + } + b->cb(b->opaque, ret); + qemu_free(b); +} + +static BlockCompleteData *blk_dirty_cb_alloc(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, + BlockDriverCompletionFunc *cb, + void *opaque) +{ + BlockCompleteData *blkdata = qemu_mallocz(sizeof(BlockCompleteData)); + + blkdata->bs = bs; + blkdata->cb = cb; + blkdata->opaque = opaque; + blkdata->sector_num = sector_num; + blkdata->nb_sectors = nb_sectors; + + return blkdata; +} + BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { BlockDriver *drv = bs->drv; BlockDriverAIOCB *ret; + BlockCompleteData *blk_cb_data; trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque); @@ -2048,7 +2085,10 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, return NULL; if (bs->dirty_bitmap) { - set_dirty_bitmap(bs, sector_num, nb_sectors, 1); + blk_cb_data = blk_dirty_cb_alloc(bs, sector_num, nb_sectors, cb, + opaque); + cb = &block_complete_cb; + opaque = blk_cb_data; } ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors, -- cgit v1.1 From 33656af70230d5ccebe29e2f3bee38afe17db9b2 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 8 Nov 2010 17:02:56 -0200 Subject: block migration: do not submit multiple AIOs for same sector Block migration can submit multiple AIO reads for the same sector/chunk, but completion of such reads can happen out of order: migration guest - get_dirty(N) - aio_read(N) - clear_dirty(N) write(N) set_dirty(N) - get_dirty(N) - aio_read(N) If the first aio_read completes after the second, stale data will be migrated to the destination. Fix by not allowing multiple AIOs inflight for the same sector. Signed-off-by: Marcelo Tosatti Signed-off-by: Anthony Liguori --- block-migration.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/block-migration.c b/block-migration.c index 0bfdb73..3e66f49 100644 --- a/block-migration.c +++ b/block-migration.c @@ -49,12 +49,14 @@ typedef struct BlkMigDevState { int64_t total_sectors; int64_t dirty; QSIMPLEQ_ENTRY(BlkMigDevState) entry; + unsigned long *aio_bitmap; } BlkMigDevState; typedef struct BlkMigBlock { uint8_t *buf; BlkMigDevState *bmds; int64_t sector; + int nr_sectors; struct iovec iov; QEMUIOVector qiov; BlockDriverAIOCB *aiocb; @@ -140,6 +142,57 @@ static inline long double compute_read_bwidth(void) return (block_mig_state.reads * BLOCK_SIZE)/ block_mig_state.total_time; } +static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector) +{ + int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK; + + if (bmds->aio_bitmap && + (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) { + return !!(bmds->aio_bitmap[chunk / (sizeof(unsigned long) * 8)] & + (1UL << (chunk % (sizeof(unsigned long) * 8)))); + } else { + return 0; + } +} + +static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num, + int nb_sectors, int set) +{ + int64_t start, end; + unsigned long val, idx, bit; + + start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK; + end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK; + + for (; start <= end; start++) { + idx = start / (sizeof(unsigned long) * 8); + bit = start % (sizeof(unsigned long) * 8); + val = bmds->aio_bitmap[idx]; + if (set) { + if (!(val & (1UL << bit))) { + val |= 1UL << bit; + } + } else { + if (val & (1UL << bit)) { + val &= ~(1UL << bit); + } + } + bmds->aio_bitmap[idx] = val; + } +} + +static void alloc_aio_bitmap(BlkMigDevState *bmds) +{ + BlockDriverState *bs = bmds->bs; + int64_t bitmap_size; + + bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) + + BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1; + bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * 8; + + bmds->aio_bitmap = qemu_mallocz(bitmap_size); +} + static void blk_mig_read_cb(void *opaque, int ret) { BlkMigBlock *blk = opaque; @@ -151,6 +204,7 @@ static void blk_mig_read_cb(void *opaque, int ret) add_avg_read_time(blk->time); QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry); + bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0); block_mig_state.submitted--; block_mig_state.read_done++; @@ -194,6 +248,7 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f, blk->buf = qemu_malloc(BLOCK_SIZE); blk->bmds = bmds; blk->sector = cur_sector; + blk->nr_sectors = nr_sectors; blk->iov.iov_base = blk->buf; blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE; @@ -248,6 +303,7 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs) bmds->total_sectors = sectors; bmds->completed_sectors = 0; bmds->shared_base = block_mig_state.shared_base; + alloc_aio_bitmap(bmds); block_mig_state.total_sector_sum += sectors; @@ -329,6 +385,8 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, int nr_sectors; for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) { + if (bmds_aio_inflight(bmds, sector)) + qemu_aio_flush(); if (bdrv_get_dirty(bmds->bs, sector)) { if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) { @@ -340,6 +398,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, blk->buf = qemu_malloc(BLOCK_SIZE); blk->bmds = bmds; blk->sector = sector; + blk->nr_sectors = nr_sectors; if (is_async) { blk->iov.iov_base = blk->buf; @@ -354,6 +413,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, goto error; } block_mig_state.submitted++; + bmds_set_aio_inflight(bmds, sector, nr_sectors, 1); } else { if (bdrv_read(bmds->bs, sector, blk->buf, nr_sectors) < 0) { @@ -474,6 +534,7 @@ static void blk_mig_cleanup(Monitor *mon) while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) { QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry); + qemu_free(bmds->aio_bitmap); qemu_free(bmds); } -- cgit v1.1 From e71e00ed258202052570ae631536f4d7b65792fa Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 12 Nov 2010 12:55:46 -0200 Subject: Makefile: Fix check dependency breakage Commit b152aa84d52882bb1846485a89baf13aa07c86bc broke the unit-tests build, fix it. Signed-off-by: Luiz Capitulino Signed-off-by: Anthony Liguori --- Makefile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 747e47c..4e120a2 100644 --- a/Makefile +++ b/Makefile @@ -163,12 +163,14 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS) -check-qint: check-qint.o qint.o qemu-malloc.o $(trace-obj-y) -check-qstring: check-qstring.o qstring.o qemu-malloc.o $(trace-obj-y) -check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o $(trace-obj-y) -check-qlist: check-qlist.o qlist.o qint.o qemu-malloc.o $(trace-obj-y) -check-qfloat: check-qfloat.o qfloat.o qemu-malloc.o $(trace-obj-y) -check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o qemu-malloc.o $(trace-obj-y) +CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y) + +check-qint: check-qint.o qint.o $(CHECK_PROG_DEPS) +check-qstring: check-qstring.o qstring.o $(CHECK_PROG_DEPS) +check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(CHECK_PROG_DEPS) +check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS) +check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS) +check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS) clean: # avoid old build problems by removing potentially incorrect old files -- cgit v1.1 From 33bbd1de5ec9b8802d63e811908f2351ba83884c Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 16 Nov 2010 16:33:17 +0200 Subject: optionrom: fix bugs in signrom.sh signrom.sh has multiple bugs: - the last byte is considered when calculating the existing checksum, but not when computing the correction - apprently the 'expr' expression overflows and produces incorrect results with larger roms - if the checksum happened to be zero, we calculated the correction byte to be 256 Instead of rewriting this in half a line of python, this patch fixes the bugs. Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- pc-bios/optionrom/signrom.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pc-bios/optionrom/signrom.sh b/pc-bios/optionrom/signrom.sh index 975b27d..9dc5c63 100755 --- a/pc-bios/optionrom/signrom.sh +++ b/pc-bios/optionrom/signrom.sh @@ -31,14 +31,13 @@ x=`dd if="$1" bs=1 count=1 skip=2 2>/dev/null | od -t u1 -A n` size=$(( $x * 512 - 1 )) # now get the checksum -nums=`od -A n -t u1 -v "$1"` +nums=`od -A n -t u1 -v -N $size "$1"` for i in ${nums}; do # add each byte's value to sum - sum=`expr $sum + $i` + sum=`expr \( $sum + $i \) % 256` done -sum=$(( $sum % 256 )) -sum=$(( 256 - $sum )) +sum=$(( (256 - $sum) % 256 )) sum_octal=$( printf "%o" $sum ) # and write the output file -- cgit v1.1 From 0550f9c1b58896a6ca1d1256e26c78f84de2ed55 Mon Sep 17 00:00:00 2001 From: Bernhard Kohl Date: Tue, 16 Nov 2010 13:28:37 +0100 Subject: pc: disable the BOCHS BIOS panic port We have an OS which writes to port 0x400 when probing for special hardware. This causes an exit of the VM. With SeaBIOS this port isn't used anyway. Signed-off-by: Alexander Graf Reviewed-By: Paolo Bonzini Signed-off-by: Bernhard Kohl Signed-off-by: Anthony Liguori --- hw/pc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index c34d194..119c110 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -430,8 +430,8 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) /* Bochs BIOS messages */ case 0x400: case 0x401: - fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val); - exit(1); + /* used to be panic, now unused */ + break; case 0x402: case 0x403: #ifdef DEBUG_BIOS -- cgit v1.1 From 9eca6cc64392b4ad8bd8723e840f491fa36524ad Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 15 Nov 2010 21:15:26 +0100 Subject: slirp: Remove unused code for bad sprintf Neither DECLARE_SPRINTF nor BAD_SPRINTF are needed for QEMU. QEMU won't support systems with missing or bad declarations for sprintf. The unused code was detected while looking for functions with missing format checking. Instead of adding GCC_FMT_ATTR, the unused code was removed. Cc: Blue Swirl Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- slirp/misc.c | 42 ------------------------------------------ slirp/slirp.h | 14 -------------- slirp/slirp_config.h | 6 ------ 3 files changed, 62 deletions(-) diff --git a/slirp/misc.c b/slirp/misc.c index 1aeb401..19dbec4 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -264,48 +264,6 @@ void lprint(const char *format, ...) va_end(args); } -#ifdef BAD_SPRINTF - -#undef vsprintf -#undef sprintf - -/* - * Some BSD-derived systems have a sprintf which returns char * - */ - -int -vsprintf_len(string, format, args) - char *string; - const char *format; - va_list args; -{ - vsprintf(string, format, args); - return strlen(string); -} - -int -#ifdef __STDC__ -sprintf_len(char *string, const char *format, ...) -#else -sprintf_len(va_alist) va_dcl -#endif -{ - va_list args; -#ifdef __STDC__ - va_start(args, format); -#else - char *string; - char *format; - va_start(args); - string = va_arg(args, char *); - format = va_arg(args, char *); -#endif - vsprintf(string, format, args); - return strlen(string); -} - -#endif - void u_sleep(int usec) { diff --git a/slirp/slirp.h b/slirp/slirp.h index 462292d..dfd977a 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -237,20 +237,6 @@ void if_start(Slirp *); void if_start(struct ttys *); #endif -#ifdef BAD_SPRINTF -# define vsprintf vsprintf_len -# define sprintf sprintf_len - extern int vsprintf_len(char *, const char *, va_list); - extern int sprintf_len(char *, const char *, ...); -#endif - -#ifdef DECLARE_SPRINTF -# ifndef BAD_SPRINTF - extern int vsprintf(char *, const char *, va_list); -# endif - extern int vfprintf(FILE *, const char *, va_list); -#endif - #ifndef HAVE_STRERROR extern char *strerror(int error); #endif diff --git a/slirp/slirp_config.h b/slirp/slirp_config.h index f19c703..18db45c 100644 --- a/slirp/slirp_config.h +++ b/slirp/slirp_config.h @@ -85,9 +85,6 @@ /* Define if the machine is big endian */ //#undef HOST_WORDS_BIGENDIAN -/* Define if your sprintf returns char * instead of int */ -#undef BAD_SPRINTF - /* Define if you have readv */ #undef HAVE_READV @@ -97,9 +94,6 @@ #define DECLARE_IOVEC #endif -/* Define if a declaration of sprintf/fprintf is needed */ -#undef DECLARE_SPRINTF - /* Define if you have a POSIX.1 sys/wait.h */ #undef HAVE_SYS_WAIT_H -- cgit v1.1 From 0b2c508856fa23695900c29b6ada57c07843bc6f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 15 Nov 2010 21:17:06 +0100 Subject: trace: Use fprintf_function (format checking) fprintf_function adds format checking with GCC_FMT_ATTR. Cc: Blue Swirl Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- simpletrace.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/simpletrace.h b/simpletrace.h index 72614ec..2f44ed3 100644 --- a/simpletrace.h +++ b/simpletrace.h @@ -29,10 +29,10 @@ void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3); void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4); 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, int (*stream_printf)(FILE *stream, const char *fmt, ...)); -void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)); +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, int (*stream_printf)(FILE *stream, const char *fmt, ...)); +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); -- cgit v1.1 From b903a0f721f28283e5eaab00a3cb2ada96c2eae0 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 11 Nov 2010 12:59:25 +0100 Subject: pc: add 0.13 pc machine type Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/pc_piix.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 12359a7..e17e878 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -212,7 +212,7 @@ static void pc_init_isa(ram_addr_t ram_size, } static QEMUMachine pc_machine = { - .name = "pc-0.13", + .name = "pc-0.14", .alias = "pc", .desc = "Standard PC", .init = pc_init_pci, @@ -220,6 +220,13 @@ static QEMUMachine pc_machine = { .is_default = 1, }; +static QEMUMachine pc_machine_v0_13 = { + .name = "pc-0.13", + .desc = "Standard PC", + .init = pc_init_pci, + .max_cpus = 255, +}; + static QEMUMachine pc_machine_v0_12 = { .name = "pc-0.12", .desc = "Standard PC", @@ -331,6 +338,7 @@ static QEMUMachine isapc_machine = { static void pc_machine_init(void) { qemu_register_machine(&pc_machine); + qemu_register_machine(&pc_machine_v0_13); qemu_register_machine(&pc_machine_v0_12); qemu_register_machine(&pc_machine_v0_11); qemu_register_machine(&pc_machine_v0_10); -- cgit v1.1 From 9dbcca5aa13cb9ab40788ac4c56bc227d94ca920 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 11 Nov 2010 12:59:26 +0100 Subject: virtfs: enable MSI-X This patch enables MSI-X for virtfs-9p-pci. It also adds a compat property to pc-0.13 which turns it of there to stay compatible to 0.13-stable. Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/pc_piix.c | 8 ++++++++ hw/virtio-pci.c | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index e17e878..31c80d2 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -225,6 +225,14 @@ static QEMUMachine pc_machine_v0_13 = { .desc = "Standard PC", .init = pc_init_pci, .max_cpus = 255, + .compat_props = (GlobalProperty[]) { + { + .driver = "virtio-9p-pci", + .property = "vectors", + .value = stringify(0), + }, + { /* end of list */ } + }, }; static QEMUMachine pc_machine_v0_12 = { diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 729917d..3610d7e 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -684,12 +684,14 @@ static int virtio_9p_init_pci(PCIDevice *pci_dev) VirtIODevice *vdev; vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf); + vdev->nvectors = proxy->nvectors; virtio_init_pci(proxy, vdev, PCI_VENDOR_ID_REDHAT_QUMRANET, 0x1009, 0x2, 0x00); - + /* make the actual value visible */ + proxy->nvectors = vdev->nvectors; return 0; } #endif @@ -758,6 +760,7 @@ static PCIDeviceInfo virtio_info[] = { .qdev.size = sizeof(VirtIOPCIProxy), .init = virtio_9p_init_pci, .qdev.props = (Property[]) { + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag), DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id), -- cgit v1.1 From 94b0b5ff5f5c3ab946fa926d464738edb3713ed4 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 16 Nov 2010 12:20:25 +0000 Subject: trace: Trace vm_start()/vm_stop() VM state change notifications are invoked from vm_start()/vm_stop(). Trace these state changes so we can reason about the state of the VM from trace output. Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori --- trace-events | 3 +++ vl.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/trace-events b/trace-events index 947f8b0..da03d4b 100644 --- a/trace-events +++ b/trace-events @@ -189,3 +189,6 @@ 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"" + +# vl.c +disable vm_state_notify(int running, int reason) "running %d reason %d" diff --git a/vl.c b/vl.c index 9ee6479..805e11f 100644 --- a/vl.c +++ b/vl.c @@ -158,6 +158,7 @@ int main(int argc, char **argv) #include "slirp/libslirp.h" +#include "trace.h" #include "qemu-queue.h" #include "cpus.h" #include "arch_init.h" @@ -1074,6 +1075,8 @@ void vm_state_notify(int running, int reason) { VMChangeStateEntry *e; + trace_vm_state_notify(running, reason); + for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) { e->cb(e->opaque, running, reason); } -- cgit v1.1 From acd1c812b5548c8426e093075362b6d4119db6ac Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 17 Nov 2010 11:50:09 +0200 Subject: Type-safe ioport callbacks The current ioport callbacks are not type-safe, in that they accept an "opaque" pointer as an argument whose type must match the argument to the registration function; this is not checked by the compiler. This patch adds an alternative that is type-safe. Instead of an opaque argument, both registation and the callback use a new IOPort type. The callback then uses container_of() to access its main structures. Currently the old and new methods exist side by side; once the old way is gone, we can also save a bunch of memory since the new method requires one pointer per ioport instead of 6. Acked-by: Anthony Liguori Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- ioport.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioport.h | 2 ++ iorange.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 iorange.h diff --git a/ioport.c b/ioport.c index ec3dc65..aa4188a 100644 --- a/ioport.c +++ b/ioport.c @@ -174,6 +174,70 @@ int register_ioport_write(pio_addr_t start, int length, int size, return 0; } +static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 1, &data); + return data; +} + +static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 2, &data); + return data; +} + +static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 4, &data); + return data; +} + +static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 1, data); +} + +static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 2, data); +} + +static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 4, data); +} + +void ioport_register(IORange *ioport) +{ + register_ioport_read(ioport->base, ioport->len, 1, + ioport_readb_thunk, ioport); + register_ioport_read(ioport->base, ioport->len, 2, + ioport_readw_thunk, ioport); + register_ioport_read(ioport->base, ioport->len, 4, + ioport_readl_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 1, + ioport_writeb_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 2, + ioport_writew_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 4, + ioport_writel_thunk, ioport); +} + void isa_unassign_ioport(pio_addr_t start, int length) { int i; diff --git a/ioport.h b/ioport.h index 3d3c8a3..5ae62a3 100644 --- a/ioport.h +++ b/ioport.h @@ -25,6 +25,7 @@ #define IOPORT_H #include "qemu-common.h" +#include "iorange.h" typedef uint32_t pio_addr_t; #define FMT_pioaddr PRIx32 @@ -36,6 +37,7 @@ typedef uint32_t pio_addr_t; typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); +void ioport_register(IORange *iorange); int register_ioport_read(pio_addr_t start, int length, int size, IOPortReadFunc *func, void *opaque); int register_ioport_write(pio_addr_t start, int length, int size, diff --git a/iorange.h b/iorange.h new file mode 100644 index 0000000..9783168 --- /dev/null +++ b/iorange.h @@ -0,0 +1,30 @@ +#ifndef IORANGE_H +#define IORANGE_H + +#include + +typedef struct IORange IORange; +typedef struct IORangeOps IORangeOps; + +struct IORangeOps { + void (*read)(IORange *iorange, uint64_t offset, unsigned width, + uint64_t *data); + void (*write)(IORange *iorange, uint64_t offset, unsigned width, + uint64_t data); +}; + +struct IORange { + const IORangeOps *ops; + uint64_t base; + uint64_t len; +}; + +static inline void iorange_init(IORange *iorange, const IORangeOps *ops, + uint64_t base, uint64_t len) +{ + iorange->ops = ops; + iorange->base = base; + iorange->len = len; +} + +#endif -- cgit v1.1 From 2871a3f6b64966bc78fce0d4033bf32fcd42401c Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 17 Nov 2010 11:50:10 +0200 Subject: piix4 acpi: convert io BAR to type-safe ioport callbacks Acked-by: Anthony Liguori Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- hw/acpi_piix4.c | 55 ++++++++++++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index f549089..173d781 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -52,6 +52,7 @@ struct pci_status { typedef struct PIIX4PMState { PCIDevice dev; + IORange ioport; uint16_t pmsts; uint16_t pmen; uint16_t pmcntrl; @@ -128,10 +129,16 @@ static void pm_tmr_timer(void *opaque) pm_update_sci(s); } -static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) +static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width, + uint64_t val) { - PIIX4PMState *s = opaque; - addr &= 0x3f; + PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport); + + if (width != 2) { + PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n", + (unsigned)addr, width, (unsigned)val); + } + switch(addr) { case 0x00: { @@ -184,12 +191,12 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", addr, val); } -static uint32_t pm_ioport_readw(void *opaque, uint32_t addr) +static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width, + uint64_t *data) { - PIIX4PMState *s = opaque; + PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport); uint32_t val; - addr &= 0x3f; switch(addr) { case 0x00: val = get_pmsts(s); @@ -200,27 +207,6 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr) case 0x04: val = s->pmcntrl; break; - default: - val = 0; - break; - } - PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val); - return val; -} - -static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val) -{ - // PIIX4PMState *s = opaque; - PIIX4_DPRINTF("PM writel port=0x%04x val=0x%08x\n", addr & 0x3f, val); -} - -static uint32_t pm_ioport_readl(void *opaque, uint32_t addr) -{ - PIIX4PMState *s = opaque; - uint32_t val; - - addr &= 0x3f; - switch(addr) { case 0x08: val = get_pmtmr(s); break; @@ -228,10 +214,15 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr) val = 0; break; } - PIIX4_DPRINTF("PM readl port=0x%04x val=0x%08x\n", addr, val); - return val; + PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val); + *data = val; } +static const IORangeOps pm_iorange_ops = { + .read = pm_ioport_read, + .write = pm_ioport_write, +}; + static void apm_ctrl_changed(uint32_t val, void *arg) { PIIX4PMState *s = arg; @@ -265,10 +256,8 @@ static void pm_io_space_update(PIIX4PMState *s) /* XXX: need to improve memory and ioport allocation */ PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base); - register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s); - register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s); - register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s); - register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s); + iorange_init(&s->ioport, &pm_iorange_ops, pm_io_base, 64); + ioport_register(&s->ioport); } } -- cgit v1.1 From c1ded3dc9f2d6caeb62eb3005510837a62b795d2 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 19 Oct 2010 17:03:24 +0200 Subject: pcnet: Do not receive external frames in loopback mode While not explicitly stated in the spec, it was observed on real systems that enabling loopback testing on the pcnet controller disables reception of external frames. And some legacy software relies on it, so provide this behavior. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- hw/pcnet.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/pcnet.c b/hw/pcnet.c index b52935a..f970bda 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -1048,9 +1048,10 @@ ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_) int crc_err = 0; int size = size_; - if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size) + if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size || + (CSR_LOOP(s) && !s->looptest)) { return -1; - + } #ifdef PCNET_DEBUG printf("pcnet_receive size=%d\n", size); #endif -- cgit v1.1 From 281a26b15b4adcecb8604216738975abd754bea8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Nov 2010 12:06:44 +0100 Subject: vgabios update: handle compatibility with older qemu versions As pointed out by avi the vgabios update is guest-visible and thus has migration implications. One change is that the vga has a valid pci rom bar now. We already have a pci bus property to enable/disable the rom bar and we'll load the bios via fw_cfg as fallback for the no-rom-bar case. So we just have to add compat properties to handle this case. A second change is that the magic bochs lfb @ 0xe0000000 is gone. When live-migrating a guest from a older qemu version it might be using the lfb though, so we have to keep it for the old machine types. The patch enables the bochs lfb in case we don't have the pci rom bar enabled (i.e. we are in 0.13+older compat mode). This patch depends on these patches which add (and use) the pc-0.13 machine type: http://patchwork.ozlabs.org/patch/70797/ http://patchwork.ozlabs.org/patch/70798/ Signed-off-by: Gerd Hoffmann Cc: avi@redhat.com Signed-off-by: Anthony Liguori --- hw/pc_piix.c | 16 ++++++++++++++++ hw/vga-pci.c | 5 +++++ hw/vmware_vga.c | 5 +++++ 3 files changed, 26 insertions(+) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 31c80d2..7d29d43 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -230,6 +230,14 @@ static QEMUMachine pc_machine_v0_13 = { .driver = "virtio-9p-pci", .property = "vectors", .value = stringify(0), + },{ + .driver = "VGA", + .property = "rombar", + .value = stringify(0), + },{ + .driver = "vmware-svga", + .property = "rombar", + .value = stringify(0), }, { /* end of list */ } }, @@ -249,6 +257,14 @@ static QEMUMachine pc_machine_v0_12 = { .driver = "virtio-serial-pci", .property = "vectors", .value = stringify(0), + },{ + .driver = "VGA", + .property = "rombar", + .value = stringify(0), + },{ + .driver = "vmware-svga", + .property = "rombar", + .value = stringify(0), }, { /* end of list */ } } diff --git a/hw/vga-pci.c b/hw/vga-pci.c index b09789c..791ca22 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -92,6 +92,11 @@ static int pci_vga_initfn(PCIDevice *dev) pci_register_bar(&d->dev, 0, VGA_RAM_SIZE, PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map); + if (!dev->rom_bar) { + /* compatibility with pc-0.13 and older */ + vga_init_vbe(s); + } + return 0; } diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 9337fdb..d0f4e1b 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1301,6 +1301,11 @@ static int pci_vmsvga_initfn(PCIDevice *dev) vmsvga_init(&s->chip, VGA_RAM_SIZE); + if (!dev->rom_bar) { + /* compatibility with pc-0.13 and older */ + vga_init_vbe(&s->chip.vga); + } + return 0; } -- cgit v1.1 From 870cef1dae88f131ee3e17fe0aaf45d609798ce1 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 15 Nov 2010 20:44:35 +0000 Subject: virtio-blk: Convert fprintf() to error_report() Errors should be logged using error_report() so they go to the appropriate monitor. Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori --- hw/virtio-blk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 49528a9..e5f9b27 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -324,13 +324,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) { if (req->elem.out_num < 1 || req->elem.in_num < 1) { - fprintf(stderr, "virtio-blk missing headers\n"); + error_report("virtio-blk missing headers"); exit(1); } if (req->elem.out_sg[0].iov_len < sizeof(*req->out) || req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) { - fprintf(stderr, "virtio-blk header not in correct element\n"); + error_report("virtio-blk header not in correct element"); exit(1); } -- cgit v1.1 From cd92f4cc22fbe12a7bf60c9430731f768dc1537c Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 15 Nov 2010 20:44:36 +0000 Subject: virtio: Convert fprintf() to error_report() Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori --- hw/virtio.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/hw/virtio.c b/hw/virtio.c index a2a657e..849a60f 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -14,6 +14,7 @@ #include #include "trace.h" +#include "qemu-error.h" #include "virtio.h" #include "sysemu.h" @@ -253,8 +254,8 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx) /* Check it isn't doing very strange things with descriptor numbers. */ if (num_heads > vq->vring.num) { - fprintf(stderr, "Guest moved used index from %u to %u", - idx, vring_avail_idx(vq)); + error_report("Guest moved used index from %u to %u", + idx, vring_avail_idx(vq)); exit(1); } @@ -271,7 +272,7 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx) /* If their number is silly, that's a fatal mistake. */ if (head >= vq->vring.num) { - fprintf(stderr, "Guest says index %u is available", head); + error_report("Guest says index %u is available", head); exit(1); } @@ -293,7 +294,7 @@ static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa, wmb(); if (next >= max) { - fprintf(stderr, "Desc next is %u", next); + error_report("Desc next is %u", next); exit(1); } @@ -320,13 +321,13 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) { if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) { - fprintf(stderr, "Invalid size for indirect buffer table\n"); + error_report("Invalid size for indirect buffer table"); exit(1); } /* If we've got too many, that implies a descriptor loop. */ if (num_bufs >= max) { - fprintf(stderr, "Looped descriptor"); + error_report("Looped descriptor"); exit(1); } @@ -340,7 +341,7 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) do { /* If we've got too many, that implies a descriptor loop. */ if (++num_bufs > max) { - fprintf(stderr, "Looped descriptor"); + error_report("Looped descriptor"); exit(1); } @@ -374,7 +375,7 @@ void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr, len = sg[i].iov_len; sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write); if (sg[i].iov_base == NULL || len != sg[i].iov_len) { - fprintf(stderr, "virtio: trying to map MMIO memory\n"); + error_report("virtio: trying to map MMIO memory"); exit(1); } } @@ -397,7 +398,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) { if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) { - fprintf(stderr, "Invalid size for indirect buffer table\n"); + error_report("Invalid size for indirect buffer table"); exit(1); } @@ -423,7 +424,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) /* If we've got too many, that implies a descriptor loop. */ if ((elem->in_num + elem->out_num) > max) { - fprintf(stderr, "Looped descriptor"); + error_report("Looped descriptor"); exit(1); } } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max); @@ -694,8 +695,8 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) qemu_get_be16s(f, &vdev->queue_sel); qemu_get_be32s(f, &features); if (features & ~supported_features) { - fprintf(stderr, "Features 0x%x unsupported. Allowed features: 0x%x\n", - features, supported_features); + error_report("Features 0x%x unsupported. Allowed features: 0x%x", + features, supported_features); return -1; } if (vdev->set_features) @@ -717,11 +718,11 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) num_heads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx; /* Check it isn't doing very strange things with descriptor numbers. */ if (num_heads > vdev->vq[i].vring.num) { - fprintf(stderr, "VQ %d size 0x%x Guest index 0x%x " - "inconsistent with Host index 0x%x: delta 0x%x\n", - i, vdev->vq[i].vring.num, - vring_avail_idx(&vdev->vq[i]), - vdev->vq[i].last_avail_idx, num_heads); + error_report("VQ %d size 0x%x Guest index 0x%x " + "inconsistent with Host index 0x%x: delta 0x%x", + i, vdev->vq[i].vring.num, + vring_avail_idx(&vdev->vq[i]), + vdev->vq[i].last_avail_idx, num_heads); return -1; } if (vdev->binding->load_queue) { -- cgit v1.1 From e7b43f7e60a0a170356e82b01b8ffdcecafad7ed Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 15 Nov 2010 20:44:37 +0000 Subject: virtio-net: Convert fprintf() to error_report() Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori --- hw/virtio-net.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 7e1688c..1d61f19 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -120,8 +120,8 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status) if (!n->vhost_started) { int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev); if (r < 0) { - fprintf(stderr, "unable to start vhost net: %d: " - "falling back on userspace virtio\n", -r); + error_report("unable to start vhost net: %d: " + "falling back on userspace virtio", -r); } else { n->vhost_started = 1; } @@ -271,7 +271,7 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, uint8_t on; if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(on)) { - fprintf(stderr, "virtio-net ctrl invalid rx mode command\n"); + error_report("virtio-net ctrl invalid rx mode command"); exit(1); } @@ -353,7 +353,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd, uint16_t vid; if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(vid)) { - fprintf(stderr, "virtio-net ctrl invalid vlan command\n"); + error_report("virtio-net ctrl invalid vlan command"); return VIRTIO_NET_ERR; } @@ -381,13 +381,13 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) while (virtqueue_pop(vq, &elem)) { if ((elem.in_num < 1) || (elem.out_num < 1)) { - fprintf(stderr, "virtio-net ctrl missing headers\n"); + error_report("virtio-net ctrl missing headers"); exit(1); } if (elem.out_sg[0].iov_len < sizeof(ctrl) || elem.in_sg[elem.in_num - 1].iov_len < sizeof(status)) { - fprintf(stderr, "virtio-net ctrl header not in correct element\n"); + error_report("virtio-net ctrl header not in correct element"); exit(1); } @@ -591,21 +591,21 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_ if (virtqueue_pop(n->rx_vq, &elem) == 0) { if (i == 0) return -1; - fprintf(stderr, "virtio-net unexpected empty queue: " + error_report("virtio-net unexpected empty queue: " "i %zd mergeable %d offset %zd, size %zd, " - "guest hdr len %zd, host hdr len %zd guest features 0x%x\n", + "guest hdr len %zd, host hdr len %zd guest features 0x%x", i, n->mergeable_rx_bufs, offset, size, guest_hdr_len, host_hdr_len, n->vdev.guest_features); exit(1); } if (elem.in_num < 1) { - fprintf(stderr, "virtio-net receive queue contains no in buffers\n"); + error_report("virtio-net receive queue contains no in buffers"); exit(1); } if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != guest_hdr_len) { - fprintf(stderr, "virtio-net header not in first element\n"); + error_report("virtio-net header not in first element"); exit(1); } @@ -630,12 +630,11 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_ * Otherwise, drop it. */ if (!n->mergeable_rx_bufs && offset < size) { #if 0 - fprintf(stderr, "virtio-net truncated non-mergeable packet: " - - "i %zd mergeable %d offset %zd, size %zd, " - "guest hdr len %zd, host hdr len %zd\n", - i, n->mergeable_rx_bufs, - offset, size, guest_hdr_len, host_hdr_len); + error_report("virtio-net truncated non-mergeable packet: " + "i %zd mergeable %d offset %zd, size %zd, " + "guest hdr len %zd, host hdr len %zd", + i, n->mergeable_rx_bufs, + offset, size, guest_hdr_len, host_hdr_len); #endif return size; } @@ -695,7 +694,7 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) sizeof(struct virtio_net_hdr); if (out_num < 1 || out_sg->iov_len != hdr_len) { - fprintf(stderr, "virtio-net header not in first element\n"); + error_report("virtio-net header not in first element"); exit(1); } @@ -981,10 +980,10 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf, n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx); if (net->tx && strcmp(net->tx, "timer") && strcmp(net->tx, "bh")) { - fprintf(stderr, "virtio-net: " - "Unknown option tx=%s, valid options: \"timer\" \"bh\"\n", - net->tx); - fprintf(stderr, "Defaulting to \"bh\"\n"); + error_report("virtio-net: " + "Unknown option tx=%s, valid options: \"timer\" \"bh\"", + net->tx); + error_report("Defaulting to \"bh\""); } if (net->tx && !strcmp(net->tx, "timer")) { -- cgit v1.1 From 4e02d460dd4b60847a1e8b689cb676e3e1f3de95 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 15 Nov 2010 20:44:38 +0000 Subject: virtio-pci: Convert fprintf() to error_report() Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori --- hw/virtio-pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 3610d7e..c65765a 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -254,8 +254,8 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) virtio_queue_set_vector(vdev, vdev->queue_sel, val); break; default: - fprintf(stderr, "%s: unexpected address 0x%x value 0x%x\n", - __func__, addr, val); + error_report("%s: unexpected address 0x%x value 0x%x", + __func__, addr, val); break; } } -- cgit v1.1 From f711df67d611e4762966a249742a5f7499e19f99 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Nov 2010 14:57:52 -0800 Subject: microblaze: target-ify target_ucontext Rename the members of target_ucontext so that they don't conflict with possible host macros for ucontext members. This has already been done for the other targets. Signed-off-by: Richard Henderson Signed-off-by: Edgar E. Iglesias --- linux-user/signal.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 77683f7..7c62fac 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -3071,11 +3071,11 @@ struct target_stack_t { }; struct target_ucontext { - abi_ulong uc_flags; - abi_ulong uc_link; - struct target_stack_t uc_stack; - struct target_sigcontext sc; - uint32_t extramask[TARGET_NSIG_WORDS - 1]; + abi_ulong tuc_flags; + abi_ulong tuc_link; + struct target_stack_t tuc_stack; + struct target_sigcontext tuc_mcontext; + uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1]; }; /* Signal frames. */ @@ -3189,7 +3189,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, goto badframe; /* Save the mask. */ - err |= __put_user(set->sig[0], &frame->uc.sc.oldmask); + err |= __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask); if (err) goto badframe; @@ -3198,7 +3198,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, goto badframe; } - setup_sigcontext(&frame->uc.sc, env); + setup_sigcontext(&frame->uc.tuc_mcontext, env); /* Set up to return from userspace. If provided, use a stub already in userspace. */ @@ -3261,7 +3261,7 @@ long do_sigreturn(CPUState *env) goto badframe; /* Restore blocked signals */ - if (__get_user(target_set.sig[0], &frame->uc.sc.oldmask)) + if (__get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask)) goto badframe; for(i = 1; i < TARGET_NSIG_WORDS; i++) { if (__get_user(target_set.sig[i], &frame->extramask[i - 1])) @@ -3270,7 +3270,7 @@ long do_sigreturn(CPUState *env) target_to_host_sigset_internal(&set, &target_set); sigprocmask(SIG_SETMASK, &set, NULL); - restore_sigcontext(&frame->uc.sc, env); + restore_sigcontext(&frame->uc.tuc_mcontext, env); /* We got here through a sigreturn syscall, our path back is via an rtb insn so setup r14 for that. */ env->regs[14] = env->sregs[SR_PC]; -- cgit v1.1 From 6fa2c95f279dda62aa7e3292cc424ff3fab6a602 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 12 Nov 2010 09:57:11 +0000 Subject: scsi-disk: Move active request asserts SCSI read/write requests should not be re-issued before the current fragment of I/O completes. There are asserts in scsi-disk.c that guard this constraint but they trigger on SPARC Linux 2.4. It turns out that the asserts are too early in the code path and don't allow for read requests to terminate. Only the read assert needs to be moved but move the write assert too for consistency. Reported-by: Nigel Horne Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/scsi-disk.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index dc71957..7d85899 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -170,6 +170,9 @@ static void scsi_read_request(SCSIDiskReq *r) return; } + /* No data transfer may already be in progress */ + assert(r->req.aiocb == NULL); + n = r->sector_count; if (n > SCSI_DMA_BUF_SIZE / 512) n = SCSI_DMA_BUF_SIZE / 512; @@ -197,9 +200,6 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag) return; } - /* No data transfer may already be in progress */ - assert(r->req.aiocb == NULL); - scsi_read_request(r); } @@ -269,6 +269,9 @@ static void scsi_write_request(SCSIDiskReq *r) SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); uint32_t n; + /* No data transfer may already be in progress */ + assert(r->req.aiocb == NULL); + n = r->iov.iov_len / 512; if (n) { qemu_iovec_init_external(&r->qiov, &r->iov, 1); @@ -298,9 +301,6 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag) return 1; } - /* No data transfer may already be in progress */ - assert(r->req.aiocb == NULL); - scsi_write_request(r); return 0; -- cgit v1.1 From 9063f81415f3518ef8206e74085c2a92c96890a0 Mon Sep 17 00:00:00 2001 From: Ryan Harper Date: Fri, 12 Nov 2010 11:07:13 -0600 Subject: Implement drive_del to decouple block removal from device removal Currently device hotplug removal code is tied to device removal via ACPI. All pci devices that are removable via device_del() require the guest to respond to the request. In some cases the guest may not respond leaving the device still accessible to the guest. The management layer doesn't currently have a reliable way to revoke access to host resource in the presence of an uncooperative guest. This patch implements a new monitor command, drive_del, which provides an explicit command to revoke access to a host block device. drive_del first quiesces the block device (qemu_aio_flush; bdrv_flush() and bdrv_close()). This prevents further IO from being submitted against the host device. Finally, drive_del cleans up pointers between the drive object (host resource) and the device object (guest resource). Signed-off-by: Ryan Harper Signed-off-by: Kevin Wolf --- blockdev.c | 39 +++++++++++++++++++++++++++++++++++++++ blockdev.h | 1 + hmp-commands.hx | 18 ++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/blockdev.c b/blockdev.c index 6cb179a..f6ac439 100644 --- a/blockdev.c +++ b/blockdev.c @@ -14,6 +14,8 @@ #include "qemu-option.h" #include "qemu-config.h" #include "sysemu.h" +#include "hw/qdev.h" +#include "block_int.h" static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); @@ -597,3 +599,40 @@ int do_change_block(Monitor *mon, const char *device, } return monitor_read_bdrv_key_start(mon, bs, NULL, NULL); } + +int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + const char *id = qdict_get_str(qdict, "id"); + BlockDriverState *bs; + BlockDriverState **ptr; + Property *prop; + + bs = bdrv_find(id); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, id); + return -1; + } + + /* quiesce block driver; prevent further io */ + qemu_aio_flush(); + bdrv_flush(bs); + bdrv_close(bs); + + /* clean up guest state from pointing to host resource by + * finding and removing DeviceState "drive" property */ + for (prop = bs->peer->info->props; prop && prop->name; prop++) { + if (prop->info->type == PROP_TYPE_DRIVE) { + ptr = qdev_get_prop_ptr(bs->peer, prop); + if ((*ptr) == bs) { + bdrv_detach(bs, bs->peer); + *ptr = NULL; + break; + } + } + } + + /* clean up host side */ + drive_uninit(drive_get_by_blockdev(bs)); + + return 0; +} diff --git a/blockdev.h b/blockdev.h index 653affc..2a0559e 100644 --- a/blockdev.h +++ b/blockdev.h @@ -51,5 +51,6 @@ int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data); int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data); int do_change_block(Monitor *mon, const char *device, const char *filename, const char *fmt); +int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data); #endif diff --git a/hmp-commands.hx b/hmp-commands.hx index e5585ba..23024ba 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -68,6 +68,24 @@ Eject a removable medium (use -f to force it). ETEXI { + .name = "drive_del", + .args_type = "id:s", + .params = "device", + .help = "remove host block device", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_drive_del, + }, + +STEXI +@item drive_del @var{device} +@findex drive_del +Remove host block device. The result is that guest generated IO is no longer +submitted against the host device underlying the disk. Once a drive has +been deleted, the QEMU Block layer returns -EIO which results in IO +errors in the guest for applications that are reading/writing to the device. +ETEXI + + { .name = "change", .args_type = "device:B,target:F,arg:s?", .params = "device filename [format]", -- cgit v1.1 From 62155e2b51e3c282ddc30adbb6d7b8d3bb7c386e Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 12 Nov 2010 16:07:50 -0200 Subject: block migration: do not submit multiple AIOs for same sector (v2) An old version of this patch was applied to master, so this contains the differences between v1 and v2. Signed-off-by: Marcelo Tosatti Signed-off-by: Kevin Wolf --- block-migration.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/block-migration.c b/block-migration.c index 3e66f49..1475325 100644 --- a/block-migration.c +++ b/block-migration.c @@ -146,8 +146,7 @@ static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector) { int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK; - if (bmds->aio_bitmap && - (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) { + if ((sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) { return !!(bmds->aio_bitmap[chunk / (sizeof(unsigned long) * 8)] & (1UL << (chunk % (sizeof(unsigned long) * 8)))); } else { @@ -169,13 +168,9 @@ static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num, bit = start % (sizeof(unsigned long) * 8); val = bmds->aio_bitmap[idx]; if (set) { - if (!(val & (1UL << bit))) { - val |= 1UL << bit; - } + val |= 1UL << bit; } else { - if (val & (1UL << bit)) { - val &= ~(1UL << bit); - } + val &= ~(1UL << bit); } bmds->aio_bitmap[idx] = val; } @@ -385,8 +380,9 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, int nr_sectors; for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) { - if (bmds_aio_inflight(bmds, sector)) + if (bmds_aio_inflight(bmds, sector)) { qemu_aio_flush(); + } if (bdrv_get_dirty(bmds->bs, sector)) { if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) { -- cgit v1.1 From 9fbef1ac7cc888f29435e9f636b5dd14cd3260df Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 21 Nov 2010 18:29:52 +0200 Subject: ide: convert bmdma address ioport to ioport_register() cmd646, via compile tested, pci lightly boot tested. Signed-off-by: Avi Kivity Signed-off-by: Kevin Wolf --- hw/ide/cmd646.c | 8 ++----- hw/ide/internal.h | 2 ++ hw/ide/pci.c | 71 ++++++++++++++----------------------------------------- hw/ide/pci.h | 7 +----- hw/ide/piix.c | 8 ++----- hw/ide/via.c | 8 ++----- 6 files changed, 27 insertions(+), 77 deletions(-) diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index ff80dd5..dfe6091 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -179,12 +179,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num, register_ioport_read(addr, 4, 1, bmdma_readb_1, d); } - register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm); - register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm); - register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm); - register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm); - register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm); - register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm); + iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4); + ioport_register(&bm->addr_ioport); addr += 8; } } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index d652e06..85f4a16 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -8,6 +8,7 @@ */ #include #include "block_int.h" +#include "iorange.h" /* debug IDE devices */ //#define DEBUG_IDE @@ -496,6 +497,7 @@ struct BMDMAState { QEMUIOVector qiov; int64_t sector_num; uint32_t nsector; + IORange addr_ioport; QEMUBH *bh; }; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index ec90f26..3722b77 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -73,72 +73,37 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) } } -uint32_t bmdma_addr_readb(void *opaque, uint32_t addr) +static void bmdma_addr_read(IORange *ioport, uint64_t addr, + unsigned width, uint64_t *data) { - BMDMAState *bm = opaque; - uint32_t val; - val = (bm->addr >> ((addr & 3) * 8)) & 0xff; -#ifdef DEBUG_IDE - printf("%s: 0x%08x\n", __func__, val); -#endif - return val; -} + BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport); + uint32_t mask = (1ULL << (width * 8)) - 1; -void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - BMDMAState *bm = opaque; - int shift = (addr & 3) * 8; + *data = (bm->addr >> (addr * 8)) & mask; #ifdef DEBUG_IDE - printf("%s: 0x%08x\n", __func__, val); + printf("%s: 0x%08x\n", __func__, (unsigned)*data); #endif - bm->addr &= ~(0xFF << shift); - bm->addr |= ((val & 0xFF) << shift) & ~3; - bm->cur_addr = bm->addr; } -uint32_t bmdma_addr_readw(void *opaque, uint32_t addr) +static void bmdma_addr_write(IORange *ioport, uint64_t addr, + unsigned width, uint64_t data) { - BMDMAState *bm = opaque; - uint32_t val; - val = (bm->addr >> ((addr & 3) * 8)) & 0xffff; -#ifdef DEBUG_IDE - printf("%s: 0x%08x\n", __func__, val); -#endif - return val; -} + BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport); + int shift = addr * 8; + uint32_t mask = (1ULL << (width * 8)) - 1; -void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val) -{ - BMDMAState *bm = opaque; - int shift = (addr & 3) * 8; #ifdef DEBUG_IDE - printf("%s: 0x%08x\n", __func__, val); + printf("%s: 0x%08x\n", __func__, (unsigned)data); #endif - bm->addr &= ~(0xFFFF << shift); - bm->addr |= ((val & 0xFFFF) << shift) & ~3; + bm->addr &= ~(mask << shift); + bm->addr |= ((data & mask) << shift) & ~3; bm->cur_addr = bm->addr; } -uint32_t bmdma_addr_readl(void *opaque, uint32_t addr) -{ - BMDMAState *bm = opaque; - uint32_t val; - val = bm->addr; -#ifdef DEBUG_IDE - printf("%s: 0x%08x\n", __func__, val); -#endif - return val; -} - -void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val) -{ - BMDMAState *bm = opaque; -#ifdef DEBUG_IDE - printf("%s: 0x%08x\n", __func__, val); -#endif - bm->addr = val & ~3; - bm->cur_addr = bm->addr; -} +const IORangeOps bmdma_addr_ioport_ops = { + .read = bmdma_addr_read, + .write = bmdma_addr_write, +}; static bool ide_bmdma_current_needed(void *opaque) { diff --git a/hw/ide/pci.h b/hw/ide/pci.h index d46a95e..b81b26c 100644 --- a/hw/ide/pci.h +++ b/hw/ide/pci.h @@ -11,12 +11,7 @@ typedef struct PCIIDEState { } PCIIDEState; void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val); -uint32_t bmdma_addr_readb(void *opaque, uint32_t addr); -void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val); -uint32_t bmdma_addr_readw(void *opaque, uint32_t addr); -void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val); -uint32_t bmdma_addr_readl(void *opaque, uint32_t addr); -void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val); +extern const IORangeOps bmdma_addr_ioport_ops; void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table); extern const VMStateDescription vmstate_ide_pci; diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 07483e8..e02b89a 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -85,12 +85,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num, register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm); register_ioport_read(addr, 4, 1, bmdma_readb, bm); - register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm); - register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm); - register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm); - register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm); - register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm); - register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm); + iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4); + ioport_register(&bm->addr_ioport); addr += 8; } } diff --git a/hw/ide/via.c b/hw/ide/via.c index b2c7cad..3e41d00 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -87,12 +87,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num, register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm); register_ioport_read(addr, 4, 1, bmdma_readb, bm); - register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm); - register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm); - register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm); - register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm); - register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm); - register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm); + iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4); + ioport_register(&bm->addr_ioport); addr += 8; } } -- cgit v1.1 From 5cbdebe39e08caf5a373ef1c03a0292d5af955ce Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 24 Nov 2010 13:08:03 +0000 Subject: qemu and qemu-xen: support empty write barriers in xen_disk This patch can be applied to both qemu-xen and qemu and adds support for empty write barriers to xen_disk. Signed-off-by: Stefano Stabellini Acked-by: Gerd Hoffmann Signed-off-by: Kevin Wolf --- hw/xen_disk.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 134ac33..85a1c85 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -181,6 +181,10 @@ static int ioreq_parse(struct ioreq *ioreq) ioreq->prot = PROT_WRITE; /* to memory */ break; case BLKIF_OP_WRITE_BARRIER: + if (!ioreq->req.nr_segments) { + ioreq->presync = 1; + return 0; + } if (!syncwrite) ioreq->presync = ioreq->postsync = 1; /* fall through */ @@ -305,7 +309,7 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq) int i, rc, len = 0; off_t pos; - if (ioreq_map(ioreq) == -1) + if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) goto err; if (ioreq->presync) bdrv_flush(blkdev->bs); @@ -329,6 +333,8 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq) break; case BLKIF_OP_WRITE: case BLKIF_OP_WRITE_BARRIER: + if (!ioreq->req.nr_segments) + break; pos = ioreq->start; for (i = 0; i < ioreq->v.niov; i++) { rc = bdrv_write(blkdev->bs, pos / BLOCK_SIZE, @@ -386,7 +392,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) { struct XenBlkDev *blkdev = ioreq->blkdev; - if (ioreq_map(ioreq) == -1) + if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) goto err; ioreq->aio_inflight++; @@ -403,6 +409,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) case BLKIF_OP_WRITE: case BLKIF_OP_WRITE_BARRIER: ioreq->aio_inflight++; + if (!ioreq->req.nr_segments) + break; bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE, &ioreq->v, ioreq->v.size / BLOCK_SIZE, qemu_aio_complete, ioreq); -- cgit v1.1 From 80465c5016f23d8b39efb36db2ca77a35f67eaef Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 16 Nov 2010 18:55:01 +0100 Subject: block: Remove unused s->hd in various drivers All drivers use bs->file instead of s->hd for quite a while now, so it's time to remove s->hd. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- block/qcow.c | 1 - block/qcow2.h | 1 - block/vdi.c | 1 - block/vmdk.c | 1 - block/vpc.c | 2 -- 5 files changed, 6 deletions(-) diff --git a/block/qcow.c b/block/qcow.c index 9cd547d..f67d3d3 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -54,7 +54,6 @@ typedef struct QCowHeader { #define L2_CACHE_SIZE 16 typedef struct BDRVQcowState { - BlockDriverState *hd; int cluster_bits; int cluster_size; int cluster_sectors; diff --git a/block/qcow2.h b/block/qcow2.h index 2d22e5e..5217bea 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -79,7 +79,6 @@ typedef struct QCowSnapshot { } QCowSnapshot; typedef struct BDRVQcowState { - BlockDriverState *hd; int cluster_bits; int cluster_size; int cluster_sectors; diff --git a/block/vdi.c b/block/vdi.c index 3b51e53..ab8f70f 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -186,7 +186,6 @@ typedef struct { } VdiHeader; typedef struct { - BlockDriverState *hd; /* The block map entries are little endian (even in memory). */ uint32_t *bmap; /* Size of block (bytes). */ diff --git a/block/vmdk.c b/block/vmdk.c index 872aeba..8fc9d67 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -61,7 +61,6 @@ typedef struct { #define L2_CACHE_SIZE 16 typedef struct BDRVVmdkState { - BlockDriverState *hd; int64_t l1_table_offset; int64_t l1_backup_table_offset; uint32_t *l1_table; diff --git a/block/vpc.c b/block/vpc.c index 416f489..21e2a68 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -110,8 +110,6 @@ struct vhd_dyndisk_header { }; typedef struct BDRVVPCState { - BlockDriverState *hd; - uint8_t footer_buf[HEADER_SIZE]; uint64_t free_data_block_offset; int max_table_entries; -- cgit v1.1 From 622b520fb4ca50b5028485f1d225317ece0a42b9 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 24 Nov 2010 12:15:56 +0100 Subject: scsi: Increase the number of possible devices The SCSI parallel interface has a limit of 8 devices, but not the SCSI stack in general. So we should be removing the hard-coded limit and use MAX_SCSI_DEVS instead. And we only need to scan those devices which are allocated by the bus. Signed-off-by: Hannes Reinecke Acked-by: Christoph Hellwig Signed-off-by: Kevin Wolf --- blockdev.h | 2 +- hw/scsi-bus.c | 2 +- hw/scsi.h | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/blockdev.h b/blockdev.h index 2a0559e..4cb8ca9 100644 --- a/blockdev.h +++ b/blockdev.h @@ -32,7 +32,7 @@ struct DriveInfo { }; #define MAX_IDE_DEVS 2 -#define MAX_SCSI_DEVS 7 +#define MAX_SCSI_DEVS 255 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); int drive_get_max_bus(BlockInterfaceType type); diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 5a3fd4b..74a08b7 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -108,7 +108,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) int res = 0, unit; loc_push_none(&loc); - for (unit = 0; unit < MAX_SCSI_DEVS; unit++) { + for (unit = 0; unit < bus->ndev; unit++) { dinfo = drive_get(IF_SCSI, bus->busnr, unit); if (dinfo == NULL) { continue; diff --git a/hw/scsi.h b/hw/scsi.h index cb06d6d..9c798ae 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -3,6 +3,7 @@ #include "qdev.h" #include "block.h" +#include "blockdev.h" #include "block_int.h" #define SCSI_CMD_BUF_SIZE 16 @@ -86,7 +87,7 @@ struct SCSIBus { int tcq, ndev; scsi_completionfn complete; - SCSIDevice *devs[8]; + SCSIDevice *devs[MAX_SCSI_DEVS]; }; void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev, -- cgit v1.1 From f017132793065abcdc4b9b78d7ca575eeb3de484 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 24 Nov 2010 12:15:57 +0100 Subject: scsi: Return SAM status codes Traditionally, the linux stack is using SCSI status codes which are shifted by one as compared to those defined in SAM. A SCSI emulation should naturally return the SAM defined codes, not the linux ones. So to avoid any confusion this patch modifies the existing definitions to match those found in SAM and removes any (now obsolete) byte-shift from the returned status codes. Signed-off-by: Hannes Reinecke Acked-by: Christoph Hellwig Signed-off-by: Kevin Wolf --- hw/scsi-defs.h | 20 +++++++++++--------- hw/scsi-generic.c | 10 +++++----- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h index a4a3518..1473ecb 100644 --- a/hw/scsi-defs.h +++ b/hw/scsi-defs.h @@ -111,18 +111,20 @@ #define BLANK 0xa1 /* - * Status codes + * SAM Status codes */ #define GOOD 0x00 -#define CHECK_CONDITION 0x01 -#define CONDITION_GOOD 0x02 -#define BUSY 0x04 -#define INTERMEDIATE_GOOD 0x08 -#define INTERMEDIATE_C_GOOD 0x0a -#define RESERVATION_CONFLICT 0x0c -#define COMMAND_TERMINATED 0x11 -#define QUEUE_FULL 0x14 +#define CHECK_CONDITION 0x02 +#define CONDITION_GOOD 0x04 +#define BUSY 0x08 +#define INTERMEDIATE_GOOD 0x10 +#define INTERMEDIATE_C_GOOD 0x14 +#define RESERVATION_CONFLICT 0x18 +#define COMMAND_TERMINATED 0x22 +#define TASK_SET_FULL 0x28 +#define ACA_ACTIVE 0x30 +#define TASK_ABORTED 0x40 #define STATUS_MASK 0x3e diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 7212091..9be1cca 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -96,17 +96,17 @@ static void scsi_command_complete(void *opaque, int ret) s->senselen = r->io_header.sb_len_wr; if (ret != 0) - r->req.status = BUSY << 1; + r->req.status = BUSY; else { if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) { - r->req.status = BUSY << 1; + r->req.status = BUSY; BADF("Driver Timeout\n"); } else if (r->io_header.status) r->req.status = r->io_header.status; else if (s->driver_status & SG_ERR_DRIVER_SENSE) - r->req.status = CHECK_CONDITION << 1; + r->req.status = CHECK_CONDITION; else - r->req.status = GOOD << 1; + r->req.status = GOOD; } DPRINTF("Command complete 0x%p tag=0x%x status=%d\n", r, r->req.tag, r->req.status); @@ -333,7 +333,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, s->senselen = 7; s->driver_status = SG_ERR_DRIVER_SENSE; bus = scsi_bus_from_device(d); - bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1); + bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION); return 0; } -- cgit v1.1 From 39d989823f2c177415a22b84b354716a1f734b70 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 24 Nov 2010 12:15:58 +0100 Subject: scsi: INQUIRY VPD fixes We should announce and support the block device characterics page only on block devices, not on CDROMs. And the VPD page 0x83 has an off-by-one error. Signed-off-by: Hannes Reinecke Acked-by: Christoph Hellwig Signed-off-by: Kevin Wolf --- hw/scsi-disk.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 7d85899..c41dcfc 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -398,15 +398,20 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) switch (page_code) { case 0x00: /* Supported page codes, mandatory */ + { + int pages; DPRINTF("Inquiry EVPD[Supported pages] " "buffer size %zd\n", req->cmd.xfer); - outbuf[buflen++] = 4; // number of pages + pages = buflen++; outbuf[buflen++] = 0x00; // list of supported pages (this page) outbuf[buflen++] = 0x80; // unit serial number outbuf[buflen++] = 0x83; // device identification - outbuf[buflen++] = 0xb0; // block device characteristics + if (bdrv_get_type_hint(s->bs) != BDRV_TYPE_CDROM) { + outbuf[buflen++] = 0xb0; // block device characteristics + } + outbuf[pages] = buflen - pages - 1; // number of pages break; - + } case 0x80: /* Device serial number, optional */ { int l = strlen(s->serial); @@ -434,7 +439,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) DPRINTF("Inquiry EVPD[Device identification] " "buffer size %zd\n", req->cmd.xfer); - outbuf[buflen++] = 3 + id_len; + outbuf[buflen++] = 4 + id_len; outbuf[buflen++] = 0x2; // ASCII outbuf[buflen++] = 0; // not officially assigned outbuf[buflen++] = 0; // reserved @@ -451,6 +456,11 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) unsigned int opt_io_size = s->qdev.conf.opt_io_size / s->qdev.blocksize; + if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { + DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n", + page_code); + return -1; + } /* required VPD size with unmap support */ outbuf[3] = buflen = 0x3c; -- cgit v1.1 From a6d96eb78bd1f87ab9d6a377f863f99be4b71538 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 24 Nov 2010 12:15:59 +0100 Subject: scsi: Move sense handling into the driver The current sense handling in scsi-bus is only used by the scsi-disk driver; the scsi-generic driver is using its own. So we should move the current sense handling into the scsi-disk driver. Signed-off-by: Hannes Reinecke Acked-by: Christoph Hellwig Signed-off-by: Kevin Wolf --- hw/scsi-bus.c | 10 ---------- hw/scsi-disk.c | 33 +++++++++++++++++++++++++-------- hw/scsi.h | 8 -------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 74a08b7..93f0e9a 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -123,16 +123,6 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) return res; } -void scsi_dev_clear_sense(SCSIDevice *dev) -{ - memset(&dev->sense, 0, sizeof(dev->sense)); -} - -void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key) -{ - dev->sense.key = key; -} - SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun) { SCSIRequest *req; diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index c41dcfc..d692fb0 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -49,6 +49,10 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0) typedef struct SCSIDiskState SCSIDiskState; +typedef struct SCSISense { + uint8_t key; +} SCSISense; + typedef struct SCSIDiskReq { SCSIRequest req; /* ??? We should probably keep track of whether the data transfer is @@ -72,6 +76,7 @@ struct SCSIDiskState QEMUBH *bh; char *version; char *serial; + SCSISense sense; }; static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type); @@ -100,10 +105,22 @@ static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag) return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag)); } -static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code) +static void scsi_disk_clear_sense(SCSIDiskState *s) { - req->status = status; - scsi_dev_set_sense(req->dev, sense_code); + memset(&s->sense, 0, sizeof(s->sense)); +} + +static void scsi_disk_set_sense(SCSIDiskState *s, uint8_t key) +{ + s->sense.key = key; +} + +static void scsi_req_set_status(SCSIDiskReq *r, int status, int sense_code) +{ + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + + r->req.status = status; + scsi_disk_set_sense(s, sense_code); } /* Helper function for command completion. */ @@ -111,7 +128,7 @@ static void scsi_command_complete(SCSIDiskReq *r, int status, int sense) { DPRINTF("Command complete tag=0x%x status=%d sense=%d\n", r->req.tag, status, sense); - scsi_req_set_status(&r->req, status, sense); + scsi_req_set_status(r, status, sense); scsi_req_complete(&r->req); scsi_remove_request(r); } @@ -822,7 +839,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) goto illegal_request; memset(outbuf, 0, 4); buflen = 4; - if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) { + if (s->sense.key == NOT_READY && req->cmd.xfer >= 18) { memset(outbuf, 0, 18); buflen = 18; outbuf[7] = 10; @@ -832,8 +849,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) } outbuf[0] = 0xf0; outbuf[1] = 0; - outbuf[2] = req->dev->sense.key; - scsi_dev_clear_sense(req->dev); + outbuf[2] = s->sense.key; + scsi_disk_clear_sense(s); break; case INQUIRY: buflen = scsi_disk_emulate_inquiry(req, outbuf); @@ -966,7 +983,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf) default: goto illegal_request; } - scsi_req_set_status(req, GOOD, NO_SENSE); + scsi_req_set_status(r, GOOD, NO_SENSE); return buflen; not_ready: diff --git a/hw/scsi.h b/hw/scsi.h index 9c798ae..bf02adf 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -26,10 +26,6 @@ enum SCSIXferMode { SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */ }; -typedef struct SCSISense { - uint8_t key; -} SCSISense; - typedef struct SCSIRequest { SCSIBus *bus; SCSIDevice *dev; @@ -57,7 +53,6 @@ struct SCSIDevice QTAILQ_HEAD(, SCSIRequest) requests; int blocksize; int type; - struct SCSISense sense; }; /* cdrom.c */ @@ -102,9 +97,6 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit); int scsi_bus_legacy_handle_cmdline(SCSIBus *bus); -void scsi_dev_clear_sense(SCSIDevice *dev); -void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key); - SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun); SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag); void scsi_req_free(SCSIRequest *req); -- cgit v1.1 From 2dd791b6302c73345f92dc9b107635787fcff938 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 24 Nov 2010 12:16:00 +0100 Subject: scsi-disk: Remove duplicate cdb parsing We parse the CDB twice, which is completely unnecessary. Signed-off-by: Hannes Reinecke Acked-by: Christoph Hellwig Signed-off-by: Kevin Wolf --- hw/scsi-disk.c | 74 +++++++++++++++++----------------------------------------- 1 file changed, 21 insertions(+), 53 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index d692fb0..6e49404 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1004,9 +1004,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, uint8_t *buf, int lun) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d); - uint64_t lba; uint32_t len; - int cmdlen; int is_write; uint8_t command; uint8_t *outbuf; @@ -1025,55 +1023,21 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, outbuf = (uint8_t *)r->iov.iov_base; is_write = 0; DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]); - switch (command >> 5) { - case 0: - lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) | - (((uint64_t) buf[1] & 0x1f) << 16); - len = buf[4]; - cmdlen = 6; - break; - case 1: - case 2: - lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) | - ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24); - len = buf[8] | (buf[7] << 8); - cmdlen = 10; - break; - case 4: - lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) | - ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) | - ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) | - ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56); - len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24); - cmdlen = 16; - break; - case 5: - lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) | - ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24); - len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24); - cmdlen = 12; - break; - default: + + if (scsi_req_parse(&r->req, buf) != 0) { BADF("Unsupported command length, command %x\n", command); goto fail; } #ifdef DEBUG_SCSI { int i; - for (i = 1; i < cmdlen; i++) { + for (i = 1; i < r->req.cmd.len; i++) { printf(" 0x%02x", buf[i]); } printf("\n"); } #endif - if (scsi_req_parse(&r->req, buf) != 0) { - BADF("Unsupported command length, command %x\n", command); - goto fail; - } - assert(r->req.cmd.len == cmdlen); - assert(r->req.cmd.lba == lba); - if (lun || buf[1] >> 5) { /* Only LUN 0 supported. */ DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5); @@ -1111,10 +1075,11 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, case READ_10: case READ_12: case READ_16: - DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len); - if (lba > s->max_lba) + len = r->req.cmd.xfer / d->blocksize; + DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len); + if (r->req.cmd.lba > s->max_lba) goto illegal_lba; - r->sector = lba * s->cluster_size; + r->sector = r->req.cmd.lba * s->cluster_size; r->sector_count = len * s->cluster_size; break; case WRITE_6: @@ -1124,42 +1089,45 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, case WRITE_VERIFY: case WRITE_VERIFY_12: case WRITE_VERIFY_16: + len = r->req.cmd.xfer / d->blocksize; DPRINTF("Write %s(sector %" PRId64 ", count %d)\n", - (command & 0xe) == 0xe ? "And Verify " : "", lba, len); - if (lba > s->max_lba) + (command & 0xe) == 0xe ? "And Verify " : "", + r->req.cmd.lba, len); + if (r->req.cmd.lba > s->max_lba) goto illegal_lba; - r->sector = lba * s->cluster_size; + r->sector = r->req.cmd.lba * s->cluster_size; r->sector_count = len * s->cluster_size; is_write = 1; break; case MODE_SELECT: - DPRINTF("Mode Select(6) (len %d)\n", len); + DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer); /* We don't support mode parameter changes. Allow the mode parameter header + block descriptors only. */ - if (len > 12) { + if (r->req.cmd.xfer > 12) { goto fail; } break; case MODE_SELECT_10: - DPRINTF("Mode Select(10) (len %d)\n", len); + DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer); /* We don't support mode parameter changes. Allow the mode parameter header + block descriptors only. */ - if (len > 16) { + if (r->req.cmd.xfer > 16) { goto fail; } break; case SEEK_6: case SEEK_10: - DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10, lba); - if (lba > s->max_lba) { + DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10, + r->req.cmd.lba); + if (r->req.cmd.lba > s->max_lba) { goto illegal_lba; } break; default: - DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]); + DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]); fail: scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST); - return 0; + return 0; illegal_lba: scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR); return 0; -- cgit v1.1 From 11a3cb8159278f7452b5bec8b9e17292a3ef53c3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 26 Nov 2010 14:32:34 +0100 Subject: raw-posix: raw_pwrite comment fixup Signed-off-by: Christoph Hellwig Signed-off-by: Kevin Wolf --- block/raw-posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index d0960b8..9286fb8 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -463,7 +463,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset, count -= ret; sum += ret; } - /* here, count < 512 because (count & ~sector_mask) == 0 */ + /* here, count < sector_size because (count & ~sector_mask) == 0 */ if (count) { ret = raw_pread_aligned(bs, offset, s->aligned_buf, bs->buffer_alignment); -- cgit v1.1 From 6e14404aab26f74a448747d1e793ac16bde8a92b Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 26 Nov 2010 18:46:03 +0000 Subject: Add missing dependency. Teach Makefile that cmd.o depends on a generated header (specifically config-host.h). Signed-off-by: Paul Brook --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4e120a2..3389775 100644 --- a/Makefile +++ b/Makefile @@ -150,7 +150,7 @@ version-obj-$(CONFIG_WIN32) += version.o ###################################################################### qemu-img.o: qemu-img-cmds.h -qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS) +qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o: $(GENERATED_HEADERS) qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o -- cgit v1.1 From bd9141bb2e53195e3c1abf29275365d7f554beb5 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 26 Nov 2010 18:47:45 +0000 Subject: Include directives in default configs Allow default configs to be split into several files. Signed-off-by: Paul Brook --- Makefile | 11 ++++++----- Makefile.objs | 3 ++- make_device_config.sh | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 make_device_config.sh diff --git a/Makefile b/Makefile index 3389775..d3bc0f2 100644 --- a/Makefile +++ b/Makefile @@ -39,18 +39,19 @@ endif SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS)) +SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %/config-devices.mak.d, $(TARGET_DIRS)) config-all-devices.mak: $(SUBDIR_DEVICES_MAK) $(call quiet-command,cat $(SUBDIR_DEVICES_MAK) | grep =y | sort -u > $@," GEN $@") +-include $(SUBDIR_DEVICES_MAK_DEP) + %/config-devices.mak: default-configs/%.mak - $(call quiet-command,cat $< > $@.tmp, " GEN $@") + $(call quiet-command,$(SHELL) $(SRC_PATH)/make_device_config.sh $@ $<, " GEN $@") @if test -f $@; then \ if cmp -s $@.old $@; then \ - if ! cmp -s $@ $@.tmp; then \ - mv $@.tmp $@; \ - cp -p $@ $@.old; \ - fi; \ + mv $@.tmp $@; \ + cp -p $@ $@.old; \ else \ if test -f $@.old; then \ echo "WARNING: $@ (user modified) out of date.";\ diff --git a/Makefile.objs b/Makefile.objs index 23b17ce..4f4aba3 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -160,7 +160,8 @@ user-obj-y += cutils.o cache-utils.o hw-obj-y = hw-obj-y += vl.o loader.o hw-obj-y += virtio.o virtio-console.o -hw-obj-y += fw_cfg.o pci.o pci_host.o pcie_host.o pci_bridge.o +hw-obj-y += fw_cfg.o +hw-obj-$(CONFIG_PCI) += pci.o pci_host.o pcie_host.o pci_bridge.o hw-obj-y += ioh3420.o xio3130_upstream.o xio3130_downstream.o hw-obj-y += watchdog.o hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o diff --git a/make_device_config.sh b/make_device_config.sh new file mode 100644 index 0000000..59f267b --- /dev/null +++ b/make_device_config.sh @@ -0,0 +1,27 @@ +#! /bin/sh +# Construct a target device config file from a default, pulling in any +# files from include directives. + +dest=$1.tmp +dep=$1.d +src=$2 +src_dir=`dirname $src` +all_includes= + +process_includes () { + cat $1 | grep '^include' | \ + while read include file ; do + all_includes="$all_includes $src_dir/$file" + process_includes $src_dir/$file + done +} + +f=$src +while [ -n "$f" ] ; do + f=`awk '/^include / {print "'$src_dir'/" $2}' $f` + all_includes="$all_includes $f" +done +process_includes $src > $dest + +cat $src $all_includes | grep -v '^include' > $dest +echo "$1: $all_includes" > $dep -- cgit v1.1 From f8f5cfbaa49387a513fddd9c9bf1aeb0ecc64cce Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 26 Nov 2010 21:39:42 +0000 Subject: PCI config include Split PCI config options into a separate file Signed-off-by: Paul Brook --- Makefile.objs | 20 +++++++++++--------- Makefile.target | 4 ++-- default-configs/arm-softmmu.mak | 3 +-- default-configs/cris-softmmu.mak | 2 +- default-configs/i386-softmmu.mak | 4 +--- default-configs/m68k-softmmu.mak | 2 +- default-configs/microblaze-softmmu.mak | 1 - default-configs/mips-softmmu.mak | 3 +-- default-configs/mips64-softmmu.mak | 3 +-- default-configs/mips64el-softmmu.mak | 3 +-- default-configs/mipsel-softmmu.mak | 3 +-- default-configs/ppc-softmmu.mak | 3 +-- default-configs/ppc64-softmmu.mak | 3 +-- default-configs/ppcemb-softmmu.mak | 3 +-- default-configs/sh4-softmmu.mak | 3 +-- default-configs/sh4eb-softmmu.mak | 3 +-- default-configs/sparc-softmmu.mak | 2 +- default-configs/sparc64-softmmu.mak | 2 +- default-configs/x86_64-softmmu.mak | 4 +--- 19 files changed, 29 insertions(+), 42 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 4f4aba3..9e85b04 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -161,8 +161,11 @@ hw-obj-y = hw-obj-y += vl.o loader.o hw-obj-y += virtio.o virtio-console.o hw-obj-y += fw_cfg.o -hw-obj-$(CONFIG_PCI) += pci.o pci_host.o pcie_host.o pci_bridge.o -hw-obj-y += ioh3420.o xio3130_upstream.o xio3130_downstream.o +# FIXME: Core PCI code and its direct dependencies are required by the +# QMP query-pci command. +hw-obj-y += pci.o pci_bridge.o msix.o msi.o +hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o +hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o hw-obj-y += watchdog.o hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o hw-obj-$(CONFIG_ECC) += ecc.o @@ -207,15 +210,14 @@ hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o hw-obj-$(CONFIG_PIIX4) += piix4.o # PCI watchdog devices -hw-obj-y += wdt_i6300esb.o +hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o -hw-obj-y += pcie.o pcie_port.o -hw-obj-y += msix.o msi.o +hw-obj-$(CONFIG_PCI) += pcie.o pcie_port.o # PCI network cards -hw-obj-y += ne2000.o -hw-obj-y += eepro100.o -hw-obj-y += pcnet.o +hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o +hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o +hw-obj-$(CONFIG_PCNET_PCI) += pcnet.o hw-obj-$(CONFIG_SMC91C111) += smc91c111.o hw-obj-$(CONFIG_LAN9118) += lan9118.o @@ -232,7 +234,7 @@ hw-obj-$(CONFIG_IDE_MACIO) += ide/macio.o hw-obj-$(CONFIG_IDE_VIA) += ide/via.o # SCSI layer -hw-obj-y += lsi53c895a.o +hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o hw-obj-$(CONFIG_ESP) += esp.o hw-obj-y += dma-helpers.o sysbus.o isa-bus.o diff --git a/Makefile.target b/Makefile.target index 2800f47..853045a 100644 --- a/Makefile.target +++ b/Makefile.target @@ -210,8 +210,8 @@ obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o obj-$(CONFIG_USB_OHCI) += usb-ohci.o # PCI network cards -obj-y += rtl8139.o -obj-y += e1000.o +obj-$(CONFIG_RTL8139_PCI) += rtl8139.o +obj-$(CONFIG_E1000_PCI) += e1000.o # Inter-VM PCI shared memory obj-$(CONFIG_KVM) += ivshmem.o diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index e7a4e84..ac48dc1 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -1,7 +1,7 @@ # Default configuration for arm-softmmu +include pci.mak CONFIG_GDBSTUB_XML=y -CONFIG_USB_OHCI=y CONFIG_ISA_MMIO=y CONFIG_NAND=y CONFIG_ECC=y @@ -25,6 +25,5 @@ CONFIG_SSI_SD=y CONFIG_LAN9118=y CONFIG_SMC91C111=y CONFIG_DS1338=y -CONFIG_VIRTIO_PCI=y CONFIG_PFLASH_CFI01=y CONFIG_PFLASH_CFI02=y diff --git a/default-configs/cris-softmmu.mak b/default-configs/cris-softmmu.mak index e0d2cab..5f1fd1e 100644 --- a/default-configs/cris-softmmu.mak +++ b/default-configs/cris-softmmu.mak @@ -1,6 +1,6 @@ # Default configuration for cris-softmmu +#include pci.mak CONFIG_NAND=y CONFIG_PTIMER=y -CONFIG_VIRTIO_PCI=y CONFIG_PFLASH_CFI02=y diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index ed00471..ce905d2 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -1,6 +1,6 @@ # Default configuration for i386-softmmu -CONFIG_USB_OHCI=y +include pci.mak CONFIG_VGA_PCI=y CONFIG_VGA_ISA=y CONFIG_VMWARE_VGA=y @@ -9,7 +9,6 @@ CONFIG_PARALLEL=y CONFIG_I8254=y CONFIG_PCSPK=y CONFIG_PCKBD=y -CONFIG_USB_UHCI=y CONFIG_FDC=y CONFIG_ACPI=y CONFIG_APM=y @@ -22,4 +21,3 @@ CONFIG_IDE_PIIX=y CONFIG_NE2000_ISA=y CONFIG_PIIX_PCI=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y diff --git a/default-configs/m68k-softmmu.mak b/default-configs/m68k-softmmu.mak index 69ca3ed..3e2ec37 100644 --- a/default-configs/m68k-softmmu.mak +++ b/default-configs/m68k-softmmu.mak @@ -1,5 +1,5 @@ # Default configuration for m68k-softmmu +include pci.mak CONFIG_GDBSTUB_XML=y CONFIG_PTIMER=y -CONFIG_VIRTIO_PCI=y diff --git a/default-configs/microblaze-softmmu.mak b/default-configs/microblaze-softmmu.mak index 6c4f4f2..4399b8b 100644 --- a/default-configs/microblaze-softmmu.mak +++ b/default-configs/microblaze-softmmu.mak @@ -1,5 +1,4 @@ # Default configuration for microblaze-softmmu CONFIG_PTIMER=y -CONFIG_VIRTIO_PCI=y CONFIG_PFLASH_CFI01=y diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak index 3d0af83..565e611 100644 --- a/default-configs/mips-softmmu.mak +++ b/default-configs/mips-softmmu.mak @@ -1,5 +1,6 @@ # Default configuration for mips-softmmu +include pci.mak CONFIG_ISA_MMIO=y CONFIG_ESP=y CONFIG_VGA_PCI=y @@ -11,7 +12,6 @@ CONFIG_PARALLEL=y CONFIG_I8254=y CONFIG_PCSPK=y CONFIG_PCKBD=y -CONFIG_USB_UHCI=y CONFIG_FDC=y CONFIG_ACPI=y CONFIG_APM=y @@ -24,7 +24,6 @@ CONFIG_IDE_ISA=y CONFIG_IDE_PIIX=y CONFIG_NE2000_ISA=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y CONFIG_RC4030=y CONFIG_DP8393X=y CONFIG_DS1225Y=y diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak index 0030de4..03bd8eb 100644 --- a/default-configs/mips64-softmmu.mak +++ b/default-configs/mips64-softmmu.mak @@ -1,5 +1,6 @@ # Default configuration for mips64-softmmu +include pci.mak CONFIG_ISA_MMIO=y CONFIG_ESP=y CONFIG_VGA_PCI=y @@ -11,7 +12,6 @@ CONFIG_PARALLEL=y CONFIG_I8254=y CONFIG_PCSPK=y CONFIG_PCKBD=y -CONFIG_USB_UHCI=y CONFIG_FDC=y CONFIG_ACPI=y CONFIG_APM=y @@ -24,7 +24,6 @@ CONFIG_IDE_ISA=y CONFIG_IDE_PIIX=y CONFIG_NE2000_ISA=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y CONFIG_RC4030=y CONFIG_DP8393X=y CONFIG_DS1225Y=y diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak index fa2a3ff..4661617 100644 --- a/default-configs/mips64el-softmmu.mak +++ b/default-configs/mips64el-softmmu.mak @@ -1,5 +1,6 @@ # Default configuration for mips64el-softmmu +include pci.mak CONFIG_ISA_MMIO=y CONFIG_ESP=y CONFIG_VGA_PCI=y @@ -11,7 +12,6 @@ CONFIG_PARALLEL=y CONFIG_I8254=y CONFIG_PCSPK=y CONFIG_PCKBD=y -CONFIG_USB_UHCI=y CONFIG_FDC=y CONFIG_ACPI=y CONFIG_APM=y @@ -25,7 +25,6 @@ CONFIG_IDE_PIIX=y CONFIG_IDE_VIA=y CONFIG_NE2000_ISA=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y CONFIG_RC4030=y CONFIG_DP8393X=y CONFIG_DS1225Y=y diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak index 238b73a..92fc473 100644 --- a/default-configs/mipsel-softmmu.mak +++ b/default-configs/mipsel-softmmu.mak @@ -1,5 +1,6 @@ # Default configuration for mipsel-softmmu +include pci.mak CONFIG_ISA_MMIO=y CONFIG_ESP=y CONFIG_VGA_PCI=y @@ -11,7 +12,6 @@ CONFIG_PARALLEL=y CONFIG_I8254=y CONFIG_PCSPK=y CONFIG_PCKBD=y -CONFIG_USB_UHCI=y CONFIG_FDC=y CONFIG_ACPI=y CONFIG_APM=y @@ -24,7 +24,6 @@ CONFIG_IDE_ISA=y CONFIG_IDE_PIIX=y CONFIG_NE2000_ISA=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y CONFIG_RC4030=y CONFIG_DP8393X=y CONFIG_DS1225Y=y diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index 940f4bf..f1cb99e 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -1,7 +1,7 @@ # Default configuration for ppc-softmmu +include pci.mak CONFIG_GDBSTUB_XML=y -CONFIG_USB_OHCI=y CONFIG_ISA_MMIO=y CONFIG_ESCC=y CONFIG_M48T59=y @@ -31,7 +31,6 @@ CONFIG_IDE_CMD646=y CONFIG_IDE_MACIO=y CONFIG_NE2000_ISA=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y CONFIG_PFLASH_CFI01=y CONFIG_PFLASH_CFI02=y CONFIG_PTIMER=y diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index e1bc6b8..83cbe97 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -1,7 +1,7 @@ # Default configuration for ppc64-softmmu +include pci.mak CONFIG_GDBSTUB_XML=y -CONFIG_USB_OHCI=y CONFIG_ISA_MMIO=y CONFIG_ESCC=y CONFIG_M48T59=y @@ -31,7 +31,6 @@ CONFIG_IDE_CMD646=y CONFIG_IDE_MACIO=y CONFIG_NE2000_ISA=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y CONFIG_PFLASH_CFI01=y CONFIG_PFLASH_CFI02=y CONFIG_PTIMER=y diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak index 8f1cc09..2b52d4a 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -1,7 +1,7 @@ # Default configuration for ppcemb-softmmu +include pci.mak CONFIG_GDBSTUB_XML=y -CONFIG_USB_OHCI=y CONFIG_ISA_MMIO=y CONFIG_ESCC=y CONFIG_M48T59=y @@ -31,7 +31,6 @@ CONFIG_IDE_CMD646=y CONFIG_IDE_MACIO=y CONFIG_NE2000_ISA=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y CONFIG_PFLASH_CFI01=y CONFIG_PFLASH_CFI02=y CONFIG_PTIMER=y diff --git a/default-configs/sh4-softmmu.mak b/default-configs/sh4-softmmu.mak index 866ed7d..87247a4 100644 --- a/default-configs/sh4-softmmu.mak +++ b/default-configs/sh4-softmmu.mak @@ -1,9 +1,8 @@ # Default configuration for sh4-softmmu -CONFIG_USB_OHCI=y +include pci.mak CONFIG_SERIAL=y CONFIG_PTIMER=y -CONFIG_VIRTIO_PCI=y CONFIG_IDE_CORE=y CONFIG_PFLASH_CFI02=y CONFIG_ISA_MMIO=y diff --git a/default-configs/sh4eb-softmmu.mak b/default-configs/sh4eb-softmmu.mak index e3e08b7..5b8a16e 100644 --- a/default-configs/sh4eb-softmmu.mak +++ b/default-configs/sh4eb-softmmu.mak @@ -1,9 +1,8 @@ # Default configuration for sh4eb-softmmu -CONFIG_USB_OHCI=y +include pci.mak CONFIG_SERIAL=y CONFIG_PTIMER=y -CONFIG_VIRTIO_PCI=y CONFIG_IDE_CORE=y CONFIG_PFLASH_CFI02=y CONFIG_ISA_MMIO=y diff --git a/default-configs/sparc-softmmu.mak b/default-configs/sparc-softmmu.mak index becf880..7c788b8 100644 --- a/default-configs/sparc-softmmu.mak +++ b/default-configs/sparc-softmmu.mak @@ -1,10 +1,10 @@ # Default configuration for sparc-softmmu +include pci.mak CONFIG_ECC=y CONFIG_ESP=y CONFIG_ESCC=y CONFIG_M48T59=y CONFIG_PTIMER=y CONFIG_FDC=y -CONFIG_VIRTIO_PCI=y CONFIG_EMPTY_SLOT=y diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak index 1cc3f13..ecc3122 100644 --- a/default-configs/sparc64-softmmu.mak +++ b/default-configs/sparc64-softmmu.mak @@ -1,5 +1,6 @@ # Default configuration for sparc64-softmmu +include pci.mak CONFIG_ISA_MMIO=y CONFIG_M48T59=y CONFIG_PTIMER=y @@ -13,4 +14,3 @@ CONFIG_IDE_QDEV=y CONFIG_IDE_PCI=y CONFIG_IDE_ISA=y CONFIG_IDE_CMD646=y -CONFIG_VIRTIO_PCI=y diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index 5183203..7f22599 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -1,6 +1,6 @@ # Default configuration for x86_64-softmmu -CONFIG_USB_OHCI=y +include pci.mak CONFIG_VGA_PCI=y CONFIG_VGA_ISA=y CONFIG_VMWARE_VGA=y @@ -9,7 +9,6 @@ CONFIG_PARALLEL=y CONFIG_I8254=y CONFIG_PCSPK=y CONFIG_PCKBD=y -CONFIG_USB_UHCI=y CONFIG_FDC=y CONFIG_ACPI=y CONFIG_APM=y @@ -22,4 +21,3 @@ CONFIG_IDE_PIIX=y CONFIG_NE2000_ISA=y CONFIG_PIIX_PCI=y CONFIG_SOUND=y -CONFIG_VIRTIO_PCI=y -- cgit v1.1 From 01af7daf5596e8860c71e72349e1d539b81d9c80 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 26 Nov 2010 22:08:48 +0000 Subject: VirtIO config option Make virtio devices optional. Selecting individual devices is not useful as the host bindings are all in one file. Signed-off-by: Paul Brook --- Makefile.objs | 10 ++++++++-- Makefile.target | 4 ++-- default-configs/s390x-softmmu.mak | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 9e85b04..72c6c7f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -42,6 +42,11 @@ net-nested-$(CONFIG_SLIRP) += slirp.o net-nested-$(CONFIG_VDE) += vde.o net-obj-y += $(addprefix net/, $(net-nested-y)) +ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS),yy) +# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add. +# only pull in the actual virtio-9p device if we also enabled virtio. +CONFIG_REALLY_VIRTFS=y +endif fsdev-nested-$(CONFIG_VIRTFS) = qemu-fsdev.o fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y)) @@ -159,7 +164,7 @@ user-obj-y += cutils.o cache-utils.o hw-obj-y = hw-obj-y += vl.o loader.o -hw-obj-y += virtio.o virtio-console.o +hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o hw-obj-y += fw_cfg.o # FIXME: Core PCI code and its direct dependencies are required by the # QMP query-pci command. @@ -264,7 +269,8 @@ sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0 hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) -hw-obj-$(CONFIG_VIRTFS) += virtio-9p-debug.o virtio-9p-local.o virtio-9p-xattr.o +hw-obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p-debug.o +hw-obj-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o ###################################################################### diff --git a/Makefile.target b/Makefile.target index 853045a..5784844 100644 --- a/Makefile.target +++ b/Makefile.target @@ -188,11 +188,11 @@ ifdef CONFIG_SOFTMMU obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly -obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o +obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o obj-y += vhost_net.o obj-$(CONFIG_VHOST_NET) += vhost.o -obj-$(CONFIG_VIRTFS) += virtio-9p.o +obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p.o obj-y += rwhandler.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o obj-$(CONFIG_NO_KVM) += kvm-stub.o diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index e69de29..16d7259 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -0,0 +1 @@ +include virtio.mak -- cgit v1.1 From 050e27c8c942151c0685342fe2cbac6a80eb1325 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sat, 27 Nov 2010 00:34:15 +0000 Subject: Fix previous commit Fix breakage from previous commit (missing pci.mak, and incorrect include in default-configs/s390x-softmmu.mak). Signed-off-by: Paul Brook --- default-configs/cris-softmmu.mak | 1 - default-configs/pci.mak | 11 +++++++++++ default-configs/s390x-softmmu.mak | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 default-configs/pci.mak diff --git a/default-configs/cris-softmmu.mak b/default-configs/cris-softmmu.mak index 5f1fd1e..1a479cd 100644 --- a/default-configs/cris-softmmu.mak +++ b/default-configs/cris-softmmu.mak @@ -1,6 +1,5 @@ # Default configuration for cris-softmmu -#include pci.mak CONFIG_NAND=y CONFIG_PTIMER=y CONFIG_PFLASH_CFI02=y diff --git a/default-configs/pci.mak b/default-configs/pci.mak new file mode 100644 index 0000000..0ddfb37 --- /dev/null +++ b/default-configs/pci.mak @@ -0,0 +1,11 @@ +CONFIG_PCI=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO=y +CONFIG_USB_UHCI=y +CONFIG_USB_OHCI=y +CONFIG_NE2000_PCI=y +CONFIG_EEPRO100_PCI=y +CONFIG_PCNET_PCI=y +CONFIG_LSI_SCSI_PCI=y +CONFIG_RTL8139_PCI=y +CONFIG_E1000_PCI=y diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 16d7259..3005729 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1 +1 @@ -include virtio.mak +CONFIG_VIRTIO=y -- cgit v1.1 From cf66924f81f022942e14b4e613f1bf0dd2bdf0eb Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sat, 27 Nov 2010 00:43:04 +0000 Subject: Detect missing config includes Terminate make_device_config.sh if the awk command fails. Typically this means a missing file. Signed-off-by: Paul Brook --- make_device_config.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/make_device_config.sh b/make_device_config.sh index 59f267b..8abadfe 100644 --- a/make_device_config.sh +++ b/make_device_config.sh @@ -18,7 +18,8 @@ process_includes () { f=$src while [ -n "$f" ] ; do - f=`awk '/^include / {print "'$src_dir'/" $2}' $f` + f=`awk '/^include / {ORS=" " ; print "'$src_dir'/" $2}' $f` + [ $? = 0 ] || exit 1 all_includes="$all_includes $f" done process_includes $src > $dest -- cgit v1.1 From 129cac5b5af110cfa94eae1a570c33ce795f0104 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sat, 27 Nov 2010 10:33:55 +0000 Subject: Remove PCI from sparc32 target None of the (current) sparc32 machines have a PCI bus, so remove the PCI code from these configs. Signed-off-by: Paul Brook --- default-configs/sparc-softmmu.mak | 1 - 1 file changed, 1 deletion(-) diff --git a/default-configs/sparc-softmmu.mak b/default-configs/sparc-softmmu.mak index 7c788b8..436d2a6 100644 --- a/default-configs/sparc-softmmu.mak +++ b/default-configs/sparc-softmmu.mak @@ -1,6 +1,5 @@ # Default configuration for sparc-softmmu -include pci.mak CONFIG_ECC=y CONFIG_ESP=y CONFIG_ESCC=y -- cgit v1.1 From a4c75a21f3749b8dc5a8cc252bc57adb3f43453c Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sat, 27 Nov 2010 11:23:34 +0000 Subject: Split out common pcnet code The core pcnet emulation code is used by both the PCI "pcnet" device and the SPARC "lance" device. Split the common code frm the PCI code so that that can be configures independantly. Signed-off-by: Paul Brook --- Makefile.objs | 3 +- default-configs/pci.mak | 1 + default-configs/sparc-softmmu.mak | 1 + hw/pcnet.c | 311 +------------------------------------- hw/pcnet.h | 3 + 5 files changed, 11 insertions(+), 308 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 72c6c7f..13ba26f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -222,7 +222,8 @@ hw-obj-$(CONFIG_PCI) += pcie.o pcie_port.o # PCI network cards hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o -hw-obj-$(CONFIG_PCNET_PCI) += pcnet.o +hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o +hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o hw-obj-$(CONFIG_SMC91C111) += smc91c111.o hw-obj-$(CONFIG_LAN9118) += lan9118.o diff --git a/default-configs/pci.mak b/default-configs/pci.mak index 0ddfb37..c74a99f 100644 --- a/default-configs/pci.mak +++ b/default-configs/pci.mak @@ -6,6 +6,7 @@ CONFIG_USB_OHCI=y CONFIG_NE2000_PCI=y CONFIG_EEPRO100_PCI=y CONFIG_PCNET_PCI=y +CONFIG_PCNET_COMMON=y CONFIG_LSI_SCSI_PCI=y CONFIG_RTL8139_PCI=y CONFIG_E1000_PCI=y diff --git a/default-configs/sparc-softmmu.mak b/default-configs/sparc-softmmu.mak index 436d2a6..b0310c5 100644 --- a/default-configs/sparc-softmmu.mak +++ b/default-configs/sparc-softmmu.mak @@ -7,3 +7,4 @@ CONFIG_M48T59=y CONFIG_PTIMER=y CONFIG_FDC=y CONFIG_EMPTY_SLOT=y +CONFIG_PCNET_COMMON=y diff --git a/hw/pcnet.c b/hw/pcnet.c index f970bda..37010b8 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -35,9 +35,8 @@ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt */ -#include "pci.h" +#include "qdev.h" #include "net.h" -#include "loader.h" #include "qemu-timer.h" #include "qemu_socket.h" @@ -52,11 +51,6 @@ //#define PCNET_DEBUG_MATCH -typedef struct { - PCIDevice pci_dev; - PCNetState state; -} PCIPCNetState; - struct qemu_ether_header { uint8_t ether_dhost[6]; uint8_t ether_shost[6]; @@ -704,7 +698,6 @@ static void pcnet_poll_timer(void *opaque); static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap); static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value); static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val); -static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap); static void pcnet_s_reset(PCNetState *s) { @@ -1538,7 +1531,7 @@ static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val) } } -static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap) +uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap) { uint32_t val; rap &= 127; @@ -1595,27 +1588,6 @@ void pcnet_h_reset(void *opaque) pcnet_poll_timer(s); } -static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - PCNetState *s = opaque; -#ifdef PCNET_DEBUG - printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val); -#endif - /* Check APROMWE bit to enable write access */ - if (pcnet_bcr_readw(s,2) & 0x100) - s->prom[addr & 15] = val; -} - -static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr) -{ - PCNetState *s = opaque; - uint32_t val = s->prom[addr & 15]; -#ifdef PCNET_DEBUG - printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val); -#endif - return val; -} - void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val) { PCNetState *s = opaque; @@ -1668,7 +1640,7 @@ uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr) return val; } -static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val) +void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val) { PCNetState *s = opaque; pcnet_poll_timer(s); @@ -1698,7 +1670,7 @@ static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val) pcnet_update_irq(s); } -static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr) +uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr) { PCNetState *s = opaque; uint32_t val = -1; @@ -1727,125 +1699,6 @@ static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr) return val; } -static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, - pcibus_t addr, pcibus_t size, int type) -{ - PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state; - -#ifdef PCNET_DEBUG_IO - printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n", - addr, size); -#endif - - register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d); - register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d); - - register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d); - register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d); - register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d); - register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d); -} - -static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - PCNetState *d = opaque; -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_writeb addr=0x" TARGET_FMT_plx" val=0x%02x\n", addr, - val); -#endif - if (!(addr & 0x10)) - pcnet_aprom_writeb(d, addr & 0x0f, val); -} - -static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) -{ - PCNetState *d = opaque; - uint32_t val = -1; - if (!(addr & 0x10)) - val = pcnet_aprom_readb(d, addr & 0x0f); -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_readb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, - val & 0xff); -#endif - return val; -} - -static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - PCNetState *d = opaque; -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, - val); -#endif - if (addr & 0x10) - pcnet_ioport_writew(d, addr & 0x0f, val); - else { - addr &= 0x0f; - pcnet_aprom_writeb(d, addr, val & 0xff); - pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8); - } -} - -static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) -{ - PCNetState *d = opaque; - uint32_t val = -1; - if (addr & 0x10) - val = pcnet_ioport_readw(d, addr & 0x0f); - else { - addr &= 0x0f; - val = pcnet_aprom_readb(d, addr+1); - val <<= 8; - val |= pcnet_aprom_readb(d, addr); - } -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_readw addr=0x" TARGET_FMT_plx" val = 0x%04x\n", addr, - val & 0xffff); -#endif - return val; -} - -static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - PCNetState *d = opaque; -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_writel addr=0x" TARGET_FMT_plx" val=0x%08x\n", addr, - val); -#endif - if (addr & 0x10) - pcnet_ioport_writel(d, addr & 0x0f, val); - else { - addr &= 0x0f; - pcnet_aprom_writeb(d, addr, val & 0xff); - pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8); - pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16); - pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24); - } -} - -static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) -{ - PCNetState *d = opaque; - uint32_t val; - if (addr & 0x10) - val = pcnet_ioport_readl(d, addr & 0x0f); - else { - addr &= 0x0f; - val = pcnet_aprom_readb(d, addr+3); - val <<= 8; - val |= pcnet_aprom_readb(d, addr+2); - val <<= 8; - val |= pcnet_aprom_readb(d, addr+1); - val <<= 8; - val |= pcnet_aprom_readb(d, addr); - } -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, - val); -#endif - return val; -} - static bool is_version_2(void *opaque, int version_id) { return version_id == 2; @@ -1875,18 +1728,6 @@ const VMStateDescription vmstate_pcnet = { } }; -static const VMStateDescription vmstate_pci_pcnet = { - .name = "pcnet", - .version_id = 3, - .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField []) { - VMSTATE_PCI_DEVICE(pci_dev, PCIPCNetState), - VMSTATE_STRUCT(state, PCIPCNetState, 0, vmstate_pcnet, PCNetState), - VMSTATE_END_OF_LIST() - } -}; - void pcnet_common_cleanup(PCNetState *d) { d->nic = NULL; @@ -1901,147 +1742,3 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); return 0; } - -/* PCI interface */ - -static CPUWriteMemoryFunc * const pcnet_mmio_write[] = { - &pcnet_mmio_writeb, - &pcnet_mmio_writew, - &pcnet_mmio_writel -}; - -static CPUReadMemoryFunc * const pcnet_mmio_read[] = { - &pcnet_mmio_readb, - &pcnet_mmio_readw, - &pcnet_mmio_readl -}; - -static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, - pcibus_t addr, pcibus_t size, int type) -{ - PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev); - -#ifdef PCNET_DEBUG_IO - printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n", - addr, size); -#endif - - cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index); -} - -static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr, - uint8_t *buf, int len, int do_bswap) -{ - cpu_physical_memory_write(addr, buf, len); -} - -static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, - uint8_t *buf, int len, int do_bswap) -{ - cpu_physical_memory_read(addr, buf, len); -} - -static void pci_pcnet_cleanup(VLANClientState *nc) -{ - PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque; - - pcnet_common_cleanup(d); -} - -static int pci_pcnet_uninit(PCIDevice *dev) -{ - PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev); - - cpu_unregister_io_memory(d->state.mmio_index); - qemu_del_timer(d->state.poll_timer); - qemu_free_timer(d->state.poll_timer); - qemu_del_vlan_client(&d->state.nic->nc); - return 0; -} - -static NetClientInfo net_pci_pcnet_info = { - .type = NET_CLIENT_TYPE_NIC, - .size = sizeof(NICState), - .can_receive = pcnet_can_receive, - .receive = pcnet_receive, - .cleanup = pci_pcnet_cleanup, -}; - -static int pci_pcnet_init(PCIDevice *pci_dev) -{ - PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev); - PCNetState *s = &d->state; - uint8_t *pci_conf; - -#if 0 - printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", - sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD)); -#endif - - pci_conf = pci_dev->config; - - pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD); - pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE); - pci_set_word(pci_conf + PCI_STATUS, - PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); - pci_conf[PCI_REVISION_ID] = 0x10; - pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET); - - pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0); - pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0); - - pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0 - pci_conf[PCI_MIN_GNT] = 0x06; - pci_conf[PCI_MAX_LAT] = 0xff; - - /* Handler for memory-mapped I/O */ - s->mmio_index = - cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state); - - pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE, - PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map); - - pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE, - PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map); - - s->irq = pci_dev->irq[0]; - s->phys_mem_read = pci_physical_memory_read; - s->phys_mem_write = pci_physical_memory_write; - - if (!pci_dev->qdev.hotplugged) { - static int loaded = 0; - if (!loaded) { - rom_add_option("pxe-pcnet.bin"); - loaded = 1; - } - } - - return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info); -} - -static void pci_reset(DeviceState *dev) -{ - PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev.qdev, dev); - - pcnet_h_reset(&d->state); -} - -static PCIDeviceInfo pcnet_info = { - .qdev.name = "pcnet", - .qdev.size = sizeof(PCIPCNetState), - .qdev.reset = pci_reset, - .qdev.vmsd = &vmstate_pci_pcnet, - .init = pci_pcnet_init, - .exit = pci_pcnet_uninit, - .qdev.props = (Property[]) { - DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf), - DEFINE_PROP_END_OF_LIST(), - } -}; - -static void pcnet_register_devices(void) -{ - pci_qdev_register(&pcnet_info); -} - -device_init(pcnet_register_devices) diff --git a/hw/pcnet.h b/hw/pcnet.h index efacc9f..534bdf9 100644 --- a/hw/pcnet.h +++ b/hw/pcnet.h @@ -32,6 +32,9 @@ struct PCNetState_st { void pcnet_h_reset(void *opaque); void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val); uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr); +void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val); +uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr); +uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap); int pcnet_can_receive(VLANClientState *nc); ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_); void pcnet_common_cleanup(PCNetState *d); -- cgit v1.1 From 661a1799ba6544a54888283db19dd51469da01e5 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sat, 27 Nov 2010 11:56:02 +0000 Subject: Add pcnet-pci.c Add file missing from last commit. Signed-off-by: Paul Brook --- hw/pcnet-pci.c | 345 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 hw/pcnet-pci.c diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c new file mode 100644 index 0000000..3dfbe46 --- /dev/null +++ b/hw/pcnet-pci.c @@ -0,0 +1,345 @@ +/* + * QEMU AMD PC-Net II (Am79C970A) PCI emulation + * + * Copyright (c) 2004 Antony T Curtis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* This software was written to be compatible with the specification: + * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet + * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000 + */ + +#include "pci.h" +#include "net.h" +#include "loader.h" +#include "qemu-timer.h" + +#include "pcnet.h" + +//#define PCNET_DEBUG +//#define PCNET_DEBUG_IO +//#define PCNET_DEBUG_BCR +//#define PCNET_DEBUG_CSR +//#define PCNET_DEBUG_RMD +//#define PCNET_DEBUG_TMD +//#define PCNET_DEBUG_MATCH + + +typedef struct { + PCIDevice pci_dev; + PCNetState state; +} PCIPCNetState; + +static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val) +{ + PCNetState *s = opaque; +#ifdef PCNET_DEBUG + printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val); +#endif + /* Check APROMWE bit to enable write access */ + if (pcnet_bcr_readw(s,2) & 0x100) + s->prom[addr & 15] = val; +} + +static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr) +{ + PCNetState *s = opaque; + uint32_t val = s->prom[addr & 15]; +#ifdef PCNET_DEBUG + printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val); +#endif + return val; +} + +static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, + pcibus_t addr, pcibus_t size, int type) +{ + PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state; + +#ifdef PCNET_DEBUG_IO + printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n", + addr, size); +#endif + + register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d); + register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d); + + register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d); + register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d); + register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d); + register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d); +} + +static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCNetState *d = opaque; +#ifdef PCNET_DEBUG_IO + printf("pcnet_mmio_writeb addr=0x" TARGET_FMT_plx" val=0x%02x\n", addr, + val); +#endif + if (!(addr & 0x10)) + pcnet_aprom_writeb(d, addr & 0x0f, val); +} + +static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) +{ + PCNetState *d = opaque; + uint32_t val = -1; + if (!(addr & 0x10)) + val = pcnet_aprom_readb(d, addr & 0x0f); +#ifdef PCNET_DEBUG_IO + printf("pcnet_mmio_readb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, + val & 0xff); +#endif + return val; +} + +static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCNetState *d = opaque; +#ifdef PCNET_DEBUG_IO + printf("pcnet_mmio_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, + val); +#endif + if (addr & 0x10) + pcnet_ioport_writew(d, addr & 0x0f, val); + else { + addr &= 0x0f; + pcnet_aprom_writeb(d, addr, val & 0xff); + pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8); + } +} + +static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) +{ + PCNetState *d = opaque; + uint32_t val = -1; + if (addr & 0x10) + val = pcnet_ioport_readw(d, addr & 0x0f); + else { + addr &= 0x0f; + val = pcnet_aprom_readb(d, addr+1); + val <<= 8; + val |= pcnet_aprom_readb(d, addr); + } +#ifdef PCNET_DEBUG_IO + printf("pcnet_mmio_readw addr=0x" TARGET_FMT_plx" val = 0x%04x\n", addr, + val & 0xffff); +#endif + return val; +} + +static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCNetState *d = opaque; +#ifdef PCNET_DEBUG_IO + printf("pcnet_mmio_writel addr=0x" TARGET_FMT_plx" val=0x%08x\n", addr, + val); +#endif + if (addr & 0x10) + pcnet_ioport_writel(d, addr & 0x0f, val); + else { + addr &= 0x0f; + pcnet_aprom_writeb(d, addr, val & 0xff); + pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8); + pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16); + pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24); + } +} + +static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) +{ + PCNetState *d = opaque; + uint32_t val; + if (addr & 0x10) + val = pcnet_ioport_readl(d, addr & 0x0f); + else { + addr &= 0x0f; + val = pcnet_aprom_readb(d, addr+3); + val <<= 8; + val |= pcnet_aprom_readb(d, addr+2); + val <<= 8; + val |= pcnet_aprom_readb(d, addr+1); + val <<= 8; + val |= pcnet_aprom_readb(d, addr); + } +#ifdef PCNET_DEBUG_IO + printf("pcnet_mmio_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, + val); +#endif + return val; +} + +static const VMStateDescription vmstate_pci_pcnet = { + .name = "pcnet", + .version_id = 3, + .minimum_version_id = 2, + .minimum_version_id_old = 2, + .fields = (VMStateField []) { + VMSTATE_PCI_DEVICE(pci_dev, PCIPCNetState), + VMSTATE_STRUCT(state, PCIPCNetState, 0, vmstate_pcnet, PCNetState), + VMSTATE_END_OF_LIST() + } +}; + +/* PCI interface */ + +static CPUWriteMemoryFunc * const pcnet_mmio_write[] = { + &pcnet_mmio_writeb, + &pcnet_mmio_writew, + &pcnet_mmio_writel +}; + +static CPUReadMemoryFunc * const pcnet_mmio_read[] = { + &pcnet_mmio_readb, + &pcnet_mmio_readw, + &pcnet_mmio_readl +}; + +static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, + pcibus_t addr, pcibus_t size, int type) +{ + PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev); + +#ifdef PCNET_DEBUG_IO + printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n", + addr, size); +#endif + + cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index); +} + +static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int do_bswap) +{ + cpu_physical_memory_write(addr, buf, len); +} + +static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int do_bswap) +{ + cpu_physical_memory_read(addr, buf, len); +} + +static void pci_pcnet_cleanup(VLANClientState *nc) +{ + PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque; + + pcnet_common_cleanup(d); +} + +static int pci_pcnet_uninit(PCIDevice *dev) +{ + PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev); + + cpu_unregister_io_memory(d->state.mmio_index); + qemu_del_timer(d->state.poll_timer); + qemu_free_timer(d->state.poll_timer); + qemu_del_vlan_client(&d->state.nic->nc); + return 0; +} + +static NetClientInfo net_pci_pcnet_info = { + .type = NET_CLIENT_TYPE_NIC, + .size = sizeof(NICState), + .can_receive = pcnet_can_receive, + .receive = pcnet_receive, + .cleanup = pci_pcnet_cleanup, +}; + +static int pci_pcnet_init(PCIDevice *pci_dev) +{ + PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev); + PCNetState *s = &d->state; + uint8_t *pci_conf; + +#if 0 + printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", + sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD)); +#endif + + pci_conf = pci_dev->config; + + pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD); + pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE); + pci_set_word(pci_conf + PCI_STATUS, + PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); + pci_conf[PCI_REVISION_ID] = 0x10; + pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET); + + pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0); + pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0); + + pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0 + pci_conf[PCI_MIN_GNT] = 0x06; + pci_conf[PCI_MAX_LAT] = 0xff; + + /* Handler for memory-mapped I/O */ + s->mmio_index = + cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state); + + pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE, + PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map); + + pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE, + PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map); + + s->irq = pci_dev->irq[0]; + s->phys_mem_read = pci_physical_memory_read; + s->phys_mem_write = pci_physical_memory_write; + + if (!pci_dev->qdev.hotplugged) { + static int loaded = 0; + if (!loaded) { + rom_add_option("pxe-pcnet.bin"); + loaded = 1; + } + } + + return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info); +} + +static void pci_reset(DeviceState *dev) +{ + PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev.qdev, dev); + + pcnet_h_reset(&d->state); +} + +static PCIDeviceInfo pcnet_info = { + .qdev.name = "pcnet", + .qdev.size = sizeof(PCIPCNetState), + .qdev.reset = pci_reset, + .qdev.vmsd = &vmstate_pci_pcnet, + .init = pci_pcnet_init, + .exit = pci_pcnet_uninit, + .qdev.props = (Property[]) { + DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf), + DEFINE_PROP_END_OF_LIST(), + } +}; + +static void pci_pcnet_register_devices(void) +{ + pci_qdev_register(&pcnet_info); +} + +device_init(pci_pcnet_register_devices) -- cgit v1.1 From 8337606d3588f80aea656db74127423bd6b61443 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 26 Nov 2010 16:31:37 +0100 Subject: ide: Factor ide_dma_set_inactive out Several places that stop a DMA transfer duplicate this code. Factor it out into a common function. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- hw/ide/core.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 484e0ca..7136ade 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -473,6 +473,14 @@ static void dma_buf_commit(IDEState *s, int is_write) qemu_sglist_destroy(&s->sg); } +static void ide_dma_set_inactive(BMDMAState *bm) +{ + bm->status &= ~BM_STATUS_DMAING; + bm->dma_cb = NULL; + bm->unit = -1; + bm->aiocb = NULL; +} + void ide_dma_error(IDEState *s) { ide_transfer_stop(s); @@ -587,11 +595,8 @@ static void ide_read_dma_cb(void *opaque, int ret) s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); eot: - bm->status &= ~BM_STATUS_DMAING; bm->status |= BM_STATUS_INT; - bm->dma_cb = NULL; - bm->unit = -1; - bm->aiocb = NULL; + ide_dma_set_inactive(bm); return; } @@ -733,11 +738,8 @@ static void ide_write_dma_cb(void *opaque, int ret) s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); eot: - bm->status &= ~BM_STATUS_DMAING; bm->status |= BM_STATUS_INT; - bm->dma_cb = NULL; - bm->unit = -1; - bm->aiocb = NULL; + ide_dma_set_inactive(bm); return; } @@ -1061,11 +1063,8 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; ide_set_irq(s->bus); eot: - bm->status &= ~BM_STATUS_DMAING; bm->status |= BM_STATUS_INT; - bm->dma_cb = NULL; - bm->unit = -1; - bm->aiocb = NULL; + ide_dma_set_inactive(bm); return; } @@ -2954,12 +2953,10 @@ void ide_dma_cancel(BMDMAState *bm) printf("aio_cancel\n"); #endif bdrv_aio_cancel(bm->aiocb); - bm->aiocb = NULL; } - bm->status &= ~BM_STATUS_DMAING; + /* cancel DMA request */ - bm->unit = -1; - bm->dma_cb = NULL; + ide_dma_set_inactive(bm); } } -- cgit v1.1 From e3982b3cf6d17fbba6839d5252f5f757a8d585dc Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 26 Nov 2010 16:47:42 +0100 Subject: ide: Set bus master inactive on error BMIDEA in the status register must be cleared on error. This makes FreeBSD respond (more) correctly to I/O errors. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- hw/ide/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/ide/core.c b/hw/ide/core.c index 7136ade..430350f 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -486,6 +486,8 @@ void ide_dma_error(IDEState *s) ide_transfer_stop(s); s->error = ABRT_ERR; s->status = READY_STAT | ERR_STAT; + ide_dma_set_inactive(s->bus->bmdma); + s->bus->bmdma->status |= BM_STATUS_INT; ide_set_irq(s->bus); } -- cgit v1.1 From c29947bbb0978d312074ec73be968bfab1b6c977 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 26 Nov 2010 16:44:53 +0100 Subject: ide: Ignore double DMA transfer starts/stops You can only start a DMA transfer if it's not running yet, and you can only cancel it if it's running. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- hw/ide/pci.c | 60 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 3722b77..404f045 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -39,38 +39,42 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) #ifdef DEBUG_IDE printf("%s: 0x%08x\n", __func__, val); #endif - if (!(val & BM_CMD_START)) { - /* - * We can't cancel Scatter Gather DMA in the middle of the - * operation or a partial (not full) DMA transfer would reach - * the storage so we wait for completion instead (we beahve - * like if the DMA was completed by the time the guest trying - * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not - * set). - * - * In the future we'll be able to safely cancel the I/O if the - * whole DMA operation will be submitted to disk with a single - * aio operation with preadv/pwritev. - */ - if (bm->aiocb) { - qemu_aio_flush(); + + /* Ignore writes to SSBM if it keeps the old value */ + if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) { + if (!(val & BM_CMD_START)) { + /* + * We can't cancel Scatter Gather DMA in the middle of the + * operation or a partial (not full) DMA transfer would reach + * the storage so we wait for completion instead (we beahve + * like if the DMA was completed by the time the guest trying + * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not + * set). + * + * In the future we'll be able to safely cancel the I/O if the + * whole DMA operation will be submitted to disk with a single + * aio operation with preadv/pwritev. + */ + if (bm->aiocb) { + qemu_aio_flush(); #ifdef DEBUG_IDE - if (bm->aiocb) - printf("ide_dma_cancel: aiocb still pending"); - if (bm->status & BM_STATUS_DMAING) - printf("ide_dma_cancel: BM_STATUS_DMAING still pending"); + if (bm->aiocb) + printf("ide_dma_cancel: aiocb still pending"); + if (bm->status & BM_STATUS_DMAING) + printf("ide_dma_cancel: BM_STATUS_DMAING still pending"); #endif + } + } else { + if (!(bm->status & BM_STATUS_DMAING)) { + bm->status |= BM_STATUS_DMAING; + /* start dma transfer if possible */ + if (bm->dma_cb) + bm->dma_cb(bm, 0); + } } - bm->cmd = val & 0x09; - } else { - if (!(bm->status & BM_STATUS_DMAING)) { - bm->status |= BM_STATUS_DMAING; - /* start dma transfer if possible */ - if (bm->dma_cb) - bm->dma_cb(bm, 0); - } - bm->cmd = val & 0x09; } + + bm->cmd = val & 0x09; } static void bmdma_addr_read(IORange *ioport, uint64_t addr, -- cgit v1.1 From b76876e602ca09ff848d99595a506feb1fd54ff4 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 26 Nov 2010 16:36:16 +0100 Subject: ide: Reset current_addr after stopping DMA Whenever SSBM is reset in the command register all state information is lost. Restarting DMA means that current_addr must be reset to the base address of the PRD table. The OS is not required to change the base address register before starting a DMA operation, it can reuse the value it wrote for an earlier request. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- hw/ide/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 404f045..ad406ee 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -65,6 +65,7 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) #endif } } else { + bm->cur_addr = bm->addr; if (!(bm->status & BM_STATUS_DMAING)) { bm->status |= BM_STATUS_DMAING; /* start dma transfer if possible */ @@ -101,7 +102,6 @@ static void bmdma_addr_write(IORange *ioport, uint64_t addr, #endif bm->addr &= ~(mask << shift); bm->addr |= ((data & mask) << shift) & ~3; - bm->cur_addr = bm->addr; } const IORangeOps bmdma_addr_ioport_ops = { -- cgit v1.1 From fd5d5c566af040be15f2cae1b14a47919974453d Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Thu, 9 Sep 2010 14:51:31 -0500 Subject: Use a Linux-style MAINTAINERS file I make no claims that this is accurate or exhaustive but I think it's a reasonable place to start. As the file mentions, the purpose of this file is to give contributors information about who they can go to with questions about a particular piece of code or who they can ask for review. If you sign up for a piece of code and indicate that it's Maintained or Supported, please be prepared to be responsive to questions about that subsystem. Signed-off-by: Anthony Liguori --- v1 -> v2 - Sort alphabetically - Copy in instructions from linux MAINTAINERS - Fix entries based on review feedback --- MAINTAINERS | 494 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 417 insertions(+), 77 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index e5165fb..59effc7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1,88 +1,428 @@ QEMU Maintainers ================ -Project leaders: ----------------- +The intention of this file is not to establish who owns what portions of the +code base, but to provide a set of names that developers can consult when they +have a question about a particular subset and also to provide a set of names +to be CC'd when submitting a patch to obtain appropriate review. -Fabrice Bellard -Paul Brook +In general, if you have a question about inclusion of a patch, you should +consult qemu-devel and not any specific individual privately. -CPU cores: ----------- +Descriptions of section entries: + + M: Mail patches to: FullName + L: Mailing list that is relevant to this area + W: Web-page with status/info + Q: Patchwork web based patch tracking system site + T: SCM tree type and location. Type is one of: git, hg, quilt, stgit. + S: Status, one of the following: + Supported: Someone is actually paid to look after this. + Maintained: Someone actually looks after it. + Odd Fixes: It has a maintainer but they don't have time to do + much other than throw the odd patch in. See below.. + Orphan: No current maintainer [but maybe you could take the + role as you write your new code]. + Obsolete: Old code. Something tagged obsolete generally means + it has been replaced by a better system and you + should be using that. + F: Files and directories with wildcard patterns. + A trailing slash includes all files and subdirectory files. + F: drivers/net/ all files in and below drivers/net + F: drivers/net/* all files in drivers/net, but not below + F: */net/* all files in "any top level directory"/net + One pattern per line. Multiple F: lines acceptable. + X: Files and directories that are NOT maintained, same rules as F: + Files exclusions are tested before file matches. + Can be useful for excluding a specific subdirectory, for instance: + F: net/ + X: net/ipv6/ + matches all files in and below net excluding net/ipv6/ + K: Keyword perl extended regex pattern to match content in a + patch or file. For instance: + K: of_get_profile + matches patches or files that contain "of_get_profile" + K: \b(printk|pr_(info|err))\b + matches patches or files that contain one or more of the words + printk, pr_info or pr_err + One regex pattern per line. Multiple K: lines acceptable. + + +General Project Administration +------------------------------ +M: Anthony Liguori +M: Paul Brook + +Guest CPU cores (TCG): +---------------------- +Alpha +M: qemu-devel@nongnu.org +S: Orphan +F: target-alpha/ -x86 Fabrice Bellard -ARM Paul Brook -SPARC Blue Swirl -MIPS ? -PowerPC Alexander Graf -M68K Paul Brook -SH4 ? -CRIS Edgar E. Iglesias -Alpha ? -MicroBlaze Edgar E. Iglesias -S390 ? - -Machines (sorted by CPU): -------------------------- - -x86 - pc.c Fabrice Bellard (new maintainer needed) ARM - integratorcp.c Paul Brook - versatilepb.c Paul Brook - Real View Paul Brook - spitz.c Andrzej Zaborowski - palm.c Andrzej Zaborowski - nseries.c Andrzej Zaborowski - stellaris.c Paul Brook - gumstix.c Thorsten Zitterell - mainstone.c Armin Kuster - musicpal.c Jan Kiszka -SPARC - sun4u.c Blue Swirl - sun4m.c Blue Swirl +M: Paul Brook +S: Maintained +F: target-arm/ + +CRIS +M: Edgar E. Iglesias +S: Maintained +F: target-cris/ + +M68K +M: Paul Brook +S: Maintained +F: target-m68k/ + +MicroBlaze +M: Edgar E. Iglesias +S: Maintained +F: target-microblaze/ + MIPS - mips_r4k.c Aurelien Jarno - mips_malta.c Aurelien Jarno - mips_jazz.c Hervé Poussineau - mips_mipssim.c ? +M: qemu-devel@nongnu.org +S: Orphan +F: target-mips/ + PowerPC - ppc_prep.c ? - ppc_oldworld.c Alexander Graf - ppc_newworld.c Alexander Graf - ppc405_boards.c Alexander Graf -M86K - mcf5208.c Paul Brook - an5206.c Paul Brook - dummy_m68k.c Paul Brook +M: Alexander Graf +S: Maintained +F: target-ppc/ + +S390 +M: Alexander Graf +S: Maintained +F: target-s390x/ + SH4 - shix.c ? - r2d.c Magnus Damm -CRIS - etraxfs.c Edgar E. Iglesias - axis_dev88.c Edgar E. Iglesias -Alpha -MicroBlaze - petalogix_s3adsp1800.c Edgar E. Iglesias +M: qemu-devel@nongnu.org +S: Orphan +F: target-sh4/ + +SPARC +M: Blue Swirl +S: Maintained +F: target-sparc/ + +X86 +M: qemu-devel@nongnu.org +S: Odd Fixes +F: target-i386/ + +Guest CPU Cores (KVM): +---------------------- + +Overall +M: Avi Kivity +M: Marcelo Tosatti +L: kvm@vger.kernel.org +S: Supported +F: kvm-* +F: */kvm.* + +PPC +M: Alexander Graf +S: Maintained +F: target-ppc/kvm.c + S390 - s390-*.c Alexander Graf - -Generic Subsystems: -------------------- - -Dynamic translator Fabrice Bellard -Main loop Fabrice Bellard (new maintainer needed) -TCG Fabrice Bellard -IDE device ? -SCSI device Paul Brook -PCI layer Michael S. Tsirkin -USB layer ? -Block layer ? -Graphic layer ? -Audio device layer Vassili Karpov (malc) -Character device layer ? -Network device layer ? -GDB stub ? -Linux user ? -Darwin user ? -SLIRP ? +M: Alexander Graf +S: Maintained +F: target-s390x/kvm.c + +X86 +M: Avi Kivity +M: Marcelo Tosatti +L: kvm@vger.kernel.org +S: Supported +F: target-i386/kvm.c + +ARM Machines +------------ +Gumstix +M: qemu-devel@nongnu.org +S: Orphan +F: hw/gumstix.c + +Integrator CP +M: Paul Brook +S: Maintained +F: hw/integratorcp.c + +Mainstone +M: qemu-devel@nongnu.org +S: Orphan +F: hw/mainstone.c + +Musicpal +M: Jan Kiszka +S: Maintained +F: hw/musicpal.c + +nSeries +M: Andrzej Zaborowski +S: Maintained +F: hw/nseries.c + +Palm +M: Andrzej Zaborowski +S: Maintained +F: hw/palm.c + +Real View +M: Paul Brook +S: Maintained +F: hw/realview* + +Spitz +M: Andrzej Zaborowski +S: Maintained +F: hw/spitz.c + +Stellaris +M: Paul Brook +S: Maintained +F: hw/stellaris.c + +Versatile PB +M: Paul Brook +S: Maintained +F: hw/versatilepb.c + +CRIS Machines +------------- +Axis Dev88 +M: Edgar E. Iglesias +S: Maintained +F: hw/axis_dev88.c + +etraxfs +M: Edgar E. Iglesias +S: Maintained +F: hw/etraxfs.c + +M86K Machines +------------- +an5206 +M: Paul Brook +S: Maintained +F: hw/an5206.c + +dummy_m68k +M: Paul Brook +S: Maintained +F: hw/dummy_m68k.c + +mcf5208 +M: Paul Brook +S: Maintained +F: hw/mcf5208.c + +MicroBlaze Machines +------------------- +petalogix_s3adsp1800 +M: Edgar E. Iglesias +S: Maintained +F: hw/petalogix_s3adsp1800.c + +MIPS Machines +------------- +Jazz +M: Hervé Poussineau +S: Maintained +F: hw/mips_jazz.c + +Malta +M: Aurelien Jarno +S: Maintained +F: hw/mips_malta.c + +Mipssim +M: qemu-devel@nongnu.org +S: Orphan +F: hw/mips_mipssim.c + +R4000 +M: Aurelien Jarno +S: Maintained +F: hw/mips_r4k.c + +PowerPC Machines +---------------- +405 +M: Alexander Graf +S: Maintained +F: hw/ppc405_boards.c + +New World +M: Alexander Graf +S: Maintained +F: hw/ppc_newworld.c + +Old World +M: Alexander Graf +S: Maintained +F: hw/ppc_oldworld.c + +Prep +M: qemu-devel@nongnu.org +S: Orphan +F: hw/ppc_prep.c + +SH4 Machines +------------ +R2D +M: Magnus Damm +S: Maintained +F: hw/r2d.c + +Shix +M: Magnus Damm +S: Oprhan +F: hw/shix.c + +SPARC Machines +-------------- +Sun4m +M: Blue Swirl +S: Maintained +F: hw/sun4m.c + +Sun4u +M: Blue Swirl +S: Maintained +F: hw/sun4u.c + +S390 Machines +------------- +S390 Virtio +M: Alexander Graf +S: Maintained +F: hw/s390-*.c + +X86 Machines +------------ +PC +M: Anthony Liguori +S: Supported +F: hw/pc.[ch] hw/pc_piix.c + +Devices +------- +IDE +M: Kevin Wolf +S: Odd Fixes +F: hw/ide/ + +PCI +M: Michael S. Tsirkin +S: Supported +F: hw/pci* +F: hw/piix* + +SCSI +M: Paul Brook +M: Kevin Wolf +S: Odd Fixes +F: hw/lsi53c895a.c +F: hw/scsi* + +USB +M: qemu-devel@nongnu.org +S: Odd Fixes +F: hw/usb* + +vhost +M: Michael S. Tsirkin +S: Supported +F: hw/vhost* + +virtio +M: Anthony Liguori +S: Supported +F: hw/virtio* + +virtio-9p +M: Venkateswararao Jujjuri (JV) +S: Supported +F: hw/virtio-9p* + +virtio-blk +M: Kevin Wolf +S: Supported +F: hw/virtio-blk* + +virtio-serial +M: Amit Shah +S: Supported +F: hw/virtio-serial* +F: hw/virtio-console* + +Subsystems +---------- +Audio +M: Vassili Karpov (malc) +S: Maintained +F: audio/ + +Block +M: Kevin Wolf +S: Supported +F: block* +F: block/ + +Character Devices +M: Anthony Liguori +S: Maintained +F: qemu-char.c + +GDB stub +M: qemu-devel@nongnu.org +S: Odd Fixes +F: gdbstub* +F: gdb-xml/ + +Graphics +M: Anthony Liguori +S: Maintained +F: ui/ + +Main loop +M: Anthony Liguori +S: Supported +F: vl.c + +Monitor (QMP/HMP) +M: Luiz Capitulino +M: Markus Armbruster +S: Supported +F: monitor.c + +Network device layer +M: Anthony Liguori +M: Mark McLoughlin +S: Maintained +F: net/ + +SLIRP +M: qemu-devel@nongnu.org +S: Orphan +F: slirp/ + +Usermode Emulation +------------------ +BSD user +M: Blue Swirl +S: Maintained +F: bsd-user/ + +Darwin user +M: qemu-devel@nongnu.org +S: Orphan +F: darwin-user/ + +Linux user +M: Riku Voipio +S: Maintained +F: linux-user/ -- cgit v1.1