* [Qemu-devel] [PATCH 0/2 v2][UPDATED] Open disk images with O_DIRECT @ 2007-12-17 22:09 Laurent Vivier 2007-12-17 22:09 ` [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" Laurent Vivier 0 siblings, 1 reply; 8+ messages in thread From: Laurent Vivier @ 2007-12-17 22:09 UTC (permalink / raw) Cc: qemu-devel These patches allow to open file using O_DIRECT and bypass the host I/O cache. The v2 is a new version including comments from Anthony Liguori ("directio" has been renamed "cache"), from Balazs Attila-Mihaly (for Win32 support, not tested) and Samuel Thibault (for the generic function qemu_memalign()". This version is an updated version with last CVS changes. [PATCH 1/2] Add "cache" parameter to "-drive" Using "cache=off" with "-drive" will open the disk image file using "O_DIRECT". [PATCH 2/2] Direct IDE I/O This patch enhances the "-drive ,cache=off" mode with IDE drive emulation by removing the buffer used in the IDE emulation. Laurent ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" 2007-12-17 22:09 [Qemu-devel] [PATCH 0/2 v2][UPDATED] Open disk images with O_DIRECT Laurent Vivier @ 2007-12-17 22:09 ` Laurent Vivier 2007-12-17 22:09 ` [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O Laurent Vivier 2007-12-17 23:08 ` [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" Fabrice Bellard 0 siblings, 2 replies; 8+ messages in thread From: Laurent Vivier @ 2007-12-17 22:09 UTC (permalink / raw) Cc: qemu-devel This patch adds a new parameter to "-drive" Using "cache=off" with "-drive" will open the disk image file using "O_DIRECT". By default, "cache" is set to "on" to keep original behavior of qemu. example: "-drive file=my_disk.qcow2,cache=off" --- block-raw-posix.c | 8 ++++++++ block-raw-win32.c | 4 ++++ block.c | 2 +- block.h | 1 + hw/fdc.c | 7 ++++++- hw/ide.c | 18 ++++++++++++++---- hw/scsi-disk.c | 3 ++- hw/sd.c | 11 ++++++++++- osdep.c | 20 ++++++++++++++++++++ osdep.h | 1 + vl.c | 28 ++++++++++++++++++++++++---- 11 files changed, 91 insertions(+), 12 deletions(-) Index: qemu/block.c =================================================================== --- qemu.orig/block.c 2007-12-17 21:39:22.000000000 +0100 +++ qemu/block.c 2007-12-17 21:48:30.000000000 +0100 @@ -380,7 +380,7 @@ int bdrv_open2(BlockDriverState *bs, con /* Note: for compatibility, we open disk image files as RDWR, and RDONLY as fallback */ if (!(flags & BDRV_O_FILE)) - open_flags = BDRV_O_RDWR; + open_flags = BDRV_O_RDWR | (flags & BDRV_O_DIRECT); else open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT); ret = drv->bdrv_open(bs, filename, open_flags); Index: qemu/block.h =================================================================== --- qemu.orig/block.h 2007-12-17 21:39:22.000000000 +0100 +++ qemu/block.h 2007-12-17 21:48:30.000000000 +0100 @@ -44,6 +44,7 @@ typedef struct QEMUSnapshotInfo { use a disk image format on top of it (default for bdrv_file_open()) */ +#define BDRV_O_DIRECT 0x0020 #ifndef QEMU_IMG void bdrv_info(void); Index: qemu/hw/fdc.c =================================================================== --- qemu.orig/hw/fdc.c 2007-12-17 09:09:56.000000000 +0100 +++ qemu/hw/fdc.c 2007-12-17 21:48:30.000000000 +0100 @@ -382,7 +382,7 @@ struct fdctrl_t { uint8_t cur_drv; uint8_t bootsel; /* Command FIFO */ - uint8_t fifo[FD_SECTOR_LEN]; + uint8_t *fifo; uint32_t data_pos; uint32_t data_len; uint8_t data_state; @@ -598,6 +598,11 @@ fdctrl_t *fdctrl_init (qemu_irq irq, int fdctrl = qemu_mallocz(sizeof(fdctrl_t)); if (!fdctrl) return NULL; + fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN); + if (fdctrl->fifo == NULL) { + qemu_free(fdctrl); + return NULL; + } fdctrl->result_timer = qemu_new_timer(vm_clock, fdctrl_result_timer, fdctrl); Index: qemu/hw/ide.c =================================================================== --- qemu.orig/hw/ide.c 2007-12-17 21:38:11.000000000 +0100 +++ qemu/hw/ide.c 2007-12-17 21:48:30.000000000 +0100 @@ -365,7 +365,7 @@ typedef struct IDEState { EndTransferFunc *end_transfer_func; uint8_t *data_ptr; uint8_t *data_end; - uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; + uint8_t *io_buffer; QEMUTimer *sector_write_timer; /* only used for win2k install hack */ uint32_t irq_count; /* counts IRQs when using win2k install hack */ /* CF-ATA extended error */ @@ -2377,17 +2377,24 @@ struct partition { static int guess_disk_lchs(IDEState *s, int *pcylinders, int *pheads, int *psectors) { - uint8_t buf[512]; + uint8_t *buf; int ret, i, heads, sectors, cylinders; struct partition *p; uint32_t nr_sects; + buf = qemu_memalign(512, 512); + if (buf == NULL) + return -1; ret = bdrv_read(s->bs, 0, buf, 1); - if (ret < 0) + if (ret < 0) { + qemu_free(buf); return -1; + } /* test msdos magic */ - if (buf[510] != 0x55 || buf[511] != 0xaa) + if (buf[510] != 0x55 || buf[511] != 0xaa) { + qemu_free(buf); return -1; + } for(i = 0; i < 4; i++) { p = ((struct partition *)(buf + 0x1be)) + i; nr_sects = le32_to_cpu(p->nr_sects); @@ -2408,9 +2415,11 @@ static int guess_disk_lchs(IDEState *s, printf("guessed geometry: LCHS=%d %d %d\n", cylinders, heads, sectors); #endif + qemu_free(buf); return 0; } } + qemu_free(buf); return -1; } @@ -2425,6 +2434,7 @@ static void ide_init2(IDEState *ide_stat for(i = 0; i < 2; i++) { s = ide_state + i; + s->io_buffer = qemu_memalign(512, MAX_MULT_SECTORS*512 + 4); if (i == 0) s->bs = hd0; else Index: qemu/hw/scsi-disk.c =================================================================== --- qemu.orig/hw/scsi-disk.c 2007-12-17 09:09:56.000000000 +0100 +++ qemu/hw/scsi-disk.c 2007-12-17 21:48:30.000000000 +0100 @@ -46,7 +46,7 @@ typedef struct SCSIRequest { int sector_count; /* The amounnt of data in the buffer. */ int buf_len; - uint8_t dma_buf[SCSI_DMA_BUF_SIZE]; + uint8_t *dma_buf; BlockDriverAIOCB *aiocb; struct SCSIRequest *next; } SCSIRequest; @@ -78,6 +78,7 @@ static SCSIRequest *scsi_new_request(SCS free_requests = r->next; } else { r = qemu_malloc(sizeof(SCSIRequest)); + r->dma_buf = qemu_memalign(512, SCSI_DMA_BUF_SIZE); } r->dev = s; r->tag = tag; Index: qemu/hw/sd.c =================================================================== --- qemu.orig/hw/sd.c 2007-12-12 17:21:25.000000000 +0100 +++ qemu/hw/sd.c 2007-12-17 21:48:30.000000000 +0100 @@ -1284,10 +1284,17 @@ int sd_do_command(SDState *sd, struct sd static void sd_blk_read(BlockDriverState *bdrv, void *data, uint32_t addr, uint32_t len) { - uint8_t buf[512]; + uint8_t *buf; uint32_t end = addr + len; + buf = qemu_memalign(512, 512); + if (buf == NULL) { + printf("sd_blk_read: cannot allocate memory\n"); + return; + } + if (!bdrv || bdrv_read(bdrv, addr >> 9, buf, 1) == -1) { + qemu_free(buf); printf("sd_blk_read: read error on host side\n"); return; } @@ -1297,11 +1304,13 @@ static void sd_blk_read(BlockDriverState if (bdrv_read(bdrv, end >> 9, buf, 1) == -1) { printf("sd_blk_read: read error on host side\n"); + qemu_free(buf); return; } memcpy(data + 512 - (addr & 511), buf, end & 511); } else memcpy(data, buf + (addr & 511), len); + qemu_free(buf); } static void sd_blk_write(BlockDriverState *bdrv, Index: qemu/osdep.c =================================================================== --- qemu.orig/osdep.c 2007-12-17 09:09:56.000000000 +0100 +++ qemu/osdep.c 2007-12-17 21:48:30.000000000 +0100 @@ -61,6 +61,10 @@ void *qemu_malloc(size_t size) } #if defined(_WIN32) +void *qemu_memalign(size_t alignment, size_t size) +{ + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +} void *qemu_vmalloc(size_t size) { @@ -172,6 +176,22 @@ static void kqemu_vfree(void *ptr) #endif +void *qemu_memalign(size_t alignment, size_t size) +{ +#if defined(_POSIX_C_SOURCE) + int ret; + void *ptr; + ret = posix_memalign(&ptr, alignment, size); + if (ret != 0) + return NULL; + return ptr; +#elif defined(_BSD) + return valloc(size); +#else + return memalign(alignment, size); +#endif +} + /* alloc shared memory pages */ void *qemu_vmalloc(size_t size) { Index: qemu/osdep.h =================================================================== --- qemu.orig/osdep.h 2007-12-17 09:09:56.000000000 +0100 +++ qemu/osdep.h 2007-12-17 21:48:30.000000000 +0100 @@ -48,6 +48,7 @@ void *qemu_mallocz(size_t size); void qemu_free(void *ptr); char *qemu_strdup(const char *str); +void *qemu_memalign(size_t alignment, size_t size); void *qemu_vmalloc(size_t size); void qemu_vfree(void *ptr); Index: qemu/vl.c =================================================================== --- qemu.orig/vl.c 2007-12-17 09:09:56.000000000 +0100 +++ qemu/vl.c 2007-12-17 22:03:52.000000000 +0100 @@ -4880,8 +4880,11 @@ static int drive_init(const char *str, i BlockDriverState *bdrv; int max_devs; int index; + int cache; + int bdrv_flags; char *params[] = { "bus", "unit", "if", "index", "cyls", "heads", - "secs", "trans", "media", "snapshot", "file", NULL }; + "secs", "trans", "media", "snapshot", "file", + "cache", NULL }; if (check_params(buf, sizeof(buf), params, str) < 0) { fprintf(stderr, "qemu: unknowm parameter '%s' in '%s'\n", @@ -4895,6 +4898,7 @@ static int drive_init(const char *str, i unit_id = -1; translation = BIOS_ATA_TRANSLATION_AUTO; index = -1; + cache = 1; if (!strcmp(machine->name, "realview") || !strcmp(machine->name, "SS-5") || @@ -5037,6 +5041,17 @@ static int drive_init(const char *str, i } } + if (get_param_value(buf, sizeof(buf), "cache", str)) { + if (!strcmp(buf, "off")) + cache = 0; + else if (!strcmp(buf, "on")) + cache = 1; + else { + fprintf(stderr, "qemu: invalid cache option\n"); + return -1; + } + } + get_param_value(file, sizeof(file), "file", str); /* compute bus and unit according index */ @@ -5127,8 +5142,12 @@ static int drive_init(const char *str, i } if (!file[0]) return 0; - if (bdrv_open(bdrv, file, snapshot ? BDRV_O_SNAPSHOT : 0) < 0 || - qemu_key_check(bdrv, file)) { + bdrv_flags = 0; + if (snapshot) + bdrv_flags |= BDRV_O_SNAPSHOT; + if (!cache) + bdrv_flags |= BDRV_O_DIRECT; + if (bdrv_open(bdrv, file, bdrv_flags) < 0 || qemu_key_check(bdrv, file)) { fprintf(stderr, "qemu: could not open disk image %s\n", file); return -1; @@ -7476,7 +7495,8 @@ static void help(int exitcode) "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n" "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][index=i]\n" - " [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]\n" + " [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]" + " [,cache=on|off]\n" " use 'file' as a drive image\n" "-mtdblock file use 'file' as on-board Flash memory image\n" "-sd file use 'file' as SecureDigital card image\n" Index: qemu/block-raw-posix.c =================================================================== --- qemu.orig/block-raw-posix.c 2007-12-17 21:50:32.000000000 +0100 +++ qemu/block-raw-posix.c 2007-12-17 21:52:41.000000000 +0100 @@ -106,6 +106,10 @@ static int raw_open(BlockDriverState *bs } if (flags & BDRV_O_CREAT) open_flags |= O_CREAT | O_TRUNC; +#ifdef O_DIRECT + if (flags & BDRV_O_DIRECT) + open_flags |= O_DIRECT; +#endif s->type = FTYPE_FILE; @@ -659,6 +663,10 @@ static int hdev_open(BlockDriverState *b open_flags |= O_RDONLY; bs->read_only = 1; } +#ifdef O_DIRECT + if (flags & BDRV_O_DIRECT) + open_flags |= O_DIRECT; +#endif s->type = FTYPE_FILE; #if defined(__linux__) Index: qemu/block-raw-win32.c =================================================================== --- qemu.orig/block-raw-win32.c 2007-12-17 21:50:32.000000000 +0100 +++ qemu/block-raw-win32.c 2007-12-17 21:52:55.000000000 +0100 @@ -473,6 +473,10 @@ static int hdev_open(BlockDriverState *b #else overlapped = FILE_FLAG_OVERLAPPED; #endif + if (flags & BDRV_O_DIRECT) + overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; + if (flags & BDRV_O_DIRECT) + overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL, create_flags, overlapped, NULL); ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O 2007-12-17 22:09 ` [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" Laurent Vivier @ 2007-12-17 22:09 ` Laurent Vivier 2007-12-17 23:02 ` Fabrice Bellard 2007-12-17 23:08 ` [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" Fabrice Bellard 1 sibling, 1 reply; 8+ messages in thread From: Laurent Vivier @ 2007-12-17 22:09 UTC (permalink / raw) Cc: qemu-devel This patch enhances the "-drive ,cache=off" mode with IDE drive emulation by removing the buffer used in the IDE emulation. --- block.c | 10 +++ block.h | 2 block_int.h | 1 cpu-all.h | 1 exec.c | 19 ++++++ hw/ide.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- vl.c | 1 7 files changed, 204 insertions(+), 6 deletions(-) Index: qemu/block.c =================================================================== --- qemu.orig/block.c 2007-12-17 21:48:30.000000000 +0100 +++ qemu/block.c 2007-12-17 22:21:23.000000000 +0100 @@ -758,6 +758,11 @@ void bdrv_set_translation_hint(BlockDriv bs->translation = translation; } +void bdrv_set_cache_hint(BlockDriverState *bs, int cache) +{ + bs->cache = cache; +} + void bdrv_get_geometry_hint(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs) { @@ -786,6 +791,11 @@ int bdrv_is_read_only(BlockDriverState * return bs->read_only; } +int bdrv_is_cached(BlockDriverState *bs) +{ + return bs->cache; +} + /* XXX: no longer used */ void bdrv_set_change_cb(BlockDriverState *bs, void (*change_cb)(void *opaque), void *opaque) Index: qemu/block.h =================================================================== --- qemu.orig/block.h 2007-12-17 21:48:30.000000000 +0100 +++ qemu/block.h 2007-12-17 22:21:23.000000000 +0100 @@ -113,6 +113,7 @@ void bdrv_set_geometry_hint(BlockDriverS int cyls, int heads, int secs); void bdrv_set_type_hint(BlockDriverState *bs, int type); void bdrv_set_translation_hint(BlockDriverState *bs, int translation); +void bdrv_set_cache_hint(BlockDriverState *bs, int cache); void bdrv_get_geometry_hint(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs); int bdrv_get_type_hint(BlockDriverState *bs); @@ -120,6 +121,7 @@ int bdrv_get_translation_hint(BlockDrive int bdrv_is_removable(BlockDriverState *bs); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_inserted(BlockDriverState *bs); +int bdrv_is_cached(BlockDriverState *bs); int bdrv_media_changed(BlockDriverState *bs); int bdrv_is_locked(BlockDriverState *bs); void bdrv_set_locked(BlockDriverState *bs, int locked); Index: qemu/block_int.h =================================================================== --- qemu.orig/block_int.h 2007-12-17 21:39:22.000000000 +0100 +++ qemu/block_int.h 2007-12-17 22:21:23.000000000 +0100 @@ -124,6 +124,7 @@ struct BlockDriverState { drivers. They are not used by the block driver */ int cyls, heads, secs, translation; int type; + int cache; char device_name[32]; BlockDriverState *next; }; Index: qemu/cpu-all.h =================================================================== --- qemu.orig/cpu-all.h 2007-12-13 09:19:28.000000000 +0100 +++ qemu/cpu-all.h 2007-12-17 22:21:23.000000000 +0100 @@ -838,6 +838,7 @@ int cpu_register_io_memory(int io_index, CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index); CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index); +extern uint8_t * cpu_physical_page_addr(target_phys_addr_t addr); void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write); static inline void cpu_physical_memory_read(target_phys_addr_t addr, Index: qemu/exec.c =================================================================== --- qemu.orig/exec.c 2007-12-17 09:09:56.000000000 +0100 +++ qemu/exec.c 2007-12-17 22:21:23.000000000 +0100 @@ -2071,6 +2071,25 @@ void cpu_register_physical_memory(target } } +uint8_t * cpu_physical_page_addr(target_phys_addr_t addr) +{ + target_phys_addr_t page; + unsigned long pd; + PhysPageDesc *p; + unsigned long addr1; + + page = addr & TARGET_PAGE_MASK; + p = phys_page_find(page >> TARGET_PAGE_BITS); + if (!p) + return (uint8_t*)-1; + + pd = p->phys_offset; + + addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + + return phys_ram_base + addr1; +} + /* XXX: temporary until new memory mapping API */ uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr) { Index: qemu/hw/ide.c =================================================================== --- qemu.orig/hw/ide.c 2007-12-17 21:48:30.000000000 +0100 +++ qemu/hw/ide.c 2007-12-17 22:21:23.000000000 +0100 @@ -815,7 +815,7 @@ static int dma_buf_rw(BMDMAState *bm, in } /* XXX: handle errors */ -static void ide_read_dma_cb(void *opaque, int ret) +static void ide_read_dma_cb_buffered(void *opaque, int ret) { BMDMAState *bm = opaque; IDEState *s = bm->ide_if; @@ -855,7 +855,86 @@ static void ide_read_dma_cb(void *opaque printf("aio_read: sector_num=%lld n=%d\n", sector_num, n); #endif bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n, - ide_read_dma_cb, bm); + ide_read_dma_cb_buffered, bm); +} + +static void ide_read_dma_cb_unbuffered(void *opaque, int ret) +{ + BMDMAState *bm = opaque; + IDEState *s = bm->ide_if; + int64_t sector_num; + int nsector; + int len; + uint8_t *phy_addr; + + if (s->nsector == 0) { + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + eot: + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + bm->dma_cb = NULL; + bm->ide_if = NULL; + bm->aiocb = NULL; + return; + } + + /* launch next transfer */ + + if (bm->cur_prd_len == 0) { + struct { + uint32_t addr; + uint32_t size; + } prd; + + cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + + bm->cur_addr += 8; + prd.addr = le32_to_cpu(prd.addr); + prd.size = le32_to_cpu(prd.size); + len = prd.size & 0xfffe; + if (len == 0) + len = 0x10000; + bm->cur_prd_addr = prd.addr; + while ((bm->cur_addr - bm->addr) < 4096) { + int tmp_len; + cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + prd.addr = le32_to_cpu(prd.addr); + prd.size = le32_to_cpu(prd.size); + if (bm->cur_prd_addr + len != prd.addr) + break; + tmp_len = prd.size & 0xfffe; + if (tmp_len == 0) + tmp_len = 0x10000; + len += tmp_len; + bm->cur_addr += 8; + if (prd.size & 0x80000000) + break; + } + bm->cur_prd_len = len; + } + + phy_addr = cpu_physical_page_addr(bm->cur_prd_addr); + if (phy_addr == (uint8_t *)-1) + goto eot; + + len = (s->nsector<<9); + if (len > bm->cur_prd_len) + len = bm->cur_prd_len; + + nsector = (len>>9); + bm->cur_prd_addr += (nsector<<9); + bm->cur_prd_len -= (nsector<<9); + + sector_num = ide_get_sector(s); + ide_set_sector(s, sector_num + nsector); + s->nsector-=nsector; + +#ifdef DEBUG_AIO + printf("aio_read: sector_num=%lld n=%d\n", (unsigned long long)sector_num, nsector); +#endif + bm->aiocb = bdrv_aio_read(s->bs, sector_num, phy_addr, nsector, + ide_read_dma_cb_unbuffered, bm); } static void ide_sector_read_dma(IDEState *s) @@ -863,7 +942,10 @@ static void ide_sector_read_dma(IDEState s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; s->io_buffer_index = 0; s->io_buffer_size = 0; - ide_dma_start(s, ide_read_dma_cb); + if (bdrv_is_cached(s->bs)) + ide_dma_start(s, ide_read_dma_cb_buffered); + else + ide_dma_start(s, ide_read_dma_cb_unbuffered); } static void ide_sector_write_timer_cb(void *opaque) @@ -916,7 +998,7 @@ static void ide_sector_write(IDEState *s } /* XXX: handle errors */ -static void ide_write_dma_cb(void *opaque, int ret) +static void ide_write_dma_cb_buffered(void *opaque, int ret) { BMDMAState *bm = opaque; IDEState *s = bm->ide_if; @@ -957,7 +1039,86 @@ static void ide_write_dma_cb(void *opaqu printf("aio_write: sector_num=%lld n=%d\n", sector_num, n); #endif bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n, - ide_write_dma_cb, bm); + ide_write_dma_cb_buffered, bm); +} + +static void ide_write_dma_cb_unbuffered(void *opaque, int ret) +{ + BMDMAState *bm = opaque; + IDEState *s = bm->ide_if; + int64_t sector_num; + int nsector; + int len; + uint8_t *phy_addr; + + if (s->nsector == 0) { + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + eot: + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + bm->dma_cb = NULL; + bm->ide_if = NULL; + bm->aiocb = NULL; + return; + } + + /* launch next transfer */ + + if (bm->cur_prd_len == 0) { + struct { + uint32_t addr; + uint32_t size; + } prd; + + cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + + bm->cur_addr += 8; + prd.addr = le32_to_cpu(prd.addr); + prd.size = le32_to_cpu(prd.size); + len = prd.size & 0xfffe; + if (len == 0) + len = 0x10000; + bm->cur_prd_addr = prd.addr; + while ((bm->cur_addr - bm->addr) < 4096) { + int tmp_len; + cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + prd.addr = le32_to_cpu(prd.addr); + prd.size = le32_to_cpu(prd.size); + if (bm->cur_prd_addr + len != prd.addr) + break; + tmp_len = prd.size & 0xfffe; + if (tmp_len == 0) + tmp_len = 0x10000; + len += tmp_len; + bm->cur_addr += 8; + if (prd.size & 0x80000000) + break; + } + bm->cur_prd_len = len; + } + + phy_addr = cpu_physical_page_addr(bm->cur_prd_addr); + if (phy_addr == (uint8_t *)-1) + goto eot; + + len = (s->nsector<<9); + if (len > bm->cur_prd_len) + len = bm->cur_prd_len; + + nsector = (len>>9); + bm->cur_prd_addr += (nsector<<9); + bm->cur_prd_len -= (nsector<<9); + + sector_num = ide_get_sector(s); + ide_set_sector(s, sector_num + nsector); + s->nsector-=nsector; + +#ifdef DEBUG_AIO + printf("aio_write: sector_num=%lld n=%d\n", (unsigned long long)sector_num, nsector); +#endif + bm->aiocb = bdrv_aio_write(s->bs, sector_num, phy_addr, nsector, + ide_write_dma_cb_unbuffered, bm); } static void ide_sector_write_dma(IDEState *s) @@ -965,7 +1126,10 @@ static void ide_sector_write_dma(IDEStat s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; s->io_buffer_index = 0; s->io_buffer_size = 0; - ide_dma_start(s, ide_write_dma_cb); + if (bdrv_is_cached(s->bs)) + ide_dma_start(s, ide_write_dma_cb_buffered); + else + ide_dma_start(s, ide_write_dma_cb_unbuffered); } static void ide_atapi_cmd_ok(IDEState *s) Index: qemu/vl.c =================================================================== --- qemu.orig/vl.c 2007-12-17 22:03:52.000000000 +0100 +++ qemu/vl.c 2007-12-17 22:21:23.000000000 +0100 @@ -5147,6 +5147,7 @@ static int drive_init(const char *str, i bdrv_flags |= BDRV_O_SNAPSHOT; if (!cache) bdrv_flags |= BDRV_O_DIRECT; + bdrv_set_cache_hint(bdrv, cache); if (bdrv_open(bdrv, file, bdrv_flags) < 0 || qemu_key_check(bdrv, file)) { fprintf(stderr, "qemu: could not open disk image %s\n", file); ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O 2007-12-17 22:09 ` [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O Laurent Vivier @ 2007-12-17 23:02 ` Fabrice Bellard 2007-12-18 0:03 ` Paul Brook 0 siblings, 1 reply; 8+ messages in thread From: Fabrice Bellard @ 2007-12-17 23:02 UTC (permalink / raw) To: Laurent Vivier, qemu-devel Laurent Vivier wrote: > This patch enhances the "-drive ,cache=off" mode with IDE drive emulation > by removing the buffer used in the IDE emulation. > --- > block.c | 10 +++ > block.h | 2 > block_int.h | 1 > cpu-all.h | 1 > exec.c | 19 ++++++ > hw/ide.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- > vl.c | 1 > 7 files changed, 204 insertions(+), 6 deletions(-) > [...] Unfortunately it is more complicated to write to the CPU memory. In particular, specific action should be done when translated code is present. A consistent API must include something like cpu_page_lock() / unlock(). Look at cpu_physical_memory_rw() to see the various issues which must be handled. Moreover, it would be better to add bus specific APIs (at least for PCI), but I can accept a CPU memory API for now. Fabrice. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O 2007-12-17 23:02 ` Fabrice Bellard @ 2007-12-18 0:03 ` Paul Brook 2007-12-18 9:55 ` Laurent Vivier 2007-12-18 16:38 ` Avi Kivity 0 siblings, 2 replies; 8+ messages in thread From: Paul Brook @ 2007-12-18 0:03 UTC (permalink / raw) To: qemu-devel; +Cc: Laurent Vivier On Monday 17 December 2007, Fabrice Bellard wrote: > Laurent Vivier wrote: > > This patch enhances the "-drive ,cache=off" mode with IDE drive emulation > > by removing the buffer used in the IDE emulation. > > --- > > block.c | 10 +++ > > block.h | 2 > > block_int.h | 1 > > cpu-all.h | 1 > > exec.c | 19 ++++++ > > hw/ide.c | 176 > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- vl.c > > | 1 > > 7 files changed, 204 insertions(+), 6 deletions(-) > > [...] > > Unfortunately it is more complicated to write to the CPU memory. In > particular, specific action should be done when translated code is > present. A consistent API must include something like cpu_page_lock() / > unlock(). Look at cpu_physical_memory_rw() to see the various issues > which must be handled. Moreover, it would be better to add bus specific > APIs (at least for PCI), but I can accept a CPU memory API for now. In general it may also be unsafe to do async writes directly to guest memory because you break the atomicity of loads/stores. Paul ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O 2007-12-18 0:03 ` Paul Brook @ 2007-12-18 9:55 ` Laurent Vivier 2007-12-18 16:38 ` Avi Kivity 1 sibling, 0 replies; 8+ messages in thread From: Laurent Vivier @ 2007-12-18 9:55 UTC (permalink / raw) To: Paul Brook; +Cc: qemu-devel [-- Attachment #1: Type: text/plain, Size: 1623 bytes --] Le mardi 18 décembre 2007 à 00:03 +0000, Paul Brook a écrit : > On Monday 17 December 2007, Fabrice Bellard wrote: > > Laurent Vivier wrote: > > > This patch enhances the "-drive ,cache=off" mode with IDE drive emulation > > > by removing the buffer used in the IDE emulation. > > > --- > > > block.c | 10 +++ > > > block.h | 2 > > > block_int.h | 1 > > > cpu-all.h | 1 > > > exec.c | 19 ++++++ > > > hw/ide.c | 176 > > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- vl.c > > > | 1 > > > 7 files changed, 204 insertions(+), 6 deletions(-) > > > [...] > > > > Unfortunately it is more complicated to write to the CPU memory. In > > particular, specific action should be done when translated code is > > present. A consistent API must include something like cpu_page_lock() / > > unlock(). Look at cpu_physical_memory_rw() to see the various issues > > which must be handled. Moreover, it would be better to add bus specific > > APIs (at least for PCI), but I can accept a CPU memory API for now. > > In general it may also be unsafe to do async writes directly to guest memory > because you break the atomicity of loads/stores. Thank you for your comments. I had some doubts on this patch too. I will not resend it. I will resend only the first one corrected with comments from Fabrice (malloc()/free()). Regards, Laurent -- ----------------- Laurent.Vivier@bull.net ------------------ "La perfection est atteinte non quand il ne reste rien à ajouter mais quand il ne reste rien à enlever." Saint Exupéry [-- Attachment #2: Ceci est une partie de message numériquement signée --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O 2007-12-18 0:03 ` Paul Brook 2007-12-18 9:55 ` Laurent Vivier @ 2007-12-18 16:38 ` Avi Kivity 1 sibling, 0 replies; 8+ messages in thread From: Avi Kivity @ 2007-12-18 16:38 UTC (permalink / raw) To: qemu-devel; +Cc: Laurent Vivier Paul Brook wrote: >> Unfortunately it is more complicated to write to the CPU memory. In >> particular, specific action should be done when translated code is >> present. A consistent API must include something like cpu_page_lock() / >> unlock(). Look at cpu_physical_memory_rw() to see the various issues >> which must be handled. Moreover, it would be better to add bus specific >> APIs (at least for PCI), but I can accept a CPU memory API for now. >> > > In general it may also be unsafe to do async writes directly to guest memory > because you break the atomicity of loads/stores. > > But that is true on real hardware as well, I think. The guest cannot expect atomicity if it dmas into the memory it is accessing. Also, it would be a rare guest that accesses memory while dma is active. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" 2007-12-17 22:09 ` [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" Laurent Vivier 2007-12-17 22:09 ` [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O Laurent Vivier @ 2007-12-17 23:08 ` Fabrice Bellard 1 sibling, 0 replies; 8+ messages in thread From: Fabrice Bellard @ 2007-12-17 23:08 UTC (permalink / raw) To: Laurent Vivier, qemu-devel Laurent Vivier wrote: > This patch adds a new parameter to "-drive" > > Using "cache=off" with "-drive" will open the disk image file using > "O_DIRECT". > > By default, "cache" is set to "on" to keep original behavior of qemu. > > example: > > "-drive file=my_disk.qcow2,cache=off" > --- > block-raw-posix.c | 8 ++++++++ > block-raw-win32.c | 4 ++++ > block.c | 2 +- > block.h | 1 + > hw/fdc.c | 7 ++++++- > hw/ide.c | 18 ++++++++++++++---- > hw/scsi-disk.c | 3 ++- > hw/sd.c | 11 ++++++++++- > osdep.c | 20 ++++++++++++++++++++ > osdep.h | 1 + > vl.c | 28 ++++++++++++++++++++++++---- > 11 files changed, 91 insertions(+), 12 deletions(-) > [...] I suggest trying to remove the malloc/free which are done at every blk_read/write for sd.c. Fabrice. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2007-12-18 16:38 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-12-17 22:09 [Qemu-devel] [PATCH 0/2 v2][UPDATED] Open disk images with O_DIRECT Laurent Vivier 2007-12-17 22:09 ` [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" Laurent Vivier 2007-12-17 22:09 ` [Qemu-devel] [PATCH 2/2 v2][UPDATED] Direct IDE I/O Laurent Vivier 2007-12-17 23:02 ` Fabrice Bellard 2007-12-18 0:03 ` Paul Brook 2007-12-18 9:55 ` Laurent Vivier 2007-12-18 16:38 ` Avi Kivity 2007-12-17 23:08 ` [Qemu-devel] [PATCH 1/2 v2][UPDATE] Add "cache" parameter to "-drive" Fabrice Bellard
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).