Re: [Qemu-devel] [PATCH 2/3] Compile vl.c once
This patch breaks cpu list(-cpu ?). -- SUN OF A BEACH On Fri, Apr 16, 2010 at 03:08, Blue Swirl blauwir...@gmail.com wrote: Since kvm.h can be used in files compiled once, we can partially revert b33612d03540fda7fa67485f1c20395beb7a2bf0. Signed-off-by: Blue Swirl blauwir...@gmail.com --- Makefile.objs | 2 +- Makefile.target | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index ab1af88..c0fe5e2 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -128,7 +128,7 @@ user-obj-y += cutils.o cache-utils.o # libhw hw-obj-y = -hw-obj-y += loader.o +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 hw-obj-y += watchdog.o diff --git a/Makefile.target b/Makefile.target index 34ceed6..3bd4b86 100644 --- a/Makefile.target +++ b/Makefile.target @@ -162,7 +162,7 @@ endif #CONFIG_BSD_USER # System emulator target ifdef CONFIG_SOFTMMU -obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o vl.o balloon.o +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 -- 1.6.2.4
Re: [Qemu-devel] Re: [PATCH] virtio-spec: document block CMD and FLUSH
A userspace barrier API would be very useful instead of doing fsync when only ordering is required. I'd like to follow that discussion too. Stefan On 4 May 2010 05:39, Rusty Russell ru...@rustcorp.com.au wrote: On Fri, 19 Feb 2010 08:52:20 am Michael S. Tsirkin wrote: I took a stub at documenting CMD and FLU... ISTR Christoph had withdrawn some patches in this area, and was waiting for him to resubmit? I've given up on figuring out the block device. What seem to me to be sane semantics along the lines of memory barriers are foreign to disk people: they want (and depend on) flushing everywhere. For example, tdb transactions do not require a flush, they only require what I would call a barrier: that prior data be written out before any future data. Surely that would be more efficient in general than a flush! In fact, TDB wants only writes to *that file* (and metadata) written out first; it has no ordering issues with other I/O on the same device. A generic I/O interface would allow you to specify this request depends on these outstanding requests and leave it at that. It might have some sync flush command for dumb applications and OSes. The userspace API might be not be as precise and only allow such a barrier against all prior writes on this fd. ISTR someone mentioning a desire for such an API years ago, so CC'ing the usual I/O suspects... Cheers, Rusty.
[Qemu-devel] [PATCH v4 1/5] char: Let writers know how much data was written in case of errors
On writing errors, we just returned -1 even if some bytes were already written out. Ensure we return the number of bytes written before we return the error (on a subsequent call to qemu_chr_write()). Signed-off-by: Amit Shah amit.s...@redhat.com --- qemu-char.c |9 +++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index ac65a1c..bc76000 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -522,8 +522,13 @@ static int unix_write(int fd, const uint8_t *buf, int len1) while (len 0) { ret = write(fd, buf, len); if (ret 0) { -if (errno != EINTR errno != EAGAIN) -return -1; +if (errno != EINTR errno != EAGAIN) { +if (len1 - len) { +return len1 - len; +} else { +return -1; +} +} } else if (ret == 0) { break; } else { -- 1.6.2.5
[Qemu-devel] [PATCH v4 3/5] char: unix/tcp: Add a non-blocking write handler
Add a non-blocking write handler that can return with -EAGAIN to the caller and also callback when the socket becomes writable. Non-blocking writes are only enabled for sockets that are opened in non-blocking mode and only for callers that have registered a callback handler for resuming writes. Signed-off-by: Amit Shah amit.s...@redhat.com --- qemu-char.c | 50 ++ 1 files changed, 50 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 1cae1d2..476bb4e 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2117,11 +2117,60 @@ static void tcp_chr_read(void *opaque) } } +static void tcp_chr_write_unblocked(void *opaque) +{ +CharDriverState *chr = opaque; +TCPCharDriver *s = chr-opaque; + +assert(chr-write_blocked chr-chr_write_unblocked); + +chr-write_blocked = false; +qemu_set_fd_handler2(s-fd, tcp_chr_read_poll, tcp_chr_read, NULL, chr); +chr-chr_write_unblocked(chr-handler_opaque); +} + +static ssize_t tcp_chr_write_nb(CharDriverState *chr, const uint8_t *buf, +size_t len) +{ +TCPCharDriver *s = chr-opaque; +ssize_t ret; + +if (!s-connected) { +/* XXX: indicate an error? */ +return len; +} + +ret = send_all(s-fd, buf, len, true); +if (ret == -EAGAIN) { +chr-write_blocked = true; +qemu_set_fd_handler2(s-fd, tcp_chr_read_poll, + tcp_chr_read, tcp_chr_write_unblocked, chr); +} +return ret; +} + static void tcp_chr_connect(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr-opaque; +IOHandler *write_cb; +int flags; +bool nonblock; + +flags = fcntl(s-fd, F_GETFL); +if (flags == -1) { +flags = 0; +} +nonblock = flags O_NONBLOCK; + +write_cb = NULL; +chr-nonblock = false; +if (nonblock chr-chr_write_unblocked) { +write_cb = chr-chr_write_unblocked; +chr-nonblock = true; +} +chr-write_blocked = false; s-connected = 1; qemu_set_fd_handler2(s-fd, tcp_chr_read_poll, tcp_chr_read, NULL, chr); @@ -2254,6 +2303,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) chr-opaque = s; chr-chr_write = tcp_chr_write; +chr-chr_write_nb = tcp_chr_write_nb; chr-chr_close = tcp_chr_close; chr-get_msgfd = tcp_get_msgfd; -- 1.6.2.5
[Qemu-devel] [PATCH v4 4/5] virtio-console: Factor out common init between console and generic ports
The initialisation for generic ports and console ports is similar. Factor out the parts that are the same in a different function that can be called from each of the initfns. Signed-off-by: Amit Shah amit.s...@redhat.com --- hw/virtio-console.c | 31 ++- 1 files changed, 14 insertions(+), 17 deletions(-) diff --git a/hw/virtio-console.c b/hw/virtio-console.c index 2bccdd0..1552f47 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -58,24 +58,28 @@ static void chr_event(void *opaque, int event) } } -/* Virtio Console Ports */ -static int virtconsole_initfn(VirtIOSerialDevice *dev) +static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev) { -VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, dev-qdev); -VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); - -port-info = dev-info; - -port-is_console = true; +vcon-port.info = dev-info; if (vcon-chr) { qemu_chr_add_handlers(vcon-chr, chr_can_read, chr_read, NULL, chr_event, vcon); -port-info-have_data = flush_buf; +vcon-port.info-have_data = flush_buf; } return 0; } +/* Virtio Console Ports */ +static int virtconsole_initfn(VirtIOSerialDevice *dev) +{ +VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, dev-qdev); +VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); + +port-is_console = true; +return generic_port_init(vcon, dev); +} + static int virtconsole_exitfn(VirtIOSerialDevice *dev) { VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, dev-qdev); @@ -115,14 +119,7 @@ static int virtserialport_initfn(VirtIOSerialDevice *dev) VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, dev-qdev); VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); -port-info = dev-info; - -if (vcon-chr) { -qemu_chr_add_handlers(vcon-chr, chr_can_read, chr_read, - NULL, chr_event, vcon); -port-info-have_data = flush_buf; -} -return 0; +return generic_port_init(vcon, dev); } static VirtIOSerialPortInfo virtserialport_info = { -- 1.6.2.5
[Qemu-devel] [PATCH v4 2/5] char: Add qemu_chr_write_nb() for nonblocking writes
For char devices whose backing files are open in non-blocking mode, non-blocking writes can now be made using qemu_chr_write_nb(). For non-blocking chardevs, we can return -EAGAIN to callers of qemu_chr_write_nb(). When the backend is ready to accept more data, we can let the caller know via a callback. -EAGAIN is returned only when the backend's file is non-blocking and a callback is registered by the caller when invoking qemu_chr_add_handlers(). In case a backend doesn't support non-blocking writes, qemu_chr_write_nb() fallsback to qemu_chr_write(). Update all callers of qemu chardevs to not register any callback handler for non-blocked writes. Individual callers can update their code to add a callback handler, register the handler at the time of calling qemu_chr_add_handlers() and call qemu_chr_write_nb() instead of qemu_chr_write() if they wish to receive -EAGAIN notifications. No backend currently supports non-blocking writes. Signed-off-by: Amit Shah amit.s...@redhat.com --- gdbstub.c|2 +- hw/debugcon.c|2 +- hw/escc.c|3 ++- hw/etraxfs_ser.c |4 ++-- hw/mcf_uart.c|2 +- hw/pl011.c |2 +- hw/pxa2xx.c |2 +- hw/serial.c |2 +- hw/sh_serial.c |2 +- hw/syborg_serial.c |3 ++- hw/usb-serial.c |2 +- hw/virtio-console.c |8 hw/xen_console.c |7 --- hw/xilinx_uartlite.c |5 +++-- monitor.c|4 ++-- net/slirp.c |2 +- net/socket.c |4 ++-- qemu-char.c | 35 +++ qemu-char.h |9 + qemu_socket.h|3 ++- 20 files changed, 68 insertions(+), 35 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 93c4850..d6e5b23 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -2650,7 +2650,7 @@ int gdbserver_start(const char *device) if (!chr) return -1; -qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, +qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, NULL, gdb_chr_event, NULL); } diff --git a/hw/debugcon.c b/hw/debugcon.c index 5ee6821..4fa9189 100644 --- a/hw/debugcon.c +++ b/hw/debugcon.c @@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s) exit(1); } -qemu_chr_add_handlers(s-chr, NULL, NULL, NULL, s); +qemu_chr_add_handlers(s-chr, NULL, NULL, NULL, NULL, s); } static int debugcon_isa_initfn(ISADevice *dev) diff --git a/hw/escc.c b/hw/escc.c index 6d2fd36..94d1ba7 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -904,7 +904,8 @@ static int escc_init1(SysBusDevice *dev) s-chn[i].clock = s-frequency / 2; if (s-chn[i].chr) { qemu_chr_add_handlers(s-chn[i].chr, serial_can_receive, - serial_receive1, serial_event, s-chn[i]); + serial_receive1, NULL, serial_event, + s-chn[i]); } } s-chn[0].otherchn = s-chn[1]; diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c index e1f9615..5e592c9 100644 --- a/hw/etraxfs_ser.c +++ b/hw/etraxfs_ser.c @@ -176,8 +176,8 @@ static int etraxfs_ser_init(SysBusDevice *dev) s-chr = qdev_init_chardev(dev-qdev); if (s-chr) qemu_chr_add_handlers(s-chr, - serial_can_receive, serial_receive, - serial_event, s); + serial_can_receive, serial_receive, NULL, + serial_event, s); return 0; } diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c index d16bac7..5cea623 100644 --- a/hw/mcf_uart.c +++ b/hw/mcf_uart.c @@ -277,7 +277,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) s-irq = irq; if (chr) { qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, - mcf_uart_event, s); + NULL, mcf_uart_event, s); } mcf_uart_reset(s); return s; diff --git a/hw/pl011.c b/hw/pl011.c index 81de91e..73ae086 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -304,7 +304,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id) s-flags = 0x90; if (s-chr) { qemu_chr_add_handlers(s-chr, pl011_can_receive, pl011_receive, - pl011_event, s); + NULL, pl011_event, s); } register_savevm(pl011_uart, -1, 1, pl011_save, pl011_load, s); return 0; diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 9095386..04dbda4 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -2012,7 +2012,7 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base, if (chr) qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty, -pxa2xx_fir_rx, pxa2xx_fir_event, s); + pxa2xx_fir_rx, NULL, pxa2xx_fir_event, s);
[Qemu-devel] [PATCH v4 5/5] virtio-console: Throttle virtio-serial-bus if we can't consume any more guest data
If the char device we're connected to is overwhelmed with data and it can't accept any more, signal to the virtio-serial-bus to stop sending us more data till we tell otherwise. If the current buffer being processed hasn't been completely written out to the char device, we have to keep it around and re-try sending it since the virtio-serial-bus code assumes we consume the entire buffer. Allow the chardev backends to return -EAGAIN; we're ready with a callback handler that will flush the remainder of the buffer. Also register with savevm so that we save/restore such a buffer across migration. Signed-off-by: Amit Shah amit.s...@redhat.com --- hw/virtio-console.c | 127 +-- 1 files changed, 123 insertions(+), 4 deletions(-) diff --git a/hw/virtio-console.c b/hw/virtio-console.c index 1552f47..035ef94 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -13,18 +13,92 @@ #include qemu-char.h #include virtio-serial.h +typedef struct Buffer { +uint8_t *buf; +size_t rem_len; +size_t offset; +} Buffer; + typedef struct VirtConsole { VirtIOSerialPort port; CharDriverState *chr; +Buffer *unflushed_buf; } VirtConsole; +static void add_unflushed_buf(VirtConsole *vcon, const uint8_t *buf, size_t len) +{ +vcon-unflushed_buf = qemu_malloc(sizeof(Buffer)); +vcon-unflushed_buf-buf = qemu_malloc(len); + +memcpy(vcon-unflushed_buf-buf, buf, len); +vcon-unflushed_buf-rem_len = len; +vcon-unflushed_buf-offset = 0; +} + +static void free_unflushed_buf(VirtConsole *vcon) +{ +if (vcon-unflushed_buf) { +qemu_free(vcon-unflushed_buf-buf); +qemu_free(vcon-unflushed_buf); +vcon-unflushed_buf = NULL; +} +} + +static int buffered_write_to_chardev(VirtConsole *vcon, const uint8_t *buf, + size_t len) +{ +size_t written; +ssize_t ret; + +written = 0; +do { +ret = qemu_chr_write_nb(vcon-chr, buf + written, len - written); +if (ret 0) { +if (vcon-unflushed_buf) { +vcon-unflushed_buf-offset += written; +vcon-unflushed_buf-rem_len -= written; +} else { +virtio_serial_throttle_port(vcon-port, true); +add_unflushed_buf(vcon, buf + written, len - written); +} + +return -EAGAIN; +} + +written += ret; +} while (written != len); + +return 0; +} + +/* Callback function called when the chardev can accept more data */ +static void chr_write_unblocked(void *opaque) +{ +VirtConsole *vcon = opaque; + +if (vcon-unflushed_buf) { +int ret; + +ret = buffered_write_to_chardev(vcon, vcon-unflushed_buf-buf + + vcon-unflushed_buf-offset, +vcon-unflushed_buf-rem_len); +if (ret 0) { +return; +} +free_unflushed_buf(vcon); +} +virtio_serial_throttle_port(vcon-port, false); +} /* Callback function that's called when the guest sends us data */ static void flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) { VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); -qemu_chr_write(vcon-chr, buf, len); +/* If a previous write was incomplete, we should've been throttled. */ +assert(!vcon-unflushed_buf); + +buffered_write_to_chardev(vcon, buf, len); } /* Readiness of the guest to accept data on a port */ @@ -48,25 +122,69 @@ static void chr_event(void *opaque, int event) VirtConsole *vcon = opaque; switch (event) { -case CHR_EVENT_OPENED: { +case CHR_EVENT_OPENED: virtio_serial_open(vcon-port); break; -} + case CHR_EVENT_CLOSED: +if (vcon-unflushed_buf) { +free_unflushed_buf(vcon); +} virtio_serial_close(vcon-port); break; } } +static void virtio_console_port_save(QEMUFile *f, void *opaque) +{ +VirtConsole *vcon = opaque; +uint32_t have_buffer; + +have_buffer = vcon-unflushed_buf ? true : false; + +qemu_put_be32s(f, have_buffer); +if (have_buffer) { +qemu_put_be64s(f, vcon-unflushed_buf-rem_len); +qemu_put_buffer(f, vcon-unflushed_buf-buf + + vcon-unflushed_buf-offset, +vcon-unflushed_buf-rem_len); +} +} + +static int virtio_console_port_load(QEMUFile *f, void *opaque, int version_id) +{ +VirtConsole *vcon = opaque; +uint32_t have_buffer; + +if (version_id 1) { +return -EINVAL; +} + +qemu_get_be32s(f, have_buffer); +if (have_buffer) { +vcon-unflushed_buf = qemu_mallocz(sizeof(Buffer)); + +qemu_get_be64s(f, vcon-unflushed_buf-rem_len); +vcon-unflushed_buf-buf = qemu_malloc(vcon-unflushed_buf-rem_len); +vcon-unflushed_buf-offset = 0; + +qemu_get_buffer(f,
[Qemu-devel] [PATCH v4 0/5] char: non-blocking writes, virtio-console flow control
Hello, This series lets interested callers ask for an -EAGAIN return from the chardev backends (only unix and tcp sockets as of now) to implement their own flow control. A new call, qemu_chr_write_nb() is added, that will fallback to qemu_chr_write() if the backend file isn't non-blocking or if no callback was supplied. Support for other backend types is easy to add and will be done in later patches. Amit Shah (5): char: Let writers know how much data was written in case of errors char: Add qemu_chr_write_nb() for nonblocking writes char: unix/tcp: Add a non-blocking write handler virtio-console: Factor out common init between console and generic ports virtio-console: Throttle virtio-serial-bus if we can't consume any more guest data gdbstub.c|2 +- hw/debugcon.c|2 +- hw/escc.c|3 +- hw/etraxfs_ser.c |4 +- hw/mcf_uart.c|2 +- hw/pl011.c |2 +- hw/pxa2xx.c |2 +- hw/serial.c |2 +- hw/sh_serial.c |2 +- hw/syborg_serial.c |3 +- hw/usb-serial.c |2 +- hw/virtio-console.c | 156 +++--- hw/xen_console.c |7 +- hw/xilinx_uartlite.c |5 +- monitor.c|4 +- net/slirp.c |2 +- net/socket.c |4 +- qemu-char.c | 94 +++--- qemu-char.h |9 +++ qemu_socket.h|3 +- 20 files changed, 257 insertions(+), 53 deletions(-)
[Qemu-devel] Re: [PATCH v4 3/5] char: unix/tcp: Add a non-blocking write handler
On 05/04/10 09:17, Amit Shah wrote: Add a non-blocking write handler that can return with -EAGAIN to the caller and also callback when the socket becomes writable. Non-blocking writes are only enabled for sockets that are opened in non-blocking mode and only for callers that have registered a callback handler for resuming writes. The logic will be pretty much the same for all filehandle-based backends on unix. So maybe create some helper functions, so implementing $backend_chr_write_unblocked can be done with just three lines of code? cheers, Gerd
[Qemu-devel] Re: [PATCH v4 3/5] char: unix/tcp: Add a non-blocking write handler
On 05/04/10 09:56, Amit Shah wrote: The logic will be pretty much the same for all filehandle-based backends on unix. So maybe create some helper functions, so implementing $backend_chr_write_unblocked can be done with just three lines of code? Yes, that's the next step. Let's push this for now and do that in a later patch series? Fine with me. cheers, Gerd
Re: [Qemu-devel] [PATCH v4 1/4] Modify DIRTY_FLAG value and introduce DIRTY_IDX to use as indexes of bit-based phys_ram_dirty.
Sure. Submitted as v5. Thanks, Yoshi 2010/5/4 Anthony Liguori anth...@codemonkey.ws: Hi Yoshi, Could you rebase this series and resubmit? It conflicts with the latest HEAD. Regards, Anthony Liguori On 04/19/2010 10:40 PM, Yoshiaki Tamura wrote: Replaces byte-based phys_ram_dirty bitmap with four (MASTER, VGA, CODE, MIGRATION) bit-based phys_ram_dirty bitmap. On allocation, it sets all bits in the bitmap. It uses ffs() to convert DIRTY_FLAG to DIRTY_IDX. Modifies wrapper functions for byte-based phys_ram_dirty bitmap to bit-based phys_ram_dirty bitmap. MASTER works as a buffer, and upon get_diry() or get_dirty_flags(), it calls cpu_physical_memory_sync_master() to update VGA and MIGRATION. Signed-off-by: Yoshiaki Tamuratamura.yoshi...@lab.ntt.co.jp --- cpu-all.h | 127 - exec.c | 15 +-- qemu-common.h | 3 + 3 files changed, 121 insertions(+), 24 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index f8bfa66..b6a2d91 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -37,6 +37,9 @@ #include softfloat.h +/* to use ffs in flag_to_idx() */ +#includestrings.h + #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) #define BSWAP_NEEDED #endif @@ -853,7 +856,6 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr); /* memory API */ extern int phys_ram_fd; -extern uint8_t *phys_ram_dirty; extern ram_addr_t ram_size; extern ram_addr_t last_ram_offset; @@ -878,50 +880,137 @@ extern int mem_prealloc; /* Set if TLB entry is an IO callback. */ #define TLB_MMIO (1 5) -#define VGA_DIRTY_FLAG 0x01 -#define CODE_DIRTY_FLAG 0x02 -#define MIGRATION_DIRTY_FLAG 0x08 +/* Use DIRTY_IDX as indexes of bit-based phys_ram_dirty. */ +#define MASTER_DIRTY_IDX 0 +#define VGA_DIRTY_IDX 1 +#define CODE_DIRTY_IDX 2 +#define MIGRATION_DIRTY_IDX 3 +#define NUM_DIRTY_IDX 4 + +#define MASTER_DIRTY_FLAG (1 MASTER_DIRTY_IDX) +#define VGA_DIRTY_FLAG (1 VGA_DIRTY_IDX) +#define CODE_DIRTY_FLAG (1 CODE_DIRTY_IDX) +#define MIGRATION_DIRTY_FLAG (1 MIGRATION_DIRTY_IDX) + +extern unsigned long *phys_ram_dirty[NUM_DIRTY_IDX]; + +static inline int dirty_flag_to_idx(int flag) +{ + return ffs(flag) - 1; +} + +static inline int dirty_idx_to_flag(int idx) +{ + return 1 idx; +} /* read dirty bit (return 0 or 1) */ static inline int cpu_physical_memory_is_dirty(ram_addr_t addr) { - return phys_ram_dirty[addr TARGET_PAGE_BITS] == 0xff; + unsigned long mask; + ram_addr_t index = (addr TARGET_PAGE_BITS) / HOST_LONG_BITS; + int offset = (addr TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); + + mask = 1UL offset; + return (phys_ram_dirty[MASTER_DIRTY_IDX][index] mask) == mask; +} + +static inline void cpu_physical_memory_sync_master(ram_addr_t index) +{ + if (phys_ram_dirty[MASTER_DIRTY_IDX][index]) { + phys_ram_dirty[VGA_DIRTY_IDX][index] + |= phys_ram_dirty[MASTER_DIRTY_IDX][index]; + phys_ram_dirty[MIGRATION_DIRTY_IDX][index] + |= phys_ram_dirty[MASTER_DIRTY_IDX][index]; + phys_ram_dirty[MASTER_DIRTY_IDX][index] = 0UL; + } } static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr) { - return phys_ram_dirty[addr TARGET_PAGE_BITS]; + unsigned long mask; + ram_addr_t index = (addr TARGET_PAGE_BITS) / HOST_LONG_BITS; + int offset = (addr TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); + int ret = 0, i; + + mask = 1UL offset; + cpu_physical_memory_sync_master(index); + + for (i = VGA_DIRTY_IDX; i= MIGRATION_DIRTY_IDX; i++) { + if (phys_ram_dirty[i][index] mask) { + ret |= dirty_idx_to_flag(i); + } + } + + return ret; +} + +static inline int cpu_physical_memory_get_dirty_idx(ram_addr_t addr, + int dirty_idx) +{ + unsigned long mask; + ram_addr_t index = (addr TARGET_PAGE_BITS) / HOST_LONG_BITS; + int offset = (addr TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); + + mask = 1UL offset; + cpu_physical_memory_sync_master(index); + return (phys_ram_dirty[dirty_idx][index] mask) == mask; } static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, int dirty_flags) { - return phys_ram_dirty[addr TARGET_PAGE_BITS] dirty_flags; + return cpu_physical_memory_get_dirty_idx(addr, + dirty_flag_to_idx(dirty_flags)); } static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) { - phys_ram_dirty[addr TARGET_PAGE_BITS] = 0xff; + unsigned long mask; + ram_addr_t index = (addr TARGET_PAGE_BITS) / HOST_LONG_BITS; + int offset = (addr TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); + + mask = 1UL offset; +
[Qemu-devel] Re: [PATCH] virtio-spec: document block CMD and FLUSH
On 05/04/2010 07:38 AM, Rusty Russell wrote: On Fri, 19 Feb 2010 08:52:20 am Michael S. Tsirkin wrote: I took a stub at documenting CMD and FLUSH request types in virtio block. Christoph, could you look over this please? I note that the interface seems full of warts to me, this might be a first step to cleaning them. ISTR Christoph had withdrawn some patches in this area, and was waiting for him to resubmit? I've given up on figuring out the block device. What seem to me to be sane semantics along the lines of memory barriers are foreign to disk people: they want (and depend on) flushing everywhere. For example, tdb transactions do not require a flush, they only require what I would call a barrier: that prior data be written out before any future data. Surely that would be more efficient in general than a flush! In fact, TDB wants only writes to *that file* (and metadata) written out first; it has no ordering issues with other I/O on the same device. I think that's SCSI ordered tags. A generic I/O interface would allow you to specify this request depends on these outstanding requests and leave it at that. It might have some sync flush command for dumb applications and OSes. The userspace API might be not be as precise and only allow such a barrier against all prior writes on this fd. Depends on all previous requests, and will commit before all following requests. ie a full barrier. ISTR someone mentioning a desire for such an API years ago, so CC'ing the usual I/O suspects... I'd love to see TCQ exposed to user space. -- error compiling committee.c: too many arguments to function
Re: [Qemu-devel] Qemu-KVM 0.12.3 and Multipath - Assertion
Am 03.05.2010 23:26, schrieb Peter Lieven: Hi Qemu/KVM Devel Team, i'm using qemu-kvm 0.12.3 with latest Kernel 2.6.33.3. As backend we use open-iSCSI with dm-multipath. Multipath is configured to queue i/o if no path is available. If we create a failure on all paths, qemu starts to consume 100% CPU due to i/o waits which is ok so far. 1 odd thing: The Monitor Interface is not responding any more ... What es a really blocker is that KVM crashes with: kvm: /usr/src/qemu-kvm-0.12.3/hw/ide/internal.h:507: bmdma_active_if: Assertion `bmdma-unit != (uint8_t)-1' failed. after the multipath has reestablisched at least one path. Can you get a stack backtrace with gdb? Any ideas? I remember this was working with earlier kernel/kvm/qemu versions. If it works in the same setup with an older qemu version, bisecting might help. Kevin
Re: [Qemu-devel] Re: [PATCH] Revert PCI: Convert pci_device_hot_add() to QObject
Anthony Liguori anth...@codemonkey.ws writes: On 05/03/2010 04:29 AM, Markus Armbruster wrote: [...] Why am I proposing to remove pci_add from QMP before its replacement is ready? I want it out sooner rather than later, because it isn't fully functional (errors and drive_add are missing), and we do not plan to complete the job. In other words, it's not really usable over QMP now, and it's not what we want for QMP anyway. Since we don't want it to be used over QMP, we should take it out, not leave it around as a trap for the uninitiated. Anyway, I'll respin with a more verbose commit message, and I'll throw in the buddy patch Revert monitor: Convert do_pci_device_hot_remove() to QObject. Does libvirt not use pci_add with QMP? Re QMP in general: libvirt has code for QMP, but it is disabled. It'll get enabled as soon as a usable QMP ships, which we all expect for the next release. Re pci_add over QMP, git://libvirt.org/libvirt.git has: commit efd4ee7871a631a9293e94d58fc4384c162388a7 Author: Daniel P. Berrange berra...@redhat.com Date: Wed Apr 14 15:23:38 2010 +0100 Remove code from JSON monitor for commands that won't be ported The QEMU developers have stated that they will not be porting the commands 'pci_add', 'pci_del', 'usb_add', 'usb_del' to the JSON mode monitor, since they're obsoleted by 'device_add' and 'device_del'. libvirt has (untested) code that would have supported those commands in theory, but since we already use device_add/del where available, there's no need to keep the legacy stuff anymore. The text mode monitor keeps support for all commands for sake of historical compatability. * src/qemu/qemu_monitor_json.c: Remove 'pci_add', 'pci_del', 'usb_add', 'usb_del' commands Does this answer your question?
[Qemu-devel] Re: [PATCH] virtio-spec: document block CMD and FLUSH
On Tue, May 04 2010, Rusty Russell wrote: On Fri, 19 Feb 2010 08:52:20 am Michael S. Tsirkin wrote: I took a stub at documenting CMD and FLUSH request types in virtio block. Christoph, could you look over this please? I note that the interface seems full of warts to me, this might be a first step to cleaning them. ISTR Christoph had withdrawn some patches in this area, and was waiting for him to resubmit? I've given up on figuring out the block device. What seem to me to be sane semantics along the lines of memory barriers are foreign to disk people: they want (and depend on) flushing everywhere. For example, tdb transactions do not require a flush, they only require what I would call a barrier: that prior data be written out before any future data. Surely that would be more efficient in general than a flush! In fact, TDB wants only writes to *that file* (and metadata) written out first; it has no ordering issues with other I/O on the same device. A generic I/O interface would allow you to specify this request depends on these outstanding requests and leave it at that. It might have some sync flush command for dumb applications and OSes. The userspace API might be not be as precise and only allow such a barrier against all prior writes on this fd. ISTR someone mentioning a desire for such an API years ago, so CC'ing the usual I/O suspects... It would be nice to have a more fuller API for this, but the reality is that only the flush approach is really workable. Even just strict ordering of requests could only be supported on SCSI, and even there the kernel still lacks proper guarantees on error handling to prevent reordering there. -- Jens Axboe
[Qemu-devel] [PATCH v5 4/4] Use cpu_physical_memory_get_dirty_range() to check multiple dirty pages.
Modifies ram_save_block() and ram_save_remaining() to use cpu_physical_memory_get_dirty_range() to check multiple dirty and non-dirty pages at once. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp Signed-off-by: OHMURA Kei ohmura@lab.ntt.co.jp --- arch_init.c | 54 +- 1 files changed, 33 insertions(+), 21 deletions(-) diff --git a/arch_init.c b/arch_init.c index cfc03ea..245a082 100644 --- a/arch_init.c +++ b/arch_init.c @@ -108,31 +108,37 @@ static int ram_save_block(QEMUFile *f) static ram_addr_t current_addr = 0; ram_addr_t saved_addr = current_addr; ram_addr_t addr = 0; -int found = 0; +ram_addr_t dirty_rams[HOST_LONG_BITS]; +int i, found = 0; while (addr last_ram_offset) { -if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) { +if ((found = cpu_physical_memory_get_dirty_range( + current_addr, last_ram_offset, dirty_rams, HOST_LONG_BITS, + MIGRATION_DIRTY_FLAG))) { uint8_t *p; -cpu_physical_memory_reset_dirty(current_addr, -current_addr + TARGET_PAGE_SIZE, -MIGRATION_DIRTY_FLAG); +for (i = 0; i found; i++) { +ram_addr_t page_addr = dirty_rams[i]; +cpu_physical_memory_reset_dirty(page_addr, +page_addr + TARGET_PAGE_SIZE, +MIGRATION_DIRTY_FLAG); -p = qemu_get_ram_ptr(current_addr); +p = qemu_get_ram_ptr(page_addr); -if (is_dup_page(p, *p)) { -qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS); -qemu_put_byte(f, *p); -} else { -qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE); -qemu_put_buffer(f, p, TARGET_PAGE_SIZE); +if (is_dup_page(p, *p)) { +qemu_put_be64(f, page_addr | RAM_SAVE_FLAG_COMPRESS); +qemu_put_byte(f, *p); +} else { +qemu_put_be64(f, page_addr | RAM_SAVE_FLAG_PAGE); +qemu_put_buffer(f, p, TARGET_PAGE_SIZE); +} } -found = 1; break; +} else { +addr += dirty_rams[0]; +current_addr = (saved_addr + addr) % last_ram_offset; } -addr += TARGET_PAGE_SIZE; -current_addr = (saved_addr + addr) % last_ram_offset; } return found; @@ -142,12 +148,18 @@ static uint64_t bytes_transferred; static ram_addr_t ram_save_remaining(void) { -ram_addr_t addr; +ram_addr_t addr = 0; ram_addr_t count = 0; +ram_addr_t dirty_rams[HOST_LONG_BITS]; +int found = 0; -for (addr = 0; addr last_ram_offset; addr += TARGET_PAGE_SIZE) { -if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) { -count++; +while (addr last_ram_offset) { +if ((found = cpu_physical_memory_get_dirty_range(addr, last_ram_offset, +dirty_rams, HOST_LONG_BITS, MIGRATION_DIRTY_FLAG))) { +count += found; +addr = dirty_rams[found - 1] + TARGET_PAGE_SIZE; +} else { +addr += dirty_rams[0]; } } -- 1.7.0.31.g1df487
[Qemu-devel] [PATCH v5 1/4] Modify DIRTY_FLAG value and introduce DIRTY_IDX to use as indexes of bit-based phys_ram_dirty.
Replaces byte-based phys_ram_dirty bitmap with four (MASTER, VGA, CODE, MIGRATION) bit-based phys_ram_dirty bitmap. On allocation, it sets all bits in the bitmap. It uses ffs() to convert DIRTY_FLAG to DIRTY_IDX. Modifies wrapper functions for byte-based phys_ram_dirty bitmap to bit-based phys_ram_dirty bitmap. MASTER works as a buffer, and upon get_diry() or get_dirty_flags(), it calls cpu_physical_memory_sync_master() to update VGA and MIGRATION. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- cpu-all.h | 128 - exec.c| 15 -- qemu-common.h |3 + 3 files changed, 121 insertions(+), 25 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 7b1594c..d21ecbc 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -37,6 +37,9 @@ #include softfloat.h +/* to use ffs in flag_to_idx() */ +#include strings.h + #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) #define BSWAP_NEEDED #endif @@ -853,7 +856,6 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr); /* memory API */ extern int phys_ram_fd; -extern uint8_t *phys_ram_dirty; extern ram_addr_t ram_size; extern ram_addr_t last_ram_offset; @@ -878,51 +880,137 @@ extern int mem_prealloc; /* Set if TLB entry is an IO callback. */ #define TLB_MMIO(1 5) -#define VGA_DIRTY_FLAG 0x01 -#define CODE_DIRTY_FLAG 0x02 -#define MIGRATION_DIRTY_FLAG 0x08 +/* Use DIRTY_IDX as indexes of bit-based phys_ram_dirty. */ +#define MASTER_DIRTY_IDX0 +#define VGA_DIRTY_IDX 1 +#define CODE_DIRTY_IDX 2 +#define MIGRATION_DIRTY_IDX 3 +#define NUM_DIRTY_IDX 4 + +#define MASTER_DIRTY_FLAG(1 MASTER_DIRTY_IDX) +#define VGA_DIRTY_FLAG (1 VGA_DIRTY_IDX) +#define CODE_DIRTY_FLAG (1 CODE_DIRTY_IDX) +#define MIGRATION_DIRTY_FLAG (1 MIGRATION_DIRTY_IDX) + +extern unsigned long *phys_ram_dirty[NUM_DIRTY_IDX]; + +static inline int dirty_flag_to_idx(int flag) +{ +return ffs(flag) - 1; +} + +static inline int dirty_idx_to_flag(int idx) +{ +return 1 idx; +} /* read dirty bit (return 0 or 1) */ static inline int cpu_physical_memory_is_dirty(ram_addr_t addr) { -return phys_ram_dirty[addr TARGET_PAGE_BITS] == 0xff; +unsigned long mask; +ram_addr_t index = (addr TARGET_PAGE_BITS) / HOST_LONG_BITS; +int offset = (addr TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); + +mask = 1UL offset; +return (phys_ram_dirty[MASTER_DIRTY_IDX][index] mask) == mask; +} + +static inline void cpu_physical_memory_sync_master(ram_addr_t index) +{ +if (phys_ram_dirty[MASTER_DIRTY_IDX][index]) { +phys_ram_dirty[VGA_DIRTY_IDX][index] +|= phys_ram_dirty[MASTER_DIRTY_IDX][index]; +phys_ram_dirty[MIGRATION_DIRTY_IDX][index] +|= phys_ram_dirty[MASTER_DIRTY_IDX][index]; +phys_ram_dirty[MASTER_DIRTY_IDX][index] = 0UL; +} } static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr) { -return phys_ram_dirty[addr TARGET_PAGE_BITS]; + unsigned long mask; + ram_addr_t index = (addr TARGET_PAGE_BITS) / HOST_LONG_BITS; + int offset = (addr TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); + int ret = 0, i; + + mask = 1UL offset; + cpu_physical_memory_sync_master(index); + + for (i = VGA_DIRTY_IDX; i = MIGRATION_DIRTY_IDX; i++) { + if (phys_ram_dirty[i][index] mask) { + ret |= dirty_idx_to_flag(i); + } + } + + return ret; +} + +static inline int cpu_physical_memory_get_dirty_idx(ram_addr_t addr, +int dirty_idx) +{ +unsigned long mask; +ram_addr_t index = (addr TARGET_PAGE_BITS) / HOST_LONG_BITS; +int offset = (addr TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); + +mask = 1UL offset; +cpu_physical_memory_sync_master(index); +return (phys_ram_dirty[dirty_idx][index] mask) == mask; } static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, int dirty_flags) { -return phys_ram_dirty[addr TARGET_PAGE_BITS] dirty_flags; +return cpu_physical_memory_get_dirty_idx(addr, + dirty_flag_to_idx(dirty_flags)); } static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) { -phys_ram_dirty[addr TARGET_PAGE_BITS] = 0xff; +unsigned long mask; +ram_addr_t index = (addr TARGET_PAGE_BITS) / HOST_LONG_BITS; +int offset = (addr TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); + +mask = 1UL offset; +phys_ram_dirty[MASTER_DIRTY_IDX][index] |= mask; } -static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr, - int dirty_flags) +static inline void cpu_physical_memory_set_dirty_range(ram_addr_t addr, + unsigned long mask) { -return
Re: [Qemu-devel] [PATCH 3/3] qemu-nbd: Improve error reporting
Am 03.05.2010 19:01, schrieb Anthony Liguori: On 03/29/2010 06:03 AM, Kevin Wolf wrote: Am 28.03.2010 19:07, schrieb Ryota Ozaki: - use err(3) instead of errx(3) if errno is available to report why failed - let fail prior to daemon(3) if opening a nbd file is likely to fail after daemonizing to avoid silent failure exit - add missing 'ret = 1' when unix_socket_outgoing failed Signed-off-by: Ryota Ozakiozaki.ry...@gmail.com Acked-by: Kevin Wolfkw...@redhat.com Are you going to pull this into the block branch? There was a v2 of this patch yesterday, which I did apply to the block branch. Kevin
Re: [Qemu-devel] Re: [PATCH] Revert PCI: Convert pci_device_hot_add() to QObject
On Mon, May 03, 2010 at 11:59:55AM -0500, Anthony Liguori wrote: On 05/03/2010 04:29 AM, Markus Armbruster wrote: Why am I proposing to remove pci_add from QMP before its replacement is ready? I want it out sooner rather than later, because it isn't fully functional (errors and drive_add are missing), and we do not plan to complete the job. In other words, it's not really usable over QMP now, and it's not what we want for QMP anyway. Since we don't want it to be used over QMP, we should take it out, not leave it around as a trap for the uninitiated. Anyway, I'll respin with a more verbose commit message, and I'll throw in the buddy patch Revert monitor: Convert do_pci_device_hot_remove() to QObject. Does libvirt not use pci_add with QMP? As of QEMU 0.12, libvirt uses -device syntax for everything. As of QEMU 0.13, libvirt will use QMP for everything (if compiled with the libyajl JSON library - otherwise text mode only). When -device is in use, we use device_add exclusively. Therefore, we will have no need for pci_add friends when using QMP. Regards, Daniel -- |: Red Hat, Engineering, London-o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org-o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
[Qemu-devel] [PATCH v5 2/4] Introduce cpu_physical_memory_get_dirty_range().
It checks the first row and puts dirty addr in the array. If the first row is empty, it skips to the first non-dirty row or the end addr, and put the length in the first entry of the array. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp Signed-off-by: OHMURA Kei ohmura@lab.ntt.co.jp --- cpu-all.h |4 +++ exec.c| 67 + 2 files changed, 71 insertions(+), 0 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index d21ecbc..6d7a7fd 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -1013,6 +1013,10 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, } } +int cpu_physical_memory_get_dirty_range(ram_addr_t start, ram_addr_t end, +ram_addr_t *dirty_rams, int length, +int dirty_flags); + void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int dirty_flags); void cpu_tlb_update_dirty(CPUState *env); diff --git a/exec.c b/exec.c index 6b4b1b3..3107487 100644 --- a/exec.c +++ b/exec.c @@ -2045,6 +2045,73 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, } } +/* It checks the first row and puts dirty addrs in the array. + If the first row is empty, it skips to the first non-dirty row + or the end addr, and put the length in the first entry of the array. */ +int cpu_physical_memory_get_dirty_range(ram_addr_t start, ram_addr_t end, +ram_addr_t *dirty_rams, int length, +int dirty_flag) +{ +unsigned long p = 0, page_number; +ram_addr_t addr; +ram_addr_t s_idx = (start TARGET_PAGE_BITS) / HOST_LONG_BITS; +ram_addr_t e_idx = (end TARGET_PAGE_BITS) / HOST_LONG_BITS; +int i, j, offset, dirty_idx = dirty_flag_to_idx(dirty_flag); + +/* mask bits before the start addr */ +offset = (start TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); +cpu_physical_memory_sync_master(s_idx); +p |= phys_ram_dirty[dirty_idx][s_idx] ~((1UL offset) - 1); + +if (s_idx == e_idx) { +/* mask bits after the end addr */ +offset = (end TARGET_PAGE_BITS) (HOST_LONG_BITS - 1); +p = (1UL offset) - 1; +} + +if (p == 0) { +/* when the row is empty */ +ram_addr_t skip; +if (s_idx == e_idx) { +skip = end; + } else { +/* skip empty rows */ +while (s_idx e_idx) { +s_idx++; +cpu_physical_memory_sync_master(s_idx); + +if (phys_ram_dirty[dirty_idx][s_idx] != 0) { +break; +} +} +skip = (s_idx * HOST_LONG_BITS * TARGET_PAGE_SIZE); +} +dirty_rams[0] = skip - start; +i = 0; + +} else if (p == ~0UL) { +/* when the row is fully dirtied */ +addr = start; +for (i = 0; i length; i++) { +dirty_rams[i] = addr; +addr += TARGET_PAGE_SIZE; +} +} else { +/* when the row is partially dirtied */ +i = 0; +do { +j = ffsl(p) - 1; +p = ~(1UL j); +page_number = s_idx * HOST_LONG_BITS + j; +addr = page_number * TARGET_PAGE_SIZE; +dirty_rams[i] = addr; +i++; +} while (p != 0 i length); +} + +return i; +} + /* Note: start and end must be within the same ram block. */ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int dirty_flags) -- 1.7.0.31.g1df487
[Qemu-devel] Re: apparent key mapping error for usb keyboard
On 04/27/2010 12:46 PM, Michael Tokarev wrote: I've a debian bugreport that claims to have a fix for apparently wrong keymap for usb keyboard. I noticed this before with ps/2 keyboard too, the sympthoms were that e.g windows keys were not working in guests, but later on that has been fixed. But with `-usbdevice keyboard', i.e. with usb keyboard, it still does not work. See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=578846 for details and for the proposed patch which fixes the mentioned issue. Here's the patch itself: --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -399,3 +399,3 @@ 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, I'm not sure if it's right fix however. Hence I'm asking for opinions here. If it's a right way to go, it should probably be applied to -stable too. I've no idea, but the correct place to ask is qemu-devel (copied). -- error compiling committee.c: too many arguments to function
[Qemu-devel] Re: [PATCH] virtio-spec: document block CMD and FLUSH
On Tue, May 04, 2010 at 02:08:24PM +0930, Rusty Russell wrote: On Fri, 19 Feb 2010 08:52:20 am Michael S. Tsirkin wrote: I took a stub at documenting CMD and FLUSH request types in virtio block. Christoph, could you look over this please? I note that the interface seems full of warts to me, this might be a first step to cleaning them. ISTR Christoph had withdrawn some patches in this area, and was waiting for him to resubmit? Any patches I've withdrawn in this area are withdrawn for good. But what I really need to do is to review Michaels spec updates, sorry. UI'll get back to it today.
[Qemu-devel] Re: [PATCH v4 2/5] char: Add qemu_chr_write_nb() for nonblocking writes
Hi, -static int unix_write(int fd, const uint8_t *buf, int len1) +static int unix_write(int fd, const uint8_t *buf, int len1, bool nonblock) { int ret, len; @@ -522,6 +537,9 @@ static int unix_write(int fd, const uint8_t *buf, int len1) while (len 0) { ret = write(fd, buf, len); if (ret 0) { +if (errno == EAGAIN nonblock) { +return -EAGAIN; +} You've just re-introduced the bug you've fixed in patch 1/5 ... cheers, Gerd
[Qemu-devel] [PATCH v5 3/4] Use cpu_physical_memory_set_dirty_range() to update phys_ram_dirty.
Modifies kvm_physical_sync_dirty_bitmap to use cpu_physical_memory_set_dirty_range() to update the row of the bit-based phys_ram_dirty bitmap at once. Signed-off-by: OHMURA Kei ohmura@lab.ntt.co.jp Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- kvm-all.c | 24 +--- 1 files changed, 9 insertions(+), 15 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index 6962b2b..5f8f1ec 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -290,8 +290,8 @@ static int kvm_get_dirty_pages_log_range(unsigned long start_addr, unsigned long offset, unsigned long mem_size) { -unsigned int i, j; -unsigned long page_number, addr, addr1, c; +unsigned int i; +unsigned long page_number, addr, addr1; ram_addr_t ram_addr; unsigned int len = ((mem_size / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) / HOST_LONG_BITS; @@ -302,23 +302,17 @@ static int kvm_get_dirty_pages_log_range(unsigned long start_addr, */ for (i = 0; i len; i++) { if (bitmap[i] != 0) { -c = leul_to_cpu(bitmap[i]); -do { -j = ffsl(c) - 1; -c = ~(1ul j); -page_number = i * HOST_LONG_BITS + j; -addr1 = page_number * TARGET_PAGE_SIZE; -addr = offset + addr1; -ram_addr = cpu_get_physical_page_desc(addr); -cpu_physical_memory_set_dirty(ram_addr); -} while (c != 0); +page_number = i * HOST_LONG_BITS; +addr1 = page_number * TARGET_PAGE_SIZE; +addr = offset + addr1; +ram_addr = cpu_get_physical_page_desc(addr); +cpu_physical_memory_set_dirty_range(ram_addr, +leul_to_cpu(bitmap[i])); } } return 0; } -#define ALIGN(x, y) (((x)+(y)-1) ~((y)-1)) - /** * kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty(). @@ -343,7 +337,7 @@ static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, break; } -size = ALIGN(((mem-memory_size) TARGET_PAGE_BITS), HOST_LONG_BITS) / 8; +size = BITMAP_SIZE(mem-memory_size); if (!d.dirty_bitmap) { d.dirty_bitmap = qemu_malloc(size); } else if (size allocated_size) { -- 1.7.0.31.g1df487
[Qemu-devel] simple block driver cleanups
This series cleans up the simple read-only block drivers to use the qemu block device API to access their backing devices, making the code simpler and usable over nbd/curl. I've not touched dmg yet as it's even more bitrot than usual and deserves it's own series.
[Qemu-devel] [PATCH 1/6] bochs: use pread
Use pread instead of lseek + read in preparation of using the qemu block API. Signed-off-by: Christoph Hellwig h...@lst.de Index: qemu-kevin/block/bochs.c === --- qemu-kevin.orig/block/bochs.c 2010-05-03 12:58:53.419012621 +0200 +++ qemu-kevin/block/bochs.c2010-05-03 12:59:13.873005360 +0200 @@ -125,7 +125,7 @@ static int bochs_open(BlockDriverState * s-fd = fd; -if (read(fd, bochs, sizeof(bochs)) != sizeof(bochs)) { +if (pread(fd, bochs, sizeof(bochs), 0) != sizeof(bochs)) { goto fail; } @@ -144,14 +144,10 @@ static int bochs_open(BlockDriverState * bs-total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512; } -if (lseek(s-fd, le32_to_cpu(bochs.header), SEEK_SET) == (off_t)-1) { -goto fail; -} - s-catalog_size = le32_to_cpu(bochs.extra.redolog.catalog); s-catalog_bitmap = qemu_malloc(s-catalog_size * 4); -if (read(s-fd, s-catalog_bitmap, s-catalog_size * 4) != - s-catalog_size * 4) +if (pread(s-fd, s-catalog_bitmap, s-catalog_size * 4, + le32_to_cpu(bochs.header)) != s-catalog_size * 4) goto fail; for (i = 0; i s-catalog_size; i++) le32_to_cpus(s-catalog_bitmap[i]); @@ -169,54 +165,35 @@ static int bochs_open(BlockDriverState * return -1; } -static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num) +static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num) { BDRVBochsState *s = bs-opaque; int64_t offset = sector_num * 512; -int64_t extent_index, extent_offset, bitmap_offset, block_offset; +int64_t extent_index, extent_offset, bitmap_offset; char bitmap_entry; // seek to sector extent_index = offset / s-extent_size; extent_offset = (offset % s-extent_size) / 512; -if (s-catalog_bitmap[extent_index] == 0x) -{ -// fprintf(stderr, page not allocated [%x - %x:%x]\n, -// sector_num, extent_index, extent_offset); - return -1; // not allocated +if (s-catalog_bitmap[extent_index] == 0x) { + return -1; /* not allocated */ } bitmap_offset = s-data_offset + (512 * s-catalog_bitmap[extent_index] * (s-extent_blocks + s-bitmap_blocks)); -block_offset = bitmap_offset + (512 * (s-bitmap_blocks + extent_offset)); -//fprintf(stderr, sect: %x [ext i: %x o: %x] - %x bitmap: %x block: %x\n, -// sector_num, extent_index, extent_offset, -// le32_to_cpu(s-catalog_bitmap[extent_index]), -// bitmap_offset, block_offset); - -// read in bitmap for current extent -if (lseek(s-fd, bitmap_offset + (extent_offset / 8), SEEK_SET) == -(off_t)-1) { +/* read in bitmap for current extent */ +if (pread(s-fd, bitmap_entry, 1, bitmap_offset + (extent_offset / 8)) +!= 1) { return -1; } -if (read(s-fd, bitmap_entry, 1) != 1) -return -1; - -if (!((bitmap_entry (extent_offset % 8)) 1)) -{ -// fprintf(stderr, sector (%x) in bitmap not allocated\n, -// sector_num); - return -1; // not allocated +if (!((bitmap_entry (extent_offset % 8)) 1)) { + return -1; /* not allocated */ } -if (lseek(s-fd, block_offset, SEEK_SET) == (off_t)-1) { -return -1; -} - -return 0; +return bitmap_offset + (512 * (s-bitmap_blocks + extent_offset)); } static int bochs_read(BlockDriverState *bs, int64_t sector_num, @@ -226,13 +203,13 @@ static int bochs_read(BlockDriverState * int ret; while (nb_sectors 0) { - if (!seek_to_sector(bs, sector_num)) - { - ret = read(s-fd, buf, 512); - if (ret != 512) - return -1; - } - else +int64_t block_offset = seek_to_sector(bs, sector_num); +if (block_offset = 0) { +ret = pread(s-fd, buf, 512, block_offset); +if (ret != 512) { +return -1; +} +} else memset(buf, 0, 512); nb_sectors--; sector_num++;
[Qemu-devel] [PATCH 2/6] bochs: use qemu block API
Use bdrv_pwrite to access the backing device instead of pread, and convert the driver to implementing the bdrv_open method which gives it an already opened BlockDriverState for the underlying device. Signed-off-by: Christoph Hellwig h...@lst.de Index: qemu-kevin/block/bochs.c === --- qemu-kevin.orig/block/bochs.c 2010-05-03 12:42:19.385274599 +0200 +++ qemu-kevin/block/bochs.c2010-05-03 12:48:54.434007033 +0200 @@ -80,8 +80,6 @@ struct bochs_header { }; typedef struct BDRVBochsState { -int fd; - uint32_t *catalog_bitmap; int catalog_size; @@ -109,23 +107,16 @@ static int bochs_probe(const uint8_t *bu return 0; } -static int bochs_open(BlockDriverState *bs, const char *filename, int flags) +static int bochs_open(BlockDriverState *bs, int flags) { BDRVBochsState *s = bs-opaque; -int fd, i; +int i; struct bochs_header bochs; struct bochs_header_v1 header_v1; -fd = open(filename, O_RDONLY | O_BINARY); -if (fd 0) { -return -1; -} - bs-read_only = 1; // no write support yet -s-fd = fd; - -if (pread(fd, bochs, sizeof(bochs), 0) != sizeof(bochs)) { +if (bdrv_pread(bs-file, 0, bochs, sizeof(bochs)) != sizeof(bochs)) { goto fail; } @@ -146,8 +137,8 @@ static int bochs_open(BlockDriverState * s-catalog_size = le32_to_cpu(bochs.extra.redolog.catalog); s-catalog_bitmap = qemu_malloc(s-catalog_size * 4); -if (pread(s-fd, s-catalog_bitmap, s-catalog_size * 4, - le32_to_cpu(bochs.header)) != s-catalog_size * 4) +if (bdrv_pread(bs-file, le32_to_cpu(bochs.header), s-catalog_bitmap, + s-catalog_size * 4) != s-catalog_size * 4) goto fail; for (i = 0; i s-catalog_size; i++) le32_to_cpus(s-catalog_bitmap[i]); @@ -161,7 +152,6 @@ static int bochs_open(BlockDriverState * return 0; fail: -close(fd); return -1; } @@ -184,8 +174,8 @@ static int64_t seek_to_sector(BlockDrive (s-extent_blocks + s-bitmap_blocks)); /* read in bitmap for current extent */ -if (pread(s-fd, bitmap_entry, 1, bitmap_offset + (extent_offset / 8)) -!= 1) { +if (bdrv_pread(bs-file, bitmap_offset + (extent_offset / 8), + bitmap_entry, 1) != 1) { return -1; } @@ -199,13 +189,12 @@ static int64_t seek_to_sector(BlockDrive static int bochs_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { -BDRVBochsState *s = bs-opaque; int ret; while (nb_sectors 0) { int64_t block_offset = seek_to_sector(bs, sector_num); if (block_offset = 0) { -ret = pread(s-fd, buf, 512, block_offset); +ret = bdrv_pread(bs-file, block_offset, buf, 512); if (ret != 512) { return -1; } @@ -222,14 +211,13 @@ static void bochs_close(BlockDriverState { BDRVBochsState *s = bs-opaque; qemu_free(s-catalog_bitmap); -close(s-fd); } static BlockDriver bdrv_bochs = { .format_name = bochs, .instance_size = sizeof(BDRVBochsState), .bdrv_probe= bochs_probe, -.bdrv_file_open= bochs_open, +.bdrv_open = bochs_open, .bdrv_read = bochs_read, .bdrv_close= bochs_close, };
[Qemu-devel] [PATCH 3/6] cloop: use pread
Use pread instead of lseek + read in preparation of using the qemu block API. Signed-off-by: Christoph Hellwig h...@lst.de Index: qemu-kevin/block/cloop.c === --- qemu-kevin.orig/block/cloop.c 2010-05-03 13:01:09.035025542 +0200 +++ qemu-kevin/block/cloop.c2010-05-03 13:01:57.918284307 +0200 @@ -62,23 +62,22 @@ static int cloop_open(BlockDriverState * bs-read_only = 1; /* read header */ -if(lseek(s-fd,128,SEEK_SET)0) { -cloop_close: - close(s-fd); - return -1; +if (pread(s-fd, s-block_size, 4, 128) 4) { +goto cloop_close; } -if(read(s-fd,s-block_size,4)4) - goto cloop_close; -s-block_size=be32_to_cpu(s-block_size); -if(read(s-fd,s-n_blocks,4)4) - goto cloop_close; -s-n_blocks=be32_to_cpu(s-n_blocks); +s-block_size = be32_to_cpu(s-block_size); + +if (pread(s-fd, s-n_blocks, 4, 128 + 4) 4) { +goto cloop_close; +} +s-n_blocks = be32_to_cpu(s-n_blocks); /* read offsets */ -offsets_size=s-n_blocks*sizeof(uint64_t); -s-offsets=(uint64_t*)qemu_malloc(offsets_size); -if(read(s-fd,s-offsets,offsets_size)offsets_size) +offsets_size = s-n_blocks * sizeof(uint64_t); +s-offsets = qemu_malloc(offsets_size); +if (pread(s-fd, s-offsets, offsets_size, 128 + 4 + 4) offsets_size) { goto cloop_close; +} for(i=0;is-n_blocks;i++) { s-offsets[i]=be64_to_cpu(s-offsets[i]); if(i0) { @@ -98,6 +97,10 @@ cloop_close: s-sectors_per_block = s-block_size/512; bs-total_sectors = s-n_blocks*s-sectors_per_block; return 0; + +cloop_close: +close(s-fd); +return -1; } static inline int cloop_read_block(BDRVCloopState *s,int block_num) @@ -106,8 +109,7 @@ static inline int cloop_read_block(BDRVC int ret; uint32_t bytes = s-offsets[block_num+1]-s-offsets[block_num]; - lseek(s-fd, s-offsets[block_num], SEEK_SET); -ret = read(s-fd, s-compressed_block, bytes); +ret = pread(s-fd, s-compressed_block, bytes, s-offsets[block_num]); if (ret != bytes) return -1;
[Qemu-devel] [PATCH 4/6] cloop: use qemu block API
Use bdrv_pwrite to access the backing device instead of pread, and convert the driver to implementing the bdrv_open method which gives it an already opened BlockDriverState for the underlying device. Signed-off-by: Christoph Hellwig h...@lst.de Index: qemu-kevin/block/cloop.c === --- qemu-kevin.orig/block/cloop.c 2010-05-03 13:01:57.918284307 +0200 +++ qemu-kevin/block/cloop.c2010-05-03 13:02:27.836318598 +0200 @@ -27,7 +27,6 @@ #include zlib.h typedef struct BDRVCloopState { -int fd; uint32_t block_size; uint32_t n_blocks; uint64_t* offsets; @@ -51,23 +50,20 @@ static int cloop_probe(const uint8_t *bu return 0; } -static int cloop_open(BlockDriverState *bs, const char *filename, int flags) +static int cloop_open(BlockDriverState *bs, int flags) { BDRVCloopState *s = bs-opaque; uint32_t offsets_size,max_compressed_block_size=1,i; -s-fd = open(filename, O_RDONLY | O_BINARY); -if (s-fd 0) -return -errno; bs-read_only = 1; /* read header */ -if (pread(s-fd, s-block_size, 4, 128) 4) { +if (bdrv_pread(bs-file, 128, s-block_size, 4) 4) { goto cloop_close; } s-block_size = be32_to_cpu(s-block_size); -if (pread(s-fd, s-n_blocks, 4, 128 + 4) 4) { +if (bdrv_pread(bs-file, 128 + 4, s-n_blocks, 4) 4) { goto cloop_close; } s-n_blocks = be32_to_cpu(s-n_blocks); @@ -75,7 +71,8 @@ static int cloop_open(BlockDriverState * /* read offsets */ offsets_size = s-n_blocks * sizeof(uint64_t); s-offsets = qemu_malloc(offsets_size); -if (pread(s-fd, s-offsets, offsets_size, 128 + 4 + 4) offsets_size) { +if (bdrv_pread(bs-file, 128 + 4 + 4, s-offsets, offsets_size) +offsets_size) { goto cloop_close; } for(i=0;is-n_blocks;i++) { @@ -99,17 +96,19 @@ static int cloop_open(BlockDriverState * return 0; cloop_close: -close(s-fd); return -1; } -static inline int cloop_read_block(BDRVCloopState *s,int block_num) +static inline int cloop_read_block(BlockDriverState *bs, int block_num) { +BDRVCloopState *s = bs-opaque; + if(s-current_block != block_num) { int ret; uint32_t bytes = s-offsets[block_num+1]-s-offsets[block_num]; -ret = pread(s-fd, s-compressed_block, bytes, s-offsets[block_num]); +ret = bdrv_pread(bs-file, s-offsets[block_num], s-compressed_block, + bytes); if (ret != bytes) return -1; @@ -138,7 +137,7 @@ static int cloop_read(BlockDriverState * for(i=0;inb_sectors;i++) { uint32_t sector_offset_in_block=((sector_num+i)%s-sectors_per_block), block_num=(sector_num+i)/s-sectors_per_block; - if(cloop_read_block(s, block_num) != 0) + if(cloop_read_block(bs, block_num) != 0) return -1; memcpy(buf+i*512,s-uncompressed_block+sector_offset_in_block*512,512); } @@ -148,7 +147,6 @@ static int cloop_read(BlockDriverState * static void cloop_close(BlockDriverState *bs) { BDRVCloopState *s = bs-opaque; -close(s-fd); if(s-n_blocks0) free(s-offsets); free(s-compressed_block); @@ -160,7 +158,7 @@ static BlockDriver bdrv_cloop = { .format_name = cloop, .instance_size = sizeof(BDRVCloopState), .bdrv_probe= cloop_probe, -.bdrv_file_open= cloop_open, +.bdrv_open = cloop_open, .bdrv_read = cloop_read, .bdrv_close= cloop_close, };
[Qemu-devel] [PATCH 5/6] parallels: use pread
Use pread instead of lseek + read in preparation of using the qemu block API. Signed-off-by: Christoph Hellwig h...@lst.de Index: qemu-kevin/block/parallels.c === --- qemu-kevin.orig/block/parallels.c 2010-05-03 13:00:09.711253925 +0200 +++ qemu-kevin/block/parallels.c2010-05-03 13:04:15.686033993 +0200 @@ -83,7 +83,7 @@ static int parallels_open(BlockDriverSta s-fd = fd; -if (read(fd, ph, sizeof(ph)) != sizeof(ph)) +if (pread(fd, ph, sizeof(ph), 0) != sizeof(ph)) goto fail; if (memcmp(ph.magic, HEADER_MAGIC, 16) || @@ -93,14 +93,11 @@ static int parallels_open(BlockDriverSta bs-total_sectors = le32_to_cpu(ph.nb_sectors); -if (lseek(s-fd, 64, SEEK_SET) != 64) - goto fail; - s-tracks = le32_to_cpu(ph.tracks); s-catalog_size = le32_to_cpu(ph.catalog_entries); s-catalog_bitmap = qemu_malloc(s-catalog_size * 4); -if (read(s-fd, s-catalog_bitmap, s-catalog_size * 4) != +if (pread(s-fd, s-catalog_bitmap, s-catalog_size * 4, 64) != s-catalog_size * 4) goto fail; for (i = 0; i s-catalog_size; i++) @@ -114,28 +111,18 @@ fail: return -1; } -static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num) +static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num) { BDRVParallelsState *s = bs-opaque; uint32_t index, offset; -uint64_t position; index = sector_num / s-tracks; offset = sector_num % s-tracks; -// not allocated +/* not allocated */ if ((index s-catalog_size) || (s-catalog_bitmap[index] == 0)) return -1; - -position = (uint64_t)(s-catalog_bitmap[index] + offset) * 512; - -//fprintf(stderr, sector: %llx index=%x offset=%x pointer=%x position=%x\n, -// sector_num, index, offset, s-catalog_bitmap[index], position); - -if (lseek(s-fd, position, SEEK_SET) != position) - return -1; - -return 0; +return (uint64_t)(s-catalog_bitmap[index] + offset) * 512; } static int parallels_read(BlockDriverState *bs, int64_t sector_num, @@ -144,11 +131,13 @@ static int parallels_read(BlockDriverSta BDRVParallelsState *s = bs-opaque; while (nb_sectors 0) { - if (!seek_to_sector(bs, sector_num)) { - if (read(s-fd, buf, 512) != 512) - return -1; - } else +uint64_t position = seek_to_sector(bs, sector_num); +if (position = 0) { +if (pread(s-fd, buf, 512, position) != 512) +return -1; +} else { memset(buf, 0, 512); +} nb_sectors--; sector_num++; buf += 512;
[Qemu-devel] [PATCH 6/6] parallels: use qemu block API
Use bdrv_pwrite to access the backing device instead of pread, and convert the driver to implementing the bdrv_open method which gives it an already opened BlockDriverState for the underlying device. Signed-off-by: Christoph Hellwig h...@lst.de Index: qemu-kevin/block/parallels.c === --- qemu-kevin.orig/block/parallels.c 2010-05-03 13:04:37.494261748 +0200 +++ qemu-kevin/block/parallels.c2010-05-03 13:05:55.781255810 +0200 @@ -46,7 +46,6 @@ struct parallels_header { } __attribute__((packed)); typedef struct BDRVParallelsState { -int fd; uint32_t *catalog_bitmap; int catalog_size; @@ -68,22 +67,15 @@ static int parallels_probe(const uint8_t return 0; } -static int parallels_open(BlockDriverState *bs, const char *filename, int flags) +static int parallels_open(BlockDriverState *bs, int flags) { BDRVParallelsState *s = bs-opaque; -int fd, i; +int i; struct parallels_header ph; -fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); -if (fd 0) { -return -1; -} - bs-read_only = 1; // no write support yet -s-fd = fd; - -if (pread(fd, ph, sizeof(ph), 0) != sizeof(ph)) +if (bdrv_pread(bs-file, 0, ph, sizeof(ph)) != sizeof(ph)) goto fail; if (memcmp(ph.magic, HEADER_MAGIC, 16) || @@ -97,7 +89,7 @@ static int parallels_open(BlockDriverSta s-catalog_size = le32_to_cpu(ph.catalog_entries); s-catalog_bitmap = qemu_malloc(s-catalog_size * 4); -if (pread(s-fd, s-catalog_bitmap, s-catalog_size * 4, 64) != +if (bdrv_pread(bs-file, 64, s-catalog_bitmap, s-catalog_size * 4) != s-catalog_size * 4) goto fail; for (i = 0; i s-catalog_size; i++) @@ -107,7 +99,6 @@ static int parallels_open(BlockDriverSta fail: if (s-catalog_bitmap) qemu_free(s-catalog_bitmap); -close(fd); return -1; } @@ -128,12 +119,10 @@ static int64_t seek_to_sector(BlockDrive static int parallels_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { -BDRVParallelsState *s = bs-opaque; - while (nb_sectors 0) { uint64_t position = seek_to_sector(bs, sector_num); if (position = 0) { -if (pread(s-fd, buf, 512, position) != 512) +if (bdrv_pread(bs-file, position, buf, 512) != 512) return -1; } else { memset(buf, 0, 512); @@ -149,14 +138,13 @@ static void parallels_close(BlockDriverS { BDRVParallelsState *s = bs-opaque; qemu_free(s-catalog_bitmap); -close(s-fd); } static BlockDriver bdrv_parallels = { .format_name = parallels, .instance_size = sizeof(BDRVParallelsState), .bdrv_probe= parallels_probe, -.bdrv_file_open= parallels_open, +.bdrv_open = parallels_open, .bdrv_read = parallels_read, .bdrv_close= parallels_close, };
[Qemu-devel] [PATCH v5 1/6] virtio-console: Factor out common init between console and generic ports
The initialisation for generic ports and console ports is similar. Factor out the parts that are the same in a different function that can be called from each of the initfns. Signed-off-by: Amit Shah amit.s...@redhat.com --- hw/virtio-console.c | 31 ++- 1 files changed, 14 insertions(+), 17 deletions(-) diff --git a/hw/virtio-console.c b/hw/virtio-console.c index caea11f..d7fe68b 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -58,24 +58,28 @@ static void chr_event(void *opaque, int event) } } -/* Virtio Console Ports */ -static int virtconsole_initfn(VirtIOSerialDevice *dev) +static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev) { -VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, dev-qdev); -VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); - -port-info = dev-info; - -port-is_console = true; +vcon-port.info = dev-info; if (vcon-chr) { qemu_chr_add_handlers(vcon-chr, chr_can_read, chr_read, chr_event, vcon); -port-info-have_data = flush_buf; +vcon-port.info-have_data = flush_buf; } return 0; } +/* Virtio Console Ports */ +static int virtconsole_initfn(VirtIOSerialDevice *dev) +{ +VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, dev-qdev); +VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); + +port-is_console = true; +return generic_port_init(vcon, dev); +} + static int virtconsole_exitfn(VirtIOSerialDevice *dev) { VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, dev-qdev); @@ -115,14 +119,7 @@ static int virtserialport_initfn(VirtIOSerialDevice *dev) VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, dev-qdev); VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); -port-info = dev-info; - -if (vcon-chr) { -qemu_chr_add_handlers(vcon-chr, chr_can_read, chr_read, chr_event, - vcon); -port-info-have_data = flush_buf; -} -return 0; +return generic_port_init(vcon, dev); } static VirtIOSerialPortInfo virtserialport_info = { -- 1.6.2.5
[Qemu-devel] [PATCH v5 0/6] char: non-blocking writes, virtio-console flow control
Hello, This series lets interested callers ask for an -EAGAIN return from the chardev backends (only unix and tcp sockets as of now) to implement their own flow control. A new call, qemu_chr_write_nb() is added, that will fallback to qemu_chr_write() if the backend file isn't non-blocking or if no callback was supplied. Support for other backend types is easy to add and will be done in later patches. v5: - Fix bug pointed out by Gerd - Convert to using a struct for passing on handlers to qemu_chr_add_handlers() instead of passing each one individually. Simplifies patches. (Inspired by Juan's comment) - Re-arranged patches Amit Shah (6): virtio-console: Factor out common init between console and generic ports char: Add a QemuChrHandlers struct to initialise chardev handlers char: Let writers know how much data was written in case of errors char: Add qemu_chr_write_nb() for nonblocking writes char: unix/tcp: Add a non-blocking write handler virtio-console: Throttle virtio-serial-bus if we can't consume any more guest data gdbstub.c|9 ++- hw/debugcon.c|2 +- hw/escc.c|9 ++- hw/etraxfs_ser.c | 13 +++- hw/mcf_uart.c|9 ++- hw/pl011.c |9 ++- hw/pxa2xx.c | 13 +++- hw/serial.c |9 ++- hw/sh_serial.c | 12 +++- hw/syborg_serial.c |9 ++- hw/usb-serial.c |9 ++- hw/virtio-console.c | 162 +++-- hw/xen_console.c | 16 -- hw/xilinx_uartlite.c | 11 +++- monitor.c| 19 +- net/slirp.c |8 ++- net/socket.c |4 +- qemu-char.c | 119 +++-- qemu-char.h | 20 +- qemu_socket.h|3 +- 20 files changed, 381 insertions(+), 84 deletions(-)
[Qemu-devel] [PATCH v5 3/6] char: Let writers know how much data was written in case of errors
On writing errors, we just returned -1 even if some bytes were already written out. Ensure we return the number of bytes written before we return the error (on a subsequent call to qemu_chr_write()). Signed-off-by: Amit Shah amit.s...@redhat.com --- qemu-char.c |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 65cb3f5..97f2ef6 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -507,6 +507,9 @@ int send_all(int fd, const void *buf, int len1) while (len 0) { ret = send(fd, buf, len, 0); if (ret 0) { +if (len1 - len) { +return len1 - len; +} errno = WSAGetLastError(); if (errno != WSAEWOULDBLOCK) { return -1; @@ -531,8 +534,12 @@ static int unix_write(int fd, const uint8_t *buf, int len1) while (len 0) { ret = write(fd, buf, len); if (ret 0) { -if (errno != EINTR errno != EAGAIN) +if (len1 - len) { +return len1 - len; +} +if (errno != EINTR errno != EAGAIN) { return -1; +} } else if (ret == 0) { break; } else { -- 1.6.2.5
[Qemu-devel] [PATCH v5 4/6] char: Add qemu_chr_write_nb() for nonblocking writes
For char devices whose backing files are open in non-blocking mode, non-blocking writes can now be made using qemu_chr_write_nb(). For non-blocking chardevs, we can return -EAGAIN to callers of qemu_chr_write_nb(). When the backend is ready to accept more data, we can let the caller know via a callback. -EAGAIN is returned only when the backend's file is non-blocking and a callback is registered by the caller when invoking qemu_chr_add_handlers(). In case a backend doesn't support non-blocking writes, qemu_chr_write_nb() invokes qemu_chr_write(). Individual callers can update their code to add a callback handler, call qemu_chr_write_nb() instead of qemu_chr_write() if they wish to receive -EAGAIN notifications. No backend currently supports non-blocking writes. Signed-off-by: Amit Shah amit.s...@redhat.com --- net/socket.c |4 ++-- qemu-char.c | 31 --- qemu-char.h |8 qemu_socket.h |3 ++- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/net/socket.c b/net/socket.c index 1c4e153..8a401e6 100644 --- a/net/socket.c +++ b/net/socket.c @@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_ uint32_t len; len = htonl(size); -send_all(s-fd, (const uint8_t *)len, sizeof(len)); -return send_all(s-fd, buf, size); +send_all(s-fd, (const uint8_t *)len, sizeof(len), false); +return send_all(s-fd, buf, size, false); } static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size) diff --git a/qemu-char.c b/qemu-char.c index 97f2ef6..d383c8f 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -145,6 +145,16 @@ int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) return s-chr_write(s, buf, len); } +ssize_t qemu_chr_write_nb(CharDriverState *s, const uint8_t *buf, size_t len) +{ +if (!s-nonblock) { +/* Fallback to blocking write if no callback registered */ +return qemu_chr_write(s, buf, len); +} + +return s-chr_write_nb(s, buf, len); +} + int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg) { if (!s-chr_ioctl) @@ -203,11 +213,15 @@ void qemu_chr_add_handlers(CharDriverState *s, } s-chr_can_read = handlers-fd_can_read; s-chr_read = handlers-fd_read; +s-chr_write_unblocked = handlers-fd_write_unblocked; s-chr_event = handlers-fd_event; s-handler_opaque = opaque; if (s-chr_update_read_handler) s-chr_update_read_handler(s); +/* We'll set this at connect-time */ +s-nonblock = false; + /* We're connecting to an already opened device, so let's make sure we also get the open event */ if (s-opened) { @@ -499,7 +513,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) #ifdef _WIN32 -int send_all(int fd, const void *buf, int len1) +int send_all(int fd, const void *buf, int len1, bool nonblock) { int ret, len; @@ -526,7 +540,7 @@ int send_all(int fd, const void *buf, int len1) #else -static int unix_write(int fd, const uint8_t *buf, int len1) +static int unix_write(int fd, const uint8_t *buf, int len1, bool nonblock) { int ret, len; @@ -537,6 +551,9 @@ static int unix_write(int fd, const uint8_t *buf, int len1) if (len1 - len) { return len1 - len; } +if (errno == EAGAIN nonblock) { +return -EAGAIN; +} if (errno != EINTR errno != EAGAIN) { return -1; } @@ -550,9 +567,9 @@ static int unix_write(int fd, const uint8_t *buf, int len1) return len1 - len; } -int send_all(int fd, const void *buf, int len1) +int send_all(int fd, const void *buf, int len1, bool nonblock) { -return unix_write(fd, buf, len1); +return unix_write(fd, buf, len1, nonblock); } #endif /* !_WIN32 */ @@ -569,7 +586,7 @@ static int stdio_nb_clients = 0; static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { FDCharDriver *s = chr-opaque; -return send_all(s-fd_out, buf, len); +return send_all(s-fd_out, buf, len, false); } static int fd_chr_read_poll(void *opaque) @@ -881,7 +898,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) pty_chr_update_read_handler(chr); return 0; } -return send_all(s-fd, buf, len); +return send_all(s-fd, buf, len, false); } static int pty_chr_read_poll(void *opaque) @@ -1946,7 +1963,7 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { TCPCharDriver *s = chr-opaque; if (s-connected) { -return send_all(s-fd, buf, len); +return send_all(s-fd, buf, len, false); } else { /* XXX: indicate an error ? */ return len; diff --git a/qemu-char.h b/qemu-char.h index 6ff490b..7b10b2b 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -1,6 +1,8 @@ #ifndef QEMU_CHAR_H #define
[Qemu-devel] [PATCH v5 2/6] char: Add a QemuChrHandlers struct to initialise chardev handlers
Instead of passing each handler in the qemu_add_handlers() function, create a struct of handlers that can be passed to the function instead. Signed-off-by: Amit Shah amit.s...@redhat.com --- gdbstub.c|9 +++-- hw/debugcon.c|2 +- hw/escc.c|9 +++-- hw/etraxfs_ser.c | 13 + hw/mcf_uart.c|9 +++-- hw/pl011.c |9 +++-- hw/pxa2xx.c | 13 + hw/serial.c |9 +++-- hw/sh_serial.c | 12 +--- hw/syborg_serial.c |9 +++-- hw/usb-serial.c |9 +++-- hw/virtio-console.c |9 +++-- hw/xen_console.c | 16 +++- hw/xilinx_uartlite.c | 11 +-- monitor.c| 19 +++ net/slirp.c |8 ++-- qemu-char.c | 27 ++- qemu-char.h | 12 18 files changed, 151 insertions(+), 54 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 93c4850..7b981ce 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -2621,6 +2621,12 @@ static void gdb_sigterm_handler(int signal) } #endif +static QemuChrHandlers gdb_handlers = { +.fd_can_read = gdb_chr_can_receive, +.fd_read = gdb_chr_receive, +.fd_event = gdb_chr_event, +}; + int gdbserver_start(const char *device) { GDBState *s; @@ -2650,8 +2656,7 @@ int gdbserver_start(const char *device) if (!chr) return -1; -qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, - gdb_chr_event, NULL); +qemu_chr_add_handlers(chr, gdb_handlers, NULL); } s = gdbserver_state; diff --git a/hw/debugcon.c b/hw/debugcon.c index 5ee6821..e79a595 100644 --- a/hw/debugcon.c +++ b/hw/debugcon.c @@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s) exit(1); } -qemu_chr_add_handlers(s-chr, NULL, NULL, NULL, s); +qemu_chr_add_handlers(s-chr, NULL, s); } static int debugcon_isa_initfn(ISADevice *dev) diff --git a/hw/escc.c b/hw/escc.c index 6d2fd36..1978bf7 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -890,6 +890,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq, sysbus_mmio_map(s, 0, base); } +static QemuChrHandlers serial_handlers = { +.fd_can_read = serial_can_receive, +.fd_read = serial_receive1, +.fd_event = serial_event, +}; + static int escc_init1(SysBusDevice *dev) { SerialState *s = FROM_SYSBUS(SerialState, dev); @@ -903,8 +909,7 @@ static int escc_init1(SysBusDevice *dev) s-chn[i].chn = 1 - i; s-chn[i].clock = s-frequency / 2; if (s-chn[i].chr) { -qemu_chr_add_handlers(s-chn[i].chr, serial_can_receive, - serial_receive1, serial_event, s-chn[i]); +qemu_chr_add_handlers(s-chn[i].chr, serial_handlers, s-chn[i]); } } s-chn[0].otherchn = s-chn[1]; diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c index e1f9615..e22f770 100644 --- a/hw/etraxfs_ser.c +++ b/hw/etraxfs_ser.c @@ -161,6 +161,12 @@ static void serial_event(void *opaque, int event) } +static QemuChrHandlers serial_handlers = { +.fd_can_read = serial_can_receive, +.fd_read = serial_receive, +.fd_event = serial_event, +}; + static int etraxfs_ser_init(SysBusDevice *dev) { struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev); @@ -174,10 +180,9 @@ static int etraxfs_ser_init(SysBusDevice *dev) ser_regs = cpu_register_io_memory(ser_read, ser_write, s); sysbus_init_mmio(dev, R_MAX * 4, ser_regs); s-chr = qdev_init_chardev(dev-qdev); -if (s-chr) -qemu_chr_add_handlers(s-chr, - serial_can_receive, serial_receive, - serial_event, s); +if (s-chr) { +qemu_chr_add_handlers(s-chr, serial_handlers, s); +} return 0; } diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c index d16bac7..301b901 100644 --- a/hw/mcf_uart.c +++ b/hw/mcf_uart.c @@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size) mcf_uart_push_byte(s, buf[0]); } +static QemuChrHandlers mcf_uart_handlers = { +.fd_can_read = mcf_uart_can_receive, +.fd_read = mcf_uart_receive, +.fd_event = mcf_uart_event, +}; + void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) { mcf_uart_state *s; @@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) s-chr = chr; s-irq = irq; if (chr) { -qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, - mcf_uart_event, s); +qemu_chr_add_handlers(chr, mcf_uart_handlers, s); } mcf_uart_reset(s); return s; diff --git a/hw/pl011.c b/hw/pl011.c index 81de91e..8e5356e 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -286,6 +286,12 @@ static int pl011_load(QEMUFile *f, void *opaque, int version_id) return 0; }
[Qemu-devel] [PATCH v5 6/6] virtio-console: Throttle virtio-serial-bus if we can't consume any more guest data
If the char device we're connected to is overwhelmed with data and it can't accept any more, signal to the virtio-serial-bus to stop sending us more data till we tell otherwise. If the current buffer being processed hasn't been completely written out to the char device, we have to keep it around and re-try sending it since the virtio-serial-bus code assumes we consume the entire buffer. Allow the chardev backends to return -EAGAIN; we're ready with a callback handler that will flush the remainder of the buffer. Also register with savevm so that we save/restore such a buffer across migration. Signed-off-by: Amit Shah amit.s...@redhat.com --- hw/virtio-console.c | 126 +- 1 files changed, 123 insertions(+), 3 deletions(-) diff --git a/hw/virtio-console.c b/hw/virtio-console.c index 749ed59..7eb6aa1 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -13,18 +13,92 @@ #include qemu-char.h #include virtio-serial.h +typedef struct Buffer { +uint8_t *buf; +size_t rem_len; +size_t offset; +} Buffer; + typedef struct VirtConsole { VirtIOSerialPort port; CharDriverState *chr; +Buffer *unflushed_buf; } VirtConsole; +static void add_unflushed_buf(VirtConsole *vcon, const uint8_t *buf, size_t len) +{ +vcon-unflushed_buf = qemu_malloc(sizeof(Buffer)); +vcon-unflushed_buf-buf = qemu_malloc(len); + +memcpy(vcon-unflushed_buf-buf, buf, len); +vcon-unflushed_buf-rem_len = len; +vcon-unflushed_buf-offset = 0; +} + +static void free_unflushed_buf(VirtConsole *vcon) +{ +if (vcon-unflushed_buf) { +qemu_free(vcon-unflushed_buf-buf); +qemu_free(vcon-unflushed_buf); +vcon-unflushed_buf = NULL; +} +} + +static int buffered_write_to_chardev(VirtConsole *vcon, const uint8_t *buf, + size_t len) +{ +size_t written; +ssize_t ret; + +written = 0; +do { +ret = qemu_chr_write_nb(vcon-chr, buf + written, len - written); +if (ret 0) { +if (vcon-unflushed_buf) { +vcon-unflushed_buf-offset += written; +vcon-unflushed_buf-rem_len -= written; +} else { +virtio_serial_throttle_port(vcon-port, true); +add_unflushed_buf(vcon, buf + written, len - written); +} + +return -EAGAIN; +} + +written += ret; +} while (written != len); + +return 0; +} + +/* Callback function called when the chardev can accept more data */ +static void chr_write_unblocked(void *opaque) +{ +VirtConsole *vcon = opaque; + +if (vcon-unflushed_buf) { +int ret; + +ret = buffered_write_to_chardev(vcon, vcon-unflushed_buf-buf + + vcon-unflushed_buf-offset, +vcon-unflushed_buf-rem_len); +if (ret 0) { +return; +} +free_unflushed_buf(vcon); +} +virtio_serial_throttle_port(vcon-port, false); +} /* Callback function that's called when the guest sends us data */ static void flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) { VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); -qemu_chr_write(vcon-chr, buf, len); +/* If a previous write was incomplete, we should've been throttled. */ +assert(!vcon-unflushed_buf); + +buffered_write_to_chardev(vcon, buf, len); } /* Readiness of the guest to accept data on a port */ @@ -48,19 +122,62 @@ static void chr_event(void *opaque, int event) VirtConsole *vcon = opaque; switch (event) { -case CHR_EVENT_OPENED: { +case CHR_EVENT_OPENED: virtio_serial_open(vcon-port); break; -} + case CHR_EVENT_CLOSED: +if (vcon-unflushed_buf) { +free_unflushed_buf(vcon); +} virtio_serial_close(vcon-port); break; } } +static void virtio_console_port_save(QEMUFile *f, void *opaque) +{ +VirtConsole *vcon = opaque; +uint32_t have_buffer; + +have_buffer = vcon-unflushed_buf ? true : false; + +qemu_put_be32s(f, have_buffer); +if (have_buffer) { +qemu_put_be64s(f, vcon-unflushed_buf-rem_len); +qemu_put_buffer(f, vcon-unflushed_buf-buf + + vcon-unflushed_buf-offset, +vcon-unflushed_buf-rem_len); +} +} + +static int virtio_console_port_load(QEMUFile *f, void *opaque, int version_id) +{ +VirtConsole *vcon = opaque; +uint32_t have_buffer; + +if (version_id 1) { +return -EINVAL; +} + +qemu_get_be32s(f, have_buffer); +if (have_buffer) { +vcon-unflushed_buf = qemu_mallocz(sizeof(Buffer)); + +qemu_get_be64s(f, vcon-unflushed_buf-rem_len); +vcon-unflushed_buf-buf = qemu_malloc(vcon-unflushed_buf-rem_len); +vcon-unflushed_buf-offset = 0; + +qemu_get_buffer(f,
[Qemu-devel] [PATCH] iov: Move from hw/ to topdir
The iov functions can be useful to other code as well. Signed-off-by: Amit Shah amit.s...@redhat.com CC: Christoph Hellwig h...@lst.de --- hw/iov.c = iov.c |0 hw/iov.h = iov.h |0 2 files changed, 0 insertions(+), 0 deletions(-) rename hw/iov.c = iov.c (100%) rename hw/iov.h = iov.h (100%) diff --git a/hw/iov.c b/iov.c similarity index 100% rename from hw/iov.c rename to iov.c diff --git a/hw/iov.h b/iov.h similarity index 100% rename from hw/iov.h rename to iov.h -- 1.6.2.5
[Qemu-devel] [PATCH 3/4] doc: Heading for monitor command cpu got lost, restore it
Broken in commit 2313086a. Signed-off-by: Markus Armbruster arm...@redhat.com --- qemu-monitor.hx |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/qemu-monitor.hx b/qemu-monitor.hx index bf47ae0..220ed9c 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -611,6 +611,8 @@ ETEXI }, STEXI +...@item cpu @var{index} +...@findex cpu Set the default CPU. ETEXI -- 1.6.6.1
[Qemu-devel] [PATCH 1/4] doc: Fix host forwarding monitor command documentation
Commit f3546deb replaced host_net_redir by hostfwd_add, hostfwd_remove, but neglected to update documentation. Signed-off-by: Markus Armbruster arm...@redhat.com --- qemu-monitor.hx | 13 ++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 5ea5748..21aeb6b 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -953,7 +953,14 @@ ETEXI .help = redirect TCP or UDP connections from host to guest (requires -net user), .mhandler.cmd = net_slirp_hostfwd_add, }, +#endif +STEXI +...@item hostfwd_add +...@findex hostfwd_add +Redirect TCP or UDP connections from host to guest (requires -net user). +ETEXI +#ifdef CONFIG_SLIRP { .name = hostfwd_remove, .args_type = arg1:s,arg2:s?,arg3:s?, @@ -964,9 +971,9 @@ ETEXI #endif STEXI -...@item host_net_redir -...@findex host_net_redir -Redirect TCP or UDP connections from host to guest (requires -net user). +...@item hostfwd_remove +...@findex hostfwd_remove +Remove host-to-guest TCP or UDP redirection. ETEXI { -- 1.6.6.1
[Qemu-devel] [PATCH 2/4] doc: Fix acl monitor command documentation
Commit 15dfcd45 added acl_add and acl_reset, but fat-fingered their documentation to read acl_allow and acl_remove. Signed-off-by: Markus Armbruster arm...@redhat.com --- qemu-monitor.hx |7 --- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 21aeb6b..bf47ae0 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -1063,8 +1063,8 @@ ETEXI }, STEXI -...@item acl_allow @var{aclname} @var{match} @code{allow|deny} [...@var{index}] -...@findex acl_allow +...@item acl_add @var{aclname} @var{match} @code{allow|deny} [...@var{index}] +...@findex acl_add Add a match rule to the access control list, allowing or denying access. The match will normally be an exact username or x509 distinguished name, but can optionally include wildcard globs. eg @code{*@@EXAMPLE.COM} to @@ -1096,7 +1096,8 @@ ETEXI }, STEXI -...@item acl_remove @var{aclname} +...@item acl_reset @var{aclname} +...@findex acl_reset Remove all matches from the access control list, and set the default policy back to @code{deny}. ETEXI -- 1.6.6.1
[Qemu-devel] [PATCH 0/4] doc: Monitor command documentation fixes
Markus Armbruster (4): doc: Fix host forwarding monitor command documentation doc: Fix acl monitor command documentation doc: Heading for monitor command cpu got lost, restore it doc: Clean up monitor command function index qemu-monitor.hx | 26 +- 1 files changed, 17 insertions(+), 9 deletions(-)
Re: [Qemu-devel] [PATCH 1/6] bochs: use pread
2010/5/4 Christoph Hellwig h...@lst.de: Use pread instead of lseek + read in preparation of using the qemu block API. IIRC there is no pread in MinGW.
[Qemu-devel] Re: [PATCH v5 3/6] char: Let writers know how much data was written in case of errors
@@ -531,8 +534,12 @@ static int unix_write(int fd, const uint8_t *buf, int len1) while (len 0) { ret = write(fd, buf, len); if (ret 0) { -if (errno != EINTR errno != EAGAIN) +if (len1 - len) { +return len1 - len; +} +if (errno != EINTR errno != EAGAIN) { return -1; +} This makes unix_write pass -EINTR up to the caller which it didn't before. cheers, Gerd
[Qemu-devel] [PATCH v5 0/4] Introduce bit-based phys_ram_dirty, and bit-based dirty page checker.
The dirty and non-dirty pages are checked one by one. When most of the memory is not dirty, checking the dirty and non-dirty pages by multiple page size should be much faster than checking them one by one. We introduced bit-based phys_ram_dirty for VGA, CODE, MIGRATION, MASTER, and cpu_physical_memory_get_dirty_range() for this purpose. The following numbers show the speed up of bit-based phys_ram_dirty. The speed up grows when the number of rows, whose contents are 0, gets larger. Test Environment: CPU: 4x Intel Xeon Quad Core 2.66GHz Mem size: 96GB Host OS: CentOS (kernel 2.6.33) Guest OS: Debian/GNU Linux lenny (kernel 2.6.26) Guest Mem size: 512MB Conditions of experiments are as follows: Cond1: Guest OS periodically makes the 256MB continuous dirty pages. Cond2: Guest OS periodically makes the 256MB dirty pages and non-dirty pages in turn. Cond3: Guest OS read 1GB file, which is bigger than memory. Cond4: Guest OS write 1GB file, which is bigger than memory. Experimental results: Cond1: 5 ??? 83 times speed up Cond2: 5 ??? 52 times speed up Cond3: 5 ??? 132 times speed up Cond4: 5 ??? 57 times speed up Changes from v4 to v5 are: - Rebased to HEAD (2b644fd0e737407133c88054ba498e772ce01f27) - Use BITMAP_SIZE() in kvm_physical_sync_dirty_bitmap() (3/4) Changes from v3 to v4 are: - Merged {1,2,3}/6 to compile correctly. - Fix setting bits after phys_ram_dirty allocation. - renamed DIRTY_FLAG and DIRTY_IDX converter function. Changes from v2 to v3 are: - Change FLAGS value to (1,2,4,8), and add IDX (0,1,2,3) - Use ffs to convert FLAGS to IDX. - Add a helper function which takes IDX. - Change the behavior of MASTER as a buffer. - Change dirty bitmap access to a loop. - Add brace after if () Yoshiaki Tamura (4): Modify DIRTY_FLAG value and introduce DIRTY_IDX to use as indexes of bit-based phys_ram_dirty. Introduce cpu_physical_memory_get_dirty_range(). Use cpu_physical_memory_set_dirty_range() to update phys_ram_dirty. Use cpu_physical_memory_get_dirty_range() to check multiple dirty pages. arch_init.c | 54 ++- cpu-all.h | 132 - exec.c| 82 +-- kvm-all.c | 24 -- qemu-common.h |3 + 5 files changed, 234 insertions(+), 61 deletions(-)
[Qemu-devel] Re: [PATCH v5 3/6] char: Let writers know how much data was written in case of errors
On (Tue) May 04 2010 [13:24:58], Gerd Hoffmann wrote: @@ -531,8 +534,12 @@ static int unix_write(int fd, const uint8_t *buf, int len1) while (len 0) { ret = write(fd, buf, len); if (ret 0) { -if (errno != EINTR errno != EAGAIN) +if (len1 - len) { +return len1 - len; +} +if (errno != EINTR errno != EAGAIN) { return -1; +} This makes unix_write pass -EINTR up to the caller which it didn't before. Only on partial writes. Should be OK, no? Amit
Re: [Qemu-devel] [PATCH 1/6] bochs: use pread
On Tue, May 04, 2010 at 07:20:22PM +0800, Roy Tam wrote: 2010/5/4 Christoph Hellwig h...@lst.de: Use pread instead of lseek + read in preparation of using the qemu block API. IIRC there is no pread in MinGW. It gets replaced in the next patch anyway.
Re: [Qemu-devel] Qemu-KVM 0.12.3 and Multipath - Assertion
hi kevin, i set a breakpint at bmdma_active_if. the first 2 breaks encountered when the last path in the multipath failed, but the assertion was not true. when i kicked one path back in the breakpoint was reached again, this time leading to an assert. the stacktrace is from the point shortly before. hope this helps. br, peter -- (gdb) b bmdma_active_if Breakpoint 2 at 0x43f2e0: file /usr/src/qemu-kvm-0.12.3/hw/ide/internal.h, line 507. (gdb) c Continuing. [Switching to Thread 0x7f7b3300d950 (LWP 21171)] Breakpoint 2, bmdma_active_if (bmdma=0xe31fd8) at /usr/src/qemu-kvm-0.12.3/hw/ide/internal.h:507 507assert(bmdma-unit != (uint8_t)-1); (gdb) c Continuing. Breakpoint 2, bmdma_active_if (bmdma=0xe31fd8) at /usr/src/qemu-kvm-0.12.3/hw/ide/internal.h:507 507assert(bmdma-unit != (uint8_t)-1); (gdb) c Continuing. Breakpoint 2, bmdma_active_if (bmdma=0xe31fd8) at /usr/src/qemu-kvm-0.12.3/hw/ide/internal.h:507 507assert(bmdma-unit != (uint8_t)-1); (gdb) bt full #0 bmdma_active_if (bmdma=0xe31fd8) at /usr/src/qemu-kvm-0.12.3/hw/ide/internal.h:507 __PRETTY_FUNCTION__ = bmdma_active_if #1 0x0043f6ba in ide_read_dma_cb (opaque=0xe31fd8, ret=0) at /usr/src/qemu-kvm-0.12.3/hw/ide/core.c:554 bm = (BMDMAState *) 0xe31fd8 s = (IDEState *) 0xe17940 n = 0 sector_num = 0 #2 0x0058730c in dma_bdrv_cb (opaque=0xe17940, ret=0) at /usr/src/qemu-kvm-0.12.3/dma-helpers.c:94 dbs = (DMAAIOCB *) 0xe17940 cur_addr = 0 cur_len = 0 mem = (void *) 0x0 #3 0x0049e510 in qemu_laio_process_completion (s=0xe119c0, laiocb=0xe179c0) at linux-aio.c:68 ret = 0 #4 0x0049e611 in qemu_laio_enqueue_completed (s=0xe119c0, laiocb=0xe179c0) at linux-aio.c:107 No locals. #5 0x0049e787 in qemu_laio_completion_cb (opaque=0xe119c0) at linux-aio.c:144 iocb = (struct iocb *) 0xe179f0 laiocb = (struct qemu_laiocb *) 0xe179c0 val = 1 ret = 8 nevents = 1 i = 0 events = {{data = 0x0, obj = 0xe179f0, res = 4096, res2 = 0}, {data = 0x0, obj = 0x0, res = 0, res2 = 0} repeats 46 times, {data = 0x0, obj = 0x0, res = 0, res2 = 4365191}, {data = 0x429abf, obj = 0x7f7b3300c410, res = 4614129721674825936, res2 = 14777248}, {data = 0x300018, obj = 0x7f7b3300c4c0, res = 140167113393152, res2 = 47259417504}, {data = 0xe17740, obj = 0xa3300c4e0, res = 140167113393184, res2 = 0}, {data = 0xe17740, obj = 0x0, res = 0, res2 = 17}, {data = 0x7f7b3300ccf0, obj = 0x92, res = 32, res2 = 168}, {data = 0x7f7b33797a00, obj = 0x801000, res = 0, res2 = 140167141433408}, {data = 0x7f7b34496e00, obj = 0x7f7b33797a00, res = 140167113393392, res2 = 8392704}, {data = 0x0, obj = 0x7f7b34aca040, res = 140167134932480, res2 = 140167118209654}, {data = 0x7f7b3300d950, obj = 0x42603d, res = 0, res2 = 42949672960}, {data = 0x7f7b3300c510, obj = 0xe17ba0, res = 14776128, res2 = 43805361568}, {data = 0x7f7b3300ced0, obj = 0x42797e, res = 0, res2 = 14777248}, { data = 0x174, obj = 0x0, res = 373, res2 = 0}, {data = 0x176, obj = 0x0, res = 3221225601, res2 = 0}, {data = 0x4008ae89c083, obj = 0x0, res = 209379655938, res2 = 0}, { data = 0x7f7bc084, obj = 0x0, res = 3221225602, res2 = 0}, {data = 0x7f7b0012, obj = 0x0, res = 17, res2 = 0}, {data = 0x0, obj = 0x11, res = 140167113395840, res2 = 146}, {data = 0x20, obj = 0xa8, res = 140167121304064, res2 = 8392704}, {data = 0x0, obj = 0x7f7b34aca040, res = 140167134932480, res2 = 140167121304064}, { data = 0x7f7b3300c680, obj = 0x801000, res = 0, res2 = 140167141433408}, {data = 0x7f7b34496e00, obj = 0x7f7b334a4276, res = 140167113398608, res2 = 4350013}, {data = 0x0, obj = 0xa, res = 140167113393824, res2 = 14777248}, {data = 0xe2c010, obj = 0xa3300c730, res = 140167113396320, res2 = 4356478}, {data = 0x0, obj = 0xe17ba0, res = 372, res2 = 0}, {data = 0x175, obj = 0x0, res = 374, res2 = 0}, {data = 0xc081, obj = 0x0, res = 3221225603, res2 = 0}, {data = 0xc102, obj = 0x0, res = 3221225604, res2 = 0}, {data = 0xc082, obj = 0x0, res = 18, res2 = 0}, {data = 0x11, obj = 0x0, res = 0, res2 = 0}, {data = 0x0, obj = 0x0, res = 0, res2 = 0}, { data = 0x0, obj = 0x0, res = 0, res2 = 0}, {data = 0x0, obj = 0x0, res = 0, res2 = 0}, {data = 0x0, obj = 0x0, res = 0, res2 = 0}, {data = 0x0, obj = 0x0, res = 0, res2 = 140167139245116}, {data = 0x0, obj = 0x7f7b34abe118, res = 9, res2 = 13}, {data = 0x25bf5fc6, obj = 0x7f7b348b40f0, res = 140167117719264, res2 = 6}, { data = 0x96fd7f, obj = 0x7f7b3300c850, res = 140167113394680, res2 = 140167117724520}, {data = 0x0, obj = 0x7f7b34abe168, res = 140167141388288, res2 = 4206037}, { data = 0x7f7b3343a210, obj = 0x402058, res = 21474836480, res2 = 4294968102}, {data = 0x0, obj = 0x7f7b34ac8358, res = 140167113394736, res2 = 140167113394680}, { data = 0x25bf5fc6, obj = 0x7f7b3300c9e0, res = 0, res2 = 140167139246910}, {data = 0x0, obj = 0x7f7b34abe168, res
[Qemu-devel] [PATCH] vnc: set the right prefered encoding
From RFB specs: The order of the encoding types given in this message is a hint by the client as to its preference (the first encoding specified being most preferred) Signed-off-by: Corentin Chary corenti...@iksaif.net --- vnc.c | 14 ++ 1 files changed, 10 insertions(+), 4 deletions(-) diff --git a/vnc.c b/vnc.c index 5241a6a..2d05d8f 100644 --- a/vnc.c +++ b/vnc.c @@ -1594,7 +1594,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) vnc_zlib_init(vs); vs-features = 0; -vs-vnc_encoding = 0; +vs-vnc_encoding = -1; vs-tight_compression = 9; vs-tight_quality = 9; vs-absolute = -1; @@ -1603,18 +1603,24 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) enc = encodings[i]; switch (enc) { case VNC_ENCODING_RAW: -vs-vnc_encoding = enc; +if (vs-vnc_encoding != -1) { +vs-vnc_encoding = enc; +} break; case VNC_ENCODING_COPYRECT: vs-features |= VNC_FEATURE_COPYRECT_MASK; break; case VNC_ENCODING_HEXTILE: vs-features |= VNC_FEATURE_HEXTILE_MASK; -vs-vnc_encoding = enc; +if (vs-vnc_encoding != -1) { +vs-vnc_encoding = enc; +} break; case VNC_ENCODING_ZLIB: vs-features |= VNC_FEATURE_ZLIB_MASK; -vs-vnc_encoding = enc; +if (vs-vnc_encoding != -1) { +vs-vnc_encoding = enc; +} break; case VNC_ENCODING_DESKTOPRESIZE: vs-features |= VNC_FEATURE_RESIZE_MASK; -- 1.7.0.2
[Qemu-devel] Re: [PATCH v4 3/5] char: unix/tcp: Add a non-blocking write handler
On (Tue) May 04 2010 [09:43:04], Gerd Hoffmann wrote: On 05/04/10 09:17, Amit Shah wrote: Add a non-blocking write handler that can return with -EAGAIN to the caller and also callback when the socket becomes writable. Non-blocking writes are only enabled for sockets that are opened in non-blocking mode and only for callers that have registered a callback handler for resuming writes. The logic will be pretty much the same for all filehandle-based backends on unix. So maybe create some helper functions, so implementing $backend_chr_write_unblocked can be done with just three lines of code? Yes, that's the next step. Let's push this for now and do that in a later patch series? Amit
[Qemu-devel] [PATCH 4/5] lsi: Adjust some register reset values
According to the LSI spec, the reset value of dcmd, dstat, and ctest2 were wrong, and sdid as well as ssid require zero initialization. There are surely more discrepancies, this is just another increment. Signed-off-by: Jan Kiszka jan.kis...@siemens.com --- hw/lsi53c895a.c |8 +--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 61de23e..f088d06 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -298,8 +298,8 @@ static void lsi_soft_reset(LSIState *s) memset(s-scratch, 0, sizeof(s-scratch)); s-istat0 = 0; s-istat1 = 0; -s-dcmd = 0; -s-dstat = 0; +s-dcmd = 0x40; +s-dstat = LSI_DSTAT_DFE; s-dien = 0; s-sist0 = 0; s-sist1 = 0; @@ -308,7 +308,7 @@ static void lsi_soft_reset(LSIState *s) s-mbox0 = 0; s-mbox1 = 0; s-dfifo = 0; -s-ctest2 = 0; +s-ctest2 = LSI_CTEST2_DACK; s-ctest3 = 0; s-ctest4 = 0; s-ctest5 = 0; @@ -327,6 +327,8 @@ static void lsi_soft_reset(LSIState *s) s-scid = 7; s-sxfer = 0; s-socl = 0; +s-sdid = 0; +s-ssid = 0; s-stest1 = 0; s-stest2 = 0; s-stest3 = 0; -- 1.6.0.2
[Qemu-devel] [PATCH 0/5] scsi: More reset and hotplug fixes
This series finally stabilizes system reset during ongoing SCSI I/O here. The first patch is a repost, the others include missing reset related bits that mostly concern the LSI controller. And the last patch addresses a disk hotplugging issue: The LSI used to keep pointers to the selected device, pointer that can become invalid it the device is removed in the middle of ongoing I/O. Jan Kiszka (5): SCSI: Add disk reset handler scsi-disk: Clear aiocb on read completion lsi: Purge message queue on reset lsi: Adjust some register reset values lsi: Handle removal of selected devices hw/lsi53c895a.c | 70 +++--- hw/scsi-disk.c | 37 ++-- 2 files changed, 74 insertions(+), 33 deletions(-)
[Qemu-devel] [PATCH 5/5] lsi: Handle removal of selected devices
We must not store references to selected devices as they may be hot-removed. Instead, look up the device based on its tag right before using it. If the device disappeared, throw an interrupt and disconnect. Signed-off-by: Jan Kiszka jan.kis...@siemens.com --- hw/lsi53c895a.c | 60 ++ 1 files changed, 38 insertions(+), 22 deletions(-) diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index f088d06..9d3c44d 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -175,7 +175,6 @@ do { fprintf(stderr, lsi_scsi: error: fmt , ## __VA_ARGS__);} while (0) typedef struct lsi_request { uint32_t tag; -SCSIDevice *dev; uint32_t dma_len; uint8_t *dma_buf; uint32_t pending; @@ -202,7 +201,6 @@ typedef struct { * 3 if a DMA operation is in progress. */ int waiting; SCSIBus bus; -SCSIDevice *select_dev; int current_lun; /* The tag is a combination of the device ID and the SCSI tag. */ uint32_t select_tag; @@ -518,11 +516,25 @@ static void lsi_resume_script(LSIState *s) } } +static void lsi_disconnect(LSIState *s) +{ +s-scntl1 = ~LSI_SCNTL1_CON; +s-sstat1 = ~PHASE_MASK; +} + +static void lsi_bad_selection(LSIState *s, uint32_t id) +{ +DPRINTF(Selected absent target %d\n, id); +lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO); +lsi_disconnect(s); +} + /* Initiate a SCSI layer data transfer. */ static void lsi_do_dma(LSIState *s, int out) { -uint32_t count; +uint32_t count, id; target_phys_addr_t addr; +SCSIDevice *dev; assert(s-current); if (!s-current-dma_len) { @@ -531,6 +543,13 @@ static void lsi_do_dma(LSIState *s, int out) return; } +id = s-current-tag 8; +dev = s-bus.devs[id]; +if (!dev) { +lsi_bad_selection(s, id); +return; +} + count = s-dbc; if (count s-current-dma_len) count = s-current-dma_len; @@ -550,8 +569,7 @@ static void lsi_do_dma(LSIState *s, int out) s-dbc -= count; if (s-current-dma_buf == NULL) { -s-current-dma_buf = s-current-dev-info-get_buf(s-current-dev, - s-current-tag); +s-current-dma_buf = dev-info-get_buf(dev, s-current-tag); } /* ??? Set SFBR to first data byte. */ @@ -565,10 +583,10 @@ static void lsi_do_dma(LSIState *s, int out) s-current-dma_buf = NULL; if (out) { /* Write the data. */ -s-current-dev-info-write_data(s-current-dev, s-current-tag); +dev-info-write_data(dev, s-current-tag); } else { /* Request any remaining data. */ -s-current-dev-info-read_data(s-current-dev, s-current-tag); +dev-info-read_data(dev, s-current-tag); } } else { s-current-dma_buf += count; @@ -715,7 +733,9 @@ static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag, static void lsi_do_command(LSIState *s) { +SCSIDevice *dev; uint8_t buf[16]; +uint32_t id; int n; DPRINTF(Send command len=%d\n, s-dbc); @@ -725,19 +745,24 @@ static void lsi_do_command(LSIState *s) s-sfbr = buf[0]; s-command_complete = 0; +id = s-select_tag 8; +dev = s-bus.devs[id]; +if (!dev) { +lsi_bad_selection(s, id); +return; +} + assert(s-current == NULL); s-current = qemu_mallocz(sizeof(lsi_request)); s-current-tag = s-select_tag; -s-current-dev = s-select_dev; -n = s-current-dev-info-send_command(s-current-dev, s-current-tag, buf, -s-current_lun); +n = dev-info-send_command(dev, s-current-tag, buf, s-current_lun); if (n 0) { lsi_set_phase(s, PHASE_DI); -s-current-dev-info-read_data(s-current-dev, s-current-tag); +dev-info-read_data(dev, s-current-tag); } else if (n 0) { lsi_set_phase(s, PHASE_DO); -s-current-dev-info-write_data(s-current-dev, s-current-tag); +dev-info-write_data(dev, s-current-tag); } if (!s-command_complete) { @@ -771,12 +796,6 @@ static void lsi_do_status(LSIState *s) lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */ } -static void lsi_disconnect(LSIState *s) -{ -s-scntl1 = ~LSI_SCNTL1_CON; -s-sstat1 = ~PHASE_MASK; -} - static void lsi_do_msgin(LSIState *s) { int len; @@ -1092,9 +,7 @@ again: s-sstat0 |= LSI_SSTAT0_WOA; s-scntl1 = ~LSI_SCNTL1_IARB; if (id = LSI_MAX_DEVS || !s-bus.devs[id]) { -DPRINTF(Selected absent target %d\n, id); -lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO); -lsi_disconnect(s); +lsi_bad_selection(s, id); break; } DPRINTF(Selected target %d%s\n, @@ -1102,7 +1119,6 @@ again: /*
[Qemu-devel] [PATCH 3/5] lsi: Purge message queue on reset
Declare the input message queue empty and initialize the related state machine properly on controller reset. This fixes unrecoverable errors when the controller was reset during ongoing requests. Signed-off-by: Jan Kiszka jan.kis...@siemens.com --- hw/lsi53c895a.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 85eea15..61de23e 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -288,6 +288,8 @@ static void lsi_soft_reset(LSIState *s) DPRINTF(Reset\n); s-carry = 0; +s-msg_action = 0; +s-msg_len = 0; s-waiting = 0; s-dsa = 0; s-dnad = 0; -- 1.6.0.2
[Qemu-devel] [PATCH 1/5] SCSI: Add disk reset handler
Ensure that pending requests of an SCSI disk are purged on system reset and also restore max_lba. The latter is no only present in the reset handler as that one is called after init as well. Signed-off-by: Jan Kiszka jan.kis...@siemens.com --- hw/scsi-disk.c | 35 +++ 1 files changed, 27 insertions(+), 8 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 77cb1da..b8d805f 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1010,22 +1010,45 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, } } -static void scsi_destroy(SCSIDevice *dev) +static void scsi_disk_purge_requests(SCSIDiskState *s) { -SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); SCSIDiskReq *r; while (!QTAILQ_EMPTY(s-qdev.requests)) { r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(s-qdev.requests)); +if (r-req.aiocb) { +bdrv_aio_cancel(r-req.aiocb); +} scsi_remove_request(r); } +} + +static void scsi_disk_reset(DeviceState *dev) +{ +SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev); +uint64_t nb_sectors; + +scsi_disk_purge_requests(s); + +bdrv_get_geometry(s-bs, nb_sectors); +nb_sectors /= s-cluster_size; +if (nb_sectors) { +nb_sectors--; +} +s-max_lba = nb_sectors; +} + +static void scsi_destroy(SCSIDevice *dev) +{ +SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + +scsi_disk_purge_requests(s); drive_uninit(s-qdev.conf.dinfo); } static int scsi_disk_initfn(SCSIDevice *dev) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); -uint64_t nb_sectors; if (!s-qdev.conf.dinfo || !s-qdev.conf.dinfo-bdrv) { error_report(scsi-disk: drive property not set); @@ -1046,11 +1069,6 @@ static int scsi_disk_initfn(SCSIDevice *dev) s-cluster_size = s-qdev.blocksize / 512; s-qdev.type = TYPE_DISK; -bdrv_get_geometry(s-bs, nb_sectors); -nb_sectors /= s-cluster_size; -if (nb_sectors) -nb_sectors--; -s-max_lba = nb_sectors; qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s); return 0; } @@ -1059,6 +1077,7 @@ static SCSIDeviceInfo scsi_disk_info = { .qdev.name= scsi-disk, .qdev.desc= virtual scsi disk or cdrom, .qdev.size= sizeof(SCSIDiskState), +.qdev.reset = scsi_disk_reset, .init = scsi_disk_initfn, .destroy = scsi_destroy, .send_command = scsi_send_command, -- 1.6.0.2
[Qemu-devel] [PATCH 2/5] scsi-disk: Clear aiocb on read completion
Once the I/O completion callback returned, aiocb will be released by the controller. So we have to clear the reference not only in scsi_write_complete, but also in scsi_read_complete. Otherwise we risk inconsistencies when a reset hits us before the related request is released. Signed-off-by: Jan Kiszka jan.kis...@siemens.com --- hw/scsi-disk.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index b8d805f..4d20919 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -125,6 +125,8 @@ static void scsi_read_complete(void * opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; +r-req.aiocb = NULL; + if (ret) { DPRINTF(IO error\n); r-req.bus-complete(r-req.bus, SCSI_REASON_DATA, r-req.tag, 0); -- 1.6.0.2
Re: [Qemu-devel] Qemu-KVM 0.12.3 and Multipath - Assertion
Am 04.05.2010 13:38, schrieb Peter Lieven: hi kevin, i set a breakpint at bmdma_active_if. the first 2 breaks encountered when the last path in the multipath failed, but the assertion was not true. when i kicked one path back in the breakpoint was reached again, this time leading to an assert. the stacktrace is from the point shortly before. hope this helps. Hm, looks like there's something wrong with cancelling requests - bdrv_aio_cancel might decide that it completes a request (and consequently calls the callback for it) whereas the IDE emulation decides that it's done with the request before calling bdrv_aio_cancel. I haven't looked in much detail what this could break, but does something like this help? diff --git a/hw/ide/core.c b/hw/ide/core.c index 0757528..3cd55e3 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2838,10 +2838,6 @@ static void ide_dma_restart(IDEState *s, int is_read) void ide_dma_cancel(BMDMAState *bm) { if (bm-status BM_STATUS_DMAING) { -bm-status = ~BM_STATUS_DMAING; -/* cancel DMA request */ -bm-unit = -1; -bm-dma_cb = NULL; if (bm-aiocb) { #ifdef DEBUG_AIO printf(aio_cancel\n); @@ -2849,6 +2845,10 @@ void ide_dma_cancel(BMDMAState *bm) bdrv_aio_cancel(bm-aiocb); bm-aiocb = NULL; } +bm-status = ~BM_STATUS_DMAING; +/* cancel DMA request */ +bm-unit = -1; +bm-dma_cb = NULL; } } Kevin
Re: [Qemu-devel] simple block driver cleanups
Am 04.05.2010 12:43, schrieb Christoph Hellwig: This series cleans up the simple read-only block drivers to use the qemu block device API to access their backing devices, making the code simpler and usable over nbd/curl. I've not touched dmg yet as it's even more bitrot than usual and deserves it's own series. Have you already added something to qemu-iotests locally to test this or did you test manually? Kevin
[Qemu-devel] [patch uq/master 5/9] kvm: synchronize state from cpu context
From: Jan Kiszka jan.kis...@siemens.com It is not safe to retrieve the KVM internal state of a given cpu while its potentially modifying it. Queue the request to run on cpu context, similarly to qemu-kvm. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/kvm-all.c === --- qemu.orig/kvm-all.c +++ qemu/kvm-all.c @@ -796,14 +796,22 @@ void kvm_flush_coalesced_mmio_buffer(voi #endif } -void kvm_cpu_synchronize_state(CPUState *env) +static void do_kvm_cpu_synchronize_state(void *_env) { +CPUState *env = _env; + if (!env-kvm_vcpu_dirty) { kvm_arch_get_registers(env); env-kvm_vcpu_dirty = 1; } } +void kvm_cpu_synchronize_state(CPUState *env) +{ +if (!env-kvm_vcpu_dirty) +run_on_cpu(env, do_kvm_cpu_synchronize_state, env); +} + void kvm_cpu_synchronize_post_reset(CPUState *env) { kvm_arch_put_registers(env, KVM_PUT_RESET_STATE);
[Qemu-devel] [patch uq/master 4/9] port qemu-kvm's on_vcpu code
run_on_cpu allows to execute work on a given CPUState context. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/cpu-all.h === --- qemu.orig/cpu-all.h +++ qemu/cpu-all.h @@ -818,6 +818,7 @@ void cpu_watchpoint_remove_all(CPUState void cpu_single_step(CPUState *env, int enabled); void cpu_reset(CPUState *s); +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data); #define CPU_LOG_TB_OUT_ASM (1 0) #define CPU_LOG_TB_IN_ASM (1 1) Index: qemu/cpu-defs.h === --- qemu.orig/cpu-defs.h +++ qemu/cpu-defs.h @@ -132,6 +132,7 @@ typedef struct icount_decr_u16 { struct kvm_run; struct KVMState; +struct qemu_work_item; typedef struct CPUBreakpoint { target_ulong pc; @@ -204,6 +205,7 @@ typedef struct CPUWatchpoint { uint32_t created; \ struct QemuThread *thread; \ struct QemuCond *halt_cond; \ +struct qemu_work_item *queued_work_first, *queued_work_last;\ const char *cpu_model_str; \ struct KVMState *kvm_state; \ struct kvm_run *kvm_run;\ Index: qemu/cpus.c === --- qemu.orig/cpus.c +++ qemu/cpus.c @@ -115,6 +115,8 @@ static int cpu_has_work(CPUState *env) { if (env-stop) return 1; +if (env-queued_work_first) +return 1; if (env-stopped || !vm_running) return 0; if (!env-halted) @@ -252,6 +254,11 @@ int qemu_cpu_self(void *env) return 1; } +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) +{ +func(data); +} + void resume_all_vcpus(void) { } @@ -304,6 +311,7 @@ static QemuCond qemu_cpu_cond; /* system init */ static QemuCond qemu_system_cond; static QemuCond qemu_pause_cond; +static QemuCond qemu_work_cond; static void tcg_block_io_signals(void); static void kvm_block_io_signals(CPUState *env); @@ -334,6 +342,50 @@ void qemu_main_loop_start(void) qemu_cond_broadcast(qemu_system_cond); } +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) +{ +struct qemu_work_item wi; + +if (qemu_cpu_self(env)) { +func(data); +return; +} + +wi.func = func; +wi.data = data; +if (!env-queued_work_first) +env-queued_work_first = wi; +else +env-queued_work_last-next = wi; +env-queued_work_last = wi; +wi.next = NULL; +wi.done = false; + +qemu_cpu_kick(env); +while (!wi.done) { +CPUState *self_env = cpu_single_env; + +qemu_cond_wait(qemu_work_cond, qemu_global_mutex); +cpu_single_env = self_env; +} +} + +static void flush_queued_work(CPUState *env) +{ +struct qemu_work_item *wi; + +if (!env-queued_work_first) +return; + +while ((wi = env-queued_work_first)) { +env-queued_work_first = wi-next; +wi-func(wi-data); +wi-done = true; +} +env-queued_work_last = NULL; +qemu_cond_broadcast(qemu_work_cond); +} + static void qemu_wait_io_event_common(CPUState *env) { if (env-stop) { @@ -341,6 +393,7 @@ static void qemu_wait_io_event_common(CP env-stopped = 1; qemu_cond_signal(qemu_pause_cond); } +flush_queued_work(env); } static void qemu_wait_io_event(CPUState *env) Index: qemu/qemu-common.h === --- qemu.orig/qemu-common.h +++ qemu/qemu-common.h @@ -249,6 +249,14 @@ void qemu_notify_event(void); void qemu_cpu_kick(void *env); int qemu_cpu_self(void *env); +/* work queue */ +struct qemu_work_item { +struct qemu_work_item *next; +void (*func)(void *data); +void *data; +int done; +}; + #ifdef CONFIG_USER_ONLY #define qemu_init_vcpu(env) do { } while (0) #else
[Qemu-devel] [patch uq/master 7/9] move stop/stopped CPU_COMMON fields after area zeroed by reset
cpu_reset zeroes CPUState upto breakpoints member. Contents of stop/stopped should not be zeroed on cpu_reset. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/cpu-defs.h === --- qemu.orig/cpu-defs.h +++ qemu/cpu-defs.h @@ -159,8 +159,6 @@ typedef struct CPUWatchpoint { target_ulong mem_io_vaddr; /* target virtual addr at which the \ memory was accessed */ \ uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ -uint32_t stop; /* Stop request */ \ -uint32_t stopped; /* Artificially stopped */\ uint32_t interrupt_request; \ volatile sig_atomic_t exit_request; \ CPU_COMMON_TLB \ @@ -203,6 +201,8 @@ typedef struct CPUWatchpoint { void *opaque; \ \ uint32_t created; \ +uint32_t stop; /* Stop request */ \ +uint32_t stopped; /* Artificially stopped */\ struct QemuThread *thread; \ struct QemuCond *halt_cond; \ struct qemu_work_item *queued_work_first, *queued_work_last;\
[Qemu-devel] [patch uq/master 6/9] add cpu_is_stopped helper
Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/cpu-all.h === --- qemu.orig/cpu-all.h +++ qemu/cpu-all.h @@ -818,6 +818,7 @@ void cpu_watchpoint_remove_all(CPUState void cpu_single_step(CPUState *env, int enabled); void cpu_reset(CPUState *s); +int cpu_is_stopped(CPUState *env); void run_on_cpu(CPUState *env, void (*func)(void *data), void *data); #define CPU_LOG_TB_OUT_ASM (1 0) Index: qemu/cpus.c === --- qemu.orig/cpus.c +++ qemu/cpus.c @@ -91,6 +91,11 @@ void cpu_synchronize_all_post_init(void) } } +int cpu_is_stopped(CPUState *env) +{ +return !vm_running || env-stopped; +} + static void do_vm_stop(int reason) { if (vm_running) {
[Qemu-devel] [patch uq/master 9/9] kvm: enable smp 1
Process INIT/SIPI requests and enable -smp 1. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/kvm-all.c === --- qemu.orig/kvm-all.c +++ qemu/kvm-all.c @@ -593,11 +593,6 @@ int kvm_init(int smp_cpus) int ret; int i; -if (smp_cpus 1) { -fprintf(stderr, No SMP KVM support, use '-smp 1'\n); -return -EINVAL; -} - s = qemu_mallocz(sizeof(KVMState)); #ifdef KVM_CAP_SET_GUEST_DEBUG @@ -840,6 +835,11 @@ int kvm_cpu_exec(CPUState *env) } #endif +if (kvm_arch_process_irqchip_events(env)) { +ret = 0; +break; +} + if (env-kvm_vcpu_dirty) { kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE); env-kvm_vcpu_dirty = 0; Index: qemu/kvm.h === --- qemu.orig/kvm.h +++ qemu/kvm.h @@ -90,6 +90,8 @@ int kvm_arch_handle_exit(CPUState *env, int kvm_arch_pre_run(CPUState *env, struct kvm_run *run); +int kvm_arch_process_irqchip_events(CPUState *env); + int kvm_arch_get_registers(CPUState *env); /* state subset only touched by the VCPU itself during runtime */ Index: qemu/target-i386/kvm.c === --- qemu.orig/target-i386/kvm.c +++ qemu/target-i386/kvm.c @@ -1073,6 +1073,22 @@ int kvm_arch_post_run(CPUState *env, str return 0; } +int kvm_arch_process_irqchip_events(CPUState *env) +{ +if (env-interrupt_request CPU_INTERRUPT_INIT) { +kvm_cpu_synchronize_state(env); +do_cpu_init(env); +env-exception_index = EXCP_HALTED; +} + +if (env-interrupt_request CPU_INTERRUPT_SIPI) { +kvm_cpu_synchronize_state(env); +do_cpu_sipi(env); +} + +return env-halted; +} + static int kvm_handle_halt(CPUState *env) { if (!((env-interrupt_request CPU_INTERRUPT_HARD) Index: qemu/target-ppc/kvm.c === --- qemu.orig/target-ppc/kvm.c +++ qemu/target-ppc/kvm.c @@ -224,6 +224,11 @@ int kvm_arch_post_run(CPUState *env, str return 0; } +int kvm_arch_process_irqchip_events(CPUState *env) +{ +return 0; +} + static int kvmppc_handle_halt(CPUState *env) { if (!(env-interrupt_request CPU_INTERRUPT_HARD) (msr_ee)) { Index: qemu/target-s390x/kvm.c === --- qemu.orig/target-s390x/kvm.c +++ qemu/target-s390x/kvm.c @@ -175,6 +175,11 @@ int kvm_arch_post_run(CPUState *env, str return 0; } +int kvm_arch_process_irqchip_events(CPUState *env) +{ +return 0; +} + static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm, uint64_t parm64, int vm) {
[Qemu-devel] Re: qemu-user[armel/mips] and debian-rootfs
On Mon, 2010-05-03 at 21:30 +0200, Kenneth Johansson wrote: I'm trying to setup a debian root that I can chroot into for armel and mips from an ubuntu 9.10 x86_64. While I have it working for armel on a specific qemu the mips target is more problematic. first both fail for qemu newer than 6173d56bdcb53389c54e803873e6bf8f87836a4f. doing /sbin/ldconfig. I get bad address now on to mips. during installation of debian I get the following error, /bin/tar: ./postinst: Cannot utime: Level 2 not synchronized after discovering QEMU_STRACE. not sure why tar thinks it got EL2NSYNC in errno. 15978 execve(/bin/tar,{tar,xf,-,NULL})15977 fcntl64(0,0x300,0x0001) = 0 15976 exit_group(0) 15977 fstat64(0,0x4007e0e8) = 0 15977 mmap(NULL,256,0x300,0x208,-1,0) = 0x4225d000 15977 _llseek(0,0,0,1074258344,1,0) = -1 errno=29 (Illegal seek) 15977 read(0,0x43e570,16384) = 1959 15977 read(0,0x43ed17,12288) = 0 15977 _llseek(0,0,0,1074258408,1,0) = -1 errno=29 (Illegal seek) 15978 brk(NULL) = 0x0047a000 15978 uname(0x4007f240) = 0 15978 access(/etc/ld.so.nohwcap,F_OK) = -1 errno=2 (No such file or directory) 15978 mmap(NULL,1048576,0x300,0x208,-1,0) = 0x42081000 15978 access(/etc/ld.so.preload,0x400) = -1 errno=2 (No such file or directory) 15977 write(1,0x4007e43c,4096) = 4096 15977 write(1,0x4007e43c,4096) = 4096 15978 open(/etc/ld.so.cache,O_RDONLY) = 4 15978 fstat64(67108864,0x4007ee28) = 0 15978 mmap(NULL,-1358102528,0x100,0x200,67108864,0)15977 = 0x42082000 read(0,0x43e570,16384) = 0 15978 close(4) = 0 15977 write(1,0x4007e43c,2048) = 2048 15977 close(1) = 0 15978 access(/etc/ld.so.nohwcap,F_OK) = -1 errno=2 (No such file or directory) 15978 open(/lib/librt.so.1,O_RDONLY) = 4 15978 read(4,0x4007ef78,512) = 512 15978 lseek(4,744,0,1074262308,0,0) = 744 15978 read(4,0x4007eed0,32) = 32 15978 fstat64(67108864,0x4007ee40) = 0 15977 exit_group(0) 15978 mmap(NULL,-1602092800,0x500,0x220,67108864,0) = 0x42083000 15978 mprotect(0x4208b000,15728640,PROT_NONE) = 0 15978 mmap(0x4209a000,2097152,0x300,0x1220,67108864,0x70) = 0x4209a000 15978 close(4) = 0 15978 access(/etc/ld.so.nohwcap,F_OK) = -1 errno=2 (No such file or directory) 15978 open(/lib/libc.so.6,O_RDONLY) = 4 15978 read(4,0x4007ef60,512) = 512 15978 lseek(4,760,0,1074262316,0,0) = 760 15978 read(4,0x4007eeb8,32) = 32 15978 fstat64(67108864,0x4007ee28) = 0 15978 mmap(NULL,1048576,0x300,0x208,-1,0) = 0x4209c000 15978 mmap(NULL,1089345280,0x500,0x220,67108864,0) = 0x4209d000 15978 mprotect(0x421ff000,15728640,PROT_NONE) = 0 15978 mmap(0x4220e000,11534336,0x300,0x1220,67108864,0x101600) = 0x4220e000 15978 mmap(0x42219000,1076756480,0x300,0x1208,-1,0) = 0x42219000 15978 close(4) = 0 15978 access(/etc/ld.so.nohwcap,F_OK) = -1 errno=2 (No such file or directory) 15978 open(/lib/libpthread.so.0,O_RDONLY) = 4 15978 read(4,0x4007eeb0,512) = 512 15978 lseek(4,744,0,1074262108,0,0) = 744 15978 read(4,0x4007ee08,32) = 32 15978 fstat64(67108864,0x4007ed78) = 0 15978 mmap(NULL,-1599929856,0x500,0x220,67108864,0) = 0x4221c000 15978 mprotect(0x42233000,256,PROT_NONE) = 0 15978 mmap(0x42243000,2097152,0x300,0x1220,67108864,0x700100) = 0x42243000 15978 mmap(0x42245000,-1609367552,0x300,0x1208,-1,0) = 0x42245000 15978 close(4) = 0 15978 mmap(NULL,1048576,0x300,0x208,-1,0) = 0x42247000 15978 set_thread_area(1109714064,1109685392,65536,1109685392,0,0) = 0 15978 open(/dev/urandom,O_RDONLY) = 4 15978 read(4,0x4007f3e1,3) = 3 15978 close(4) = 0 15978 mprotect(0x42243000,1048576,0x100) = 0 15978 mprotect(0x4220e000,9437184,0x100) = 0 15978 mprotect(0x4209a000,1048576,0x100) = 0 15978 mprotect(0x400b2000,1048576,0x100) = 0 15978 munmap(0x42082000,-1358102528) = 0 15978 set_tid_address(1109684328,1109714064,1074264284,1074264284,0,0) = 15978 15978 set_robust_list(1109684336,12,1074264284,0,0,0) = -1 errno=89 (Function not implemented) 15978 futex(0x4007f758,-2130706432,16777216,0x0001,NULL,0) = 0 15978 futex(0x4007f758,-1996423168,16777216,NULL,NULL,0) = -1 errno=89 (Function not implemented) 15978 rt_sigaction(32,1074263784,0,16,0,0) = 0 15978 rt_sigaction(33,1074263784,0,16,0,0) = -1 errno=22 (Invalid argument) 15978 rt_sigprocmask(2,1074263920,0,16,0,0) = 0 15978 getrlimit(3,1074263904,0,0,0,0) = 0 15978 clock_gettime(0,4688892,1074264284,0,0,0) = 0 15978 brk(NULL) = 0x0047a000 15978 brk(0x0049b000) = 0x0049b000 15978 open(/usr/lib/locale/locale-archive,O_RDONLY|O_LARGEFILE) = -1 errno=2 (No such file or directory) 15978 open(/usr/share/locale/locale.alias,O_RDONLY) = -1 errno=2 (No such file or directory) 15978 open(/usr/lib/locale/en_US.UTF-8/LC_IDENTIFICATION,O_RDONLY) = -1 errno=2 (No such file or directory) 15978 open(/usr/lib/locale/en_US.utf8/LC_IDENTIFICATION,O_RDONLY) = -1 errno=2 (No such file or directory) 15978 open(/usr/lib/locale/en_US/LC_IDENTIFICATION,O_RDONLY) = -1 errno=2 (No such file or directory) 15978
[Qemu-devel] Re: [PATCH v5 3/6] char: Let writers know how much data was written in case of errors
On 05/04/10 13:31, Amit Shah wrote: On (Tue) May 04 2010 [13:24:58], Gerd Hoffmann wrote: @@ -531,8 +534,12 @@ static int unix_write(int fd, const uint8_t *buf, int len1) while (len 0) { ret = write(fd, buf, len); if (ret 0) { -if (errno != EINTR errno != EAGAIN) +if (len1 - len) { +return len1 - len; +} +if (errno != EINTR errno != EAGAIN) { return -1; +} This makes unix_write pass -EINTR up to the caller which it didn't before. Only on partial writes. Should be OK, no? No. Callers which never saw partial writes due to write() syscall being interrupted by some signal start seeing them now. cheers, Gerd
[Qemu-devel] [PATCH] vnc: make sure to send pointer type change event on SetEncodings
Commit 37c34d9d5d87ea9d51760310c8863b82cb8c055a introduced a regression when using relative mouse mode with a client that understands the PointerTypeChange pseudo-encoding. Reported-by: Marcelo Tosatti mtosa...@redhat.com Reported-by: Gerhard Wiesinger li...@wiesinger.com Signed-off-by: Anthony Liguori aligu...@us.ibm.com --- vnc.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/vnc.c b/vnc.c index 5241a6a..b1a3fdb 100644 --- a/vnc.c +++ b/vnc.c @@ -1642,6 +1642,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) break; } } + +check_pointer_type_change(vs-mouse_mode_notifier); } static void set_pixel_conversion(VncState *vs) -- 1.6.5.2
[Qemu-devel] [patch uq/master 0/9] enable smp 1 and related fixes
Re: [Qemu-devel] Qemu-KVM 0.12.3 and Multipath - Assertion
hi kevin, you did it *g* looks promising. applied this patched and was not able to reproduce yet :-) secure way to reproduce was to shut down all multipath paths, then initiate i/o in the vm (e.g. start an application). of course, everything hangs at this point. after reenabling one path, vm crashed. now it seems to behave correctly and just report an DMA timeout and continues normally afterwards. can you imagine of any way preventing the vm to consume 100% cpu in that waiting state? my current approach is to run all vms with nice 1, which helped to keep the machine responsible if all vms (in my test case 64 on a box) have hanging i/o at the same time. br, peter Kevin Wolf wrote: Am 04.05.2010 13:38, schrieb Peter Lieven: hi kevin, i set a breakpint at bmdma_active_if. the first 2 breaks encountered when the last path in the multipath failed, but the assertion was not true. when i kicked one path back in the breakpoint was reached again, this time leading to an assert. the stacktrace is from the point shortly before. hope this helps. Hm, looks like there's something wrong with cancelling requests - bdrv_aio_cancel might decide that it completes a request (and consequently calls the callback for it) whereas the IDE emulation decides that it's done with the request before calling bdrv_aio_cancel. I haven't looked in much detail what this could break, but does something like this help? diff --git a/hw/ide/core.c b/hw/ide/core.c index 0757528..3cd55e3 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2838,10 +2838,6 @@ static void ide_dma_restart(IDEState *s, int is_read) void ide_dma_cancel(BMDMAState *bm) { if (bm-status BM_STATUS_DMAING) { -bm-status = ~BM_STATUS_DMAING; -/* cancel DMA request */ -bm-unit = -1; -bm-dma_cb = NULL; if (bm-aiocb) { #ifdef DEBUG_AIO printf(aio_cancel\n); @@ -2849,6 +2845,10 @@ void ide_dma_cancel(BMDMAState *bm) bdrv_aio_cancel(bm-aiocb); bm-aiocb = NULL; } +bm-status = ~BM_STATUS_DMAING; +/* cancel DMA request */ +bm-unit = -1; +bm-dma_cb = NULL; } } Kevin
Re: [Qemu-devel] [PATCH] [RESEND] Make char muxer more robust wrt small FIFOs
On 04/20/2010 11:56 AM, Alexander Graf wrote: Virtio-Console can only process one character at a time. Using it on S390 gave me strage lags where I got the character I pressed before when pressing one. So I typed in abc and only received a, then pressed d but the guest received b and so on. While the stdio driver calls a poll function that just processes on its queue in case virtio-console can't take multiple characters at once, the muxer does not have such callbacks, so it can't empty its queue. To work around that limitation, I introduced a new timer that only gets active when the guest can not receive any more characters. In that case it polls again after a while to check if the guest is now receiving input. This patch fixes input when using -nographic on s390 for me. I think this is really a kvm issue. I assume it's because s390 idles in the kernel so you never drop to userspace to repoll the descriptor. A timer is a hacky solution. You really need to use an io thread to solve this and then you need to switch away from qemu_set_fd_handler2 to qemu_set_fd_handler() and make sure that the later breaks select whenever it's invoked. Regards, Anthony Liguori --- Please consider for stable. --- qemu-char.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 05df971..ce9df3a 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -235,6 +235,7 @@ typedef struct { IOEventHandler *chr_event[MAX_MUX]; void *ext_opaque[MAX_MUX]; CharDriverState *drv; +QEMUTimer *accept_timer; int focus; int mux_cnt; int term_got_escape; @@ -396,6 +397,13 @@ static void mux_chr_accept_input(CharDriverState *chr) d-chr_read[m](d-ext_opaque[m], d-buffer[m][d-cons[m]++ MUX_BUFFER_MASK], 1); } + +/* We're still not able to sync producer and consumer, so let's wait a bit + and try again by then. */ +if (d-prod[m] != d-cons[m]) { +qemu_mod_timer(d-accept_timer, qemu_get_clock(vm_clock) ++ (int64_t)10); +} } static int mux_chr_can_read(void *opaque) @@ -478,6 +486,8 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) chr-opaque = d; d-drv = drv; d-focus = -1; +d-accept_timer = qemu_new_timer(vm_clock, + (QEMUTimerCB*)mux_chr_accept_input, chr); chr-chr_write = mux_chr_write; chr-chr_update_read_handler = mux_chr_update_read_handler; chr-chr_accept_input = mux_chr_accept_input;
Re: [Qemu-devel] [PATCH] hw: better i440 emulation
On 04/20/2010 01:48 PM, Bernhard M. Wiedemann wrote: updated version of an old patch http://xenon.stanford.edu/~eswierk/misc/qemu-linuxbios/qemu-piix-ram-size.patch that together with http://www.mail-archive.com/linuxb...@linuxbios.org/msg02390.html (which is already in coreboot trunk) allows coreboot to autodetect the amount of RAM within qemu/kvm from a register in i440 northbridge. The message on the old patch states: Unfortunately the current version of qemu does not set these registers, but I have patched qemu so that it emulates the i440 more faithfully in this regard. Signed-off-by: Bernhard M. Wiedemannqemudev...@lsmod.de Applied. Thanks. Regards, Anthony Liguori
[Qemu-devel] [patch uq/master 3/9] standardize on qemu_cpu_kick for signalling cpu thread(s)
Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/cpus.c === --- qemu.orig/cpus.c +++ qemu/cpus.c @@ -454,8 +454,7 @@ void qemu_cpu_kick(void *_env) { CPUState *env = _env; qemu_cond_broadcast(env-halt_cond); -if (kvm_enabled()) -qemu_thread_signal(env-thread, SIG_IPI); +qemu_thread_signal(env-thread, SIG_IPI); } int qemu_cpu_self(void *_env) @@ -583,7 +582,6 @@ void pause_all_vcpus(void) while (penv) { penv-stop = 1; -qemu_thread_signal(penv-thread, SIG_IPI); qemu_cpu_kick(penv); penv = (CPUState *)penv-next_cpu; } @@ -592,7 +590,7 @@ void pause_all_vcpus(void) qemu_cond_timedwait(qemu_pause_cond, qemu_global_mutex, 100); penv = first_cpu; while (penv) { -qemu_thread_signal(penv-thread, SIG_IPI); +qemu_cpu_kick(penv); penv = (CPUState *)penv-next_cpu; } } @@ -605,7 +603,6 @@ void resume_all_vcpus(void) while (penv) { penv-stop = 0; penv-stopped = 0; -qemu_thread_signal(penv-thread, SIG_IPI); qemu_cpu_kick(penv); penv = (CPUState *)penv-next_cpu; }
[Qemu-devel] [patch uq/master 1/9] kvm: set cpu_single_env around KVM_RUN ioctl
Zero cpu_single_env before leaving global lock protection, and restore on return. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/kvm-all.c === --- qemu.orig/kvm-all.c +++ qemu/kvm-all.c @@ -846,9 +846,11 @@ int kvm_cpu_exec(CPUState *env) } kvm_arch_pre_run(env, run); +cpu_single_env = NULL; qemu_mutex_unlock_iothread(); ret = kvm_vcpu_ioctl(env, KVM_RUN, 0); qemu_mutex_lock_iothread(); +cpu_single_env = env; kvm_arch_post_run(env, run); if (ret == -EINTR || ret == -EAGAIN) {
[Qemu-devel] [patch uq/master 2/9] make SIG_IPI to tcg vcpu thread reliable
Store tcg loop exit request on a global variable, and transfer it to per-CPUState exit_request after assignment of cpu_single_env. This makes exit request signal from robust. Drop the timedlock hack. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/cpu-exec.c === --- qemu.orig/cpu-exec.c +++ qemu/cpu-exec.c @@ -213,6 +213,8 @@ static void cpu_handle_debug_exception(C /* main execution loop */ +volatile sig_atomic_t exit_request; + int cpu_exec(CPUState *env1) { volatile host_reg_t saved_env_reg; @@ -234,6 +236,11 @@ int cpu_exec(CPUState *env1) asm(); env = env1; +if (exit_request) { +env-exit_request = 1; +exit_request = 0; +} + #if defined(TARGET_I386) if (!kvm_enabled()) { /* put eflags in CPU temporary format */ Index: qemu/cpus.c === --- qemu.orig/cpus.c +++ qemu/cpus.c @@ -472,6 +472,7 @@ static void cpu_signal(int sig) { if (cpu_single_env) cpu_exit(cpu_single_env); +exit_request = 1; } static void tcg_block_io_signals(void) @@ -542,26 +543,20 @@ static void unblock_io_signals(void) pthread_sigmask(SIG_BLOCK, set, NULL); } -static void qemu_signal_lock(unsigned int msecs) -{ -qemu_mutex_lock(qemu_fair_mutex); - -while (qemu_mutex_trylock(qemu_global_mutex)) { -qemu_thread_signal(tcg_cpu_thread, SIG_IPI); -if (!qemu_mutex_timedlock(qemu_global_mutex, msecs)) -break; -} -qemu_mutex_unlock(qemu_fair_mutex); -} - void qemu_mutex_lock_iothread(void) { if (kvm_enabled()) { qemu_mutex_lock(qemu_fair_mutex); qemu_mutex_lock(qemu_global_mutex); qemu_mutex_unlock(qemu_fair_mutex); -} else -qemu_signal_lock(100); +} else { +qemu_mutex_lock(qemu_fair_mutex); +if (qemu_mutex_trylock(qemu_global_mutex)) { +qemu_thread_signal(tcg_cpu_thread, SIG_IPI); +qemu_mutex_lock(qemu_global_mutex); +} +qemu_mutex_unlock(qemu_fair_mutex); +} } void qemu_mutex_unlock_iothread(void) Index: qemu/exec-all.h === --- qemu.orig/exec-all.h +++ qemu/exec-all.h @@ -339,4 +339,7 @@ CPUDebugExcpHandler *cpu_set_debug_excp_ /* vl.c */ extern int singlestep; +/* cpu-exec.c */ +extern volatile sig_atomic_t exit_request; + #endif
[Qemu-devel] [patch uq/master 8/9] kvm: validate context for kvm cpu get/put operations
From: Jan Kiszka jan.kis...@siemens.com Validate that KVM vcpu state is only read/written from cpu thread itself or that cpu is stopped. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Index: qemu/target-i386/kvm.c === --- qemu.orig/target-i386/kvm.c +++ qemu/target-i386/kvm.c @@ -949,6 +949,8 @@ int kvm_arch_put_registers(CPUState *env { int ret; +assert(cpu_is_stopped(env) || qemu_cpu_self(env)); + ret = kvm_getput_regs(env, 1); if (ret 0) return ret; @@ -991,6 +993,8 @@ int kvm_arch_get_registers(CPUState *env { int ret; +assert(cpu_is_stopped(env) || qemu_cpu_self(env)); + ret = kvm_getput_regs(env, 0); if (ret 0) return ret;
Re: [Qemu-devel] [PATCH 1/2] qemu-error: Introduce get_errno_name()
On 05/04/2010 08:56 AM, Luiz Capitulino wrote: On Mon, 03 May 2010 08:16:35 -0500 Anthony Liguorianth...@codemonkey.ws wrote: On 05/03/2010 08:06 AM, Markus Armbruster wrote: Luiz Capitulinolcapitul...@redhat.com writes: We need to expose errno in QMP, for three reasons: 1. Some error handling functions print errno codes to the user, while it's debatable whether this is good or not from a user perspective, sometimes it's the best we can do because it's what system calls and libraries return 2. Some events (eg. BLOCK_IO_ERROR) will be made even more complete with errno information 3. It's very good for debugging So, we need a way to expose those codes in QMP. We can't just use the codes themselfs because they may vary between systems. The best solution I can think of is to return the string representation of the name. For example, EIO becomes EIO. This is what get_errno_name() does. Signed-off-by: Luiz Capitulinolcapitul...@redhat.com --- qemu-error.c | 85 ++ qemu-error.h |1 + 2 files changed, 86 insertions(+), 0 deletions(-) diff --git a/qemu-error.c b/qemu-error.c index 5a35e7c..7035417 100644 --- a/qemu-error.c +++ b/qemu-error.c @@ -207,3 +207,88 @@ void error_report(const char *fmt, ...) va_end(ap); error_printf(\n); } + +/* + * Probably only useful for QMP + */ +const char *get_errno_name(int err) +{ +switch (abs(err)) { +case EPERM: +return EPERM; +case ENOENT: +return ENOENT; [...] +case EDOM: +return EDOM; +case ERANGE: +return ERANGE; +case ENOMEDIUM: +return ENOMEDIUM; +case ENOTSUP: +return ENOTSUP; +default: +return unknown; How did you choose the codes to implement? POSIX has many more... I just ran an awk script on the linux's base errno header file, my idea is just to have the common names, anything 'new' will hit the default clause and we can add it later. Let me say another way why I think this is a bad path to go down. In generally, we could never just pass errno through down. Different host platforms are going to generate different errno values so we really need to filter and send reliable errno values so that clients don't have to have special code for when they're on Linux vs. AIX vs. Solaris. Sorry for the potential stupid question, but what would a 'reliable' errno be? Or, what's an unreliable errno? We're not sending plain integers to the clients, so the only problem I can see is if different unices return different errnos for the same error. Is that the problem you're seeing? Different types of platforms return different errno values for the same error type. As an example, on Linux, connect() returns EINPROGRESS when you set the socket non-blocking. On Windows, it returns EWOULDBLOCK. If you just pass through errno, then all QMP clients are going to have to know the different between QEMU on Windows and Linux and handle the errnos appropriately. If we're white listing errno values, we should be able to trivially convert errnos to QError types via a table just like you have above. Having a direct errno - QError mapping doesn't seem good for the current use cases. For example, do_savevm() (not merged yet) has a StateVmSaveFailed error which also has a 'reason' member, which would look like this on the wire: { 'class': 'StateVmSaveFailed', 'data': { 'reason': EIO } } So, the QError class says what has failed and the errno part says why it has failed. I'd be happy to implement a different solution that satisfies this basic requirement. We need to map errnos to some QMP defined error type. However, as I've said before, reason is usually an indicator that an error is bad. A better error would be: { 'class': 'SocketIOError': 'data' : { 'source': 'migration' }} Or something like that. You don't want to have command and then CommandFailed as the error. You want the errors to be the 'reason's for the commands failure. Regards, Anthony Liguori
Re: [Qemu-devel] Qemu-KVM 0.12.3 and Multipath - Assertion
Am 04.05.2010 15:42, schrieb Peter Lieven: hi kevin, you did it *g* looks promising. applied this patched and was not able to reproduce yet :-) secure way to reproduce was to shut down all multipath paths, then initiate i/o in the vm (e.g. start an application). of course, everything hangs at this point. after reenabling one path, vm crashed. now it seems to behave correctly and just report an DMA timeout and continues normally afterwards. Great, I'm going to submit it as a proper patch then. Christoph, by now I'm pretty sure it's right, but can you have another look if this is correct, anyway? can you imagine of any way preventing the vm to consume 100% cpu in that waiting state? my current approach is to run all vms with nice 1, which helped to keep the machine responsible if all vms (in my test case 64 on a box) have hanging i/o at the same time. I don't have anything particular in mind, but you could just attach gdb and get another backtrace while it consumes 100% CPU (you'll need to use thread apply all bt to catch everything). Then we should see where it's hanging. Kevin
Re: [Qemu-devel] [PATCH 1/2] qemu-error: Introduce get_errno_name()
On Mon, 03 May 2010 08:16:35 -0500 Anthony Liguori anth...@codemonkey.ws wrote: On 05/03/2010 08:06 AM, Markus Armbruster wrote: Luiz Capitulinolcapitul...@redhat.com writes: We need to expose errno in QMP, for three reasons: 1. Some error handling functions print errno codes to the user, while it's debatable whether this is good or not from a user perspective, sometimes it's the best we can do because it's what system calls and libraries return 2. Some events (eg. BLOCK_IO_ERROR) will be made even more complete with errno information 3. It's very good for debugging So, we need a way to expose those codes in QMP. We can't just use the codes themselfs because they may vary between systems. The best solution I can think of is to return the string representation of the name. For example, EIO becomes EIO. This is what get_errno_name() does. Signed-off-by: Luiz Capitulinolcapitul...@redhat.com --- qemu-error.c | 85 ++ qemu-error.h |1 + 2 files changed, 86 insertions(+), 0 deletions(-) diff --git a/qemu-error.c b/qemu-error.c index 5a35e7c..7035417 100644 --- a/qemu-error.c +++ b/qemu-error.c @@ -207,3 +207,88 @@ void error_report(const char *fmt, ...) va_end(ap); error_printf(\n); } + +/* + * Probably only useful for QMP + */ +const char *get_errno_name(int err) +{ +switch (abs(err)) { +case EPERM: +return EPERM; +case ENOENT: +return ENOENT; [...] +case EDOM: +return EDOM; +case ERANGE: +return ERANGE; +case ENOMEDIUM: +return ENOMEDIUM; +case ENOTSUP: +return ENOTSUP; +default: +return unknown; How did you choose the codes to implement? POSIX has many more... I just ran an awk script on the linux's base errno header file, my idea is just to have the common names, anything 'new' will hit the default clause and we can add it later. Let me say another way why I think this is a bad path to go down. In generally, we could never just pass errno through down. Different host platforms are going to generate different errno values so we really need to filter and send reliable errno values so that clients don't have to have special code for when they're on Linux vs. AIX vs. Solaris. Sorry for the potential stupid question, but what would a 'reliable' errno be? Or, what's an unreliable errno? We're not sending plain integers to the clients, so the only problem I can see is if different unices return different errnos for the same error. Is that the problem you're seeing? If we're white listing errno values, we should be able to trivially convert errnos to QError types via a table just like you have above. Having a direct errno - QError mapping doesn't seem good for the current use cases. For example, do_savevm() (not merged yet) has a StateVmSaveFailed error which also has a 'reason' member, which would look like this on the wire: { 'class': 'StateVmSaveFailed', 'data': { 'reason': EIO } } So, the QError class says what has failed and the errno part says why it has failed. I'd be happy to implement a different solution that satisfies this basic requirement.
[Qemu-devel] KVM call minutes for May 4
KVM Forum topic ideas - mgmt interface (qemud) - working breakout sessions are welcome at the Forum stable tree - have a volunteer (thanks Justin) - Anthony will write up proposal which is basically - bug fixes actively proposed for stable tree - stable maintainer collects and applies - periodically release and re-sync w/ main tree 0.12.4? - RSN...will tag and push shortly
Re: [Qemu-devel] [PATCH] vnc: split encoding in specific files
On 05/04/2010 03:12 AM, Kevin Wolf wrote: Am 03.05.2010 19:15, schrieb Anthony Liguori: On 05/03/2010 07:31 AM, Corentin Chary wrote: This will allow to implement new encodings (tight, zrle, ..) in a cleaner way. This may hurt performances, because some functions like vnc_convert_pixel are not static anymore, but should not be a problem with gcc 4.5 and the new -flto. Signed-off-by: Corentin Charycorenti...@iksaif.net Applied. Thanks. It's probably time to make a vnc directory too. Or maybe one for all of the interfaces we currently have in the root directory? So it would include not only VNC, but also SDL and curses. Makes sense. Regards, Anthony Liguori Kevin
[Qemu-devel] Re: QEMU: current user mode breakage
On Fri, Apr 30, 2010 at 11:43:43AM +0200, Martin Mohring wrote: not sure how to handle the situation. But since the commit of the new memory allocator for QEMU user mode, my test suites show it is broken. The 0 sized write patch still isn't applied upstream. Is that the issue (eg visible by ldconfig.real not working) for you, or is everything broken even with that patch applied? Just run ltp tests without any noticable regressions on debian/armel/sid. No performance slowdown was observerd either.
Re: [Qemu-devel] [PATCH] document boot option to -drive parameter
On 04/16/2010 12:11 PM, Bruce Rogers wrote: The boot option is missing from the documentation for the -drive parameter. If there is a better way to descibe it, I'm all ears. Signed-off-by: Bruce Rogersbrog...@novell.com diff --git a/qemu-options.hx b/qemu-options.hx index f4b3bfe..f0f9a7c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -159,6 +159,8 @@ an untrusted format header. This option specifies the serial number to assign to the device. @item ad...@var{addr} Specify the controller's PCI address (if=virtio only). +...@item bo...@var{boot} +...@var{boot} is on or off and allows for booting from non-traditional interfaces, such as virtio. @end table By default, writethrough caching is used for all block device. This means that This is only in qemu-kvm.git. Regards, Anthony Liguori
Re: [Qemu-devel] [PATCH] [RESEND] Make char muxer more robust wrt small FIFOs
Am 04.05.2010 um 15:44 schrieb Anthony Liguori anth...@codemonkey.ws: On 04/20/2010 11:56 AM, Alexander Graf wrote: Virtio-Console can only process one character at a time. Using it on S390 gave me strage lags where I got the character I pressed before when pressing one. So I typed in abc and only received a, then pressed d but the guest received b and so on. While the stdio driver calls a poll function that just processes on its queue in case virtio-console can't take multiple characters at once, the muxer does not have such callbacks, so it can't empty its queue. To work around that limitation, I introduced a new timer that only gets active when the guest can not receive any more characters. In that case it polls again after a while to check if the guest is now receiving input. This patch fixes input when using -nographic on s390 for me. I think this is really a kvm issue. I assume it's because s390 idles in the kernel so you never drop to userspace to repoll the descriptor. There is no polling for the muxer. That's why it never knows when virtio-console can receive again. This patch basically adfs timer based polling for that exact case. Alex A timer is a hacky solution. You really need to use an io thread to solve this and then you need to switch away from qemu_set_fd_handler2 to qemu_set_fd_handler() and make sure that the later breaks select whenever it's invoked. Regards, Anthony Liguori --- Please consider for stable. --- qemu-char.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 05df971..ce9df3a 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -235,6 +235,7 @@ typedef struct { IOEventHandler *chr_event[MAX_MUX]; void *ext_opaque[MAX_MUX]; CharDriverState *drv; +QEMUTimer *accept_timer; int focus; int mux_cnt; int term_got_escape; @@ -396,6 +397,13 @@ static void mux_chr_accept_input (CharDriverState *chr) d-chr_read[m](d-ext_opaque[m], d-buffer[m][d-cons[m]++ MUX_BUFFER_MASK], 1); } + +/* We're still not able to sync producer and consumer, so let's wait a bit + and try again by then. */ +if (d-prod[m] != d-cons[m]) { +qemu_mod_timer(d-accept_timer, qemu_get_clock(vm_clock) ++ (int64_t)10); +} } static int mux_chr_can_read(void *opaque) @@ -478,6 +486,8 @@ static CharDriverState *qemu_chr_open_mux (CharDriverState *drv) chr-opaque = d; d-drv = drv; d-focus = -1; +d-accept_timer = qemu_new_timer(vm_clock, + (QEMUTimerCB*) mux_chr_accept_input, chr); chr-chr_write = mux_chr_write; chr-chr_update_read_handler = mux_chr_update_read_handler; chr-chr_accept_input = mux_chr_accept_input;
Re: [Qemu-devel] [PATCH] [RESEND] Make char muxer more robust wrt small FIFOs
On 05/04/2010 09:30 AM, Alexander Graf wrote: Am 04.05.2010 um 15:44 schrieb Anthony Liguori anth...@codemonkey.ws: On 04/20/2010 11:56 AM, Alexander Graf wrote: Virtio-Console can only process one character at a time. Using it on S390 gave me strage lags where I got the character I pressed before when pressing one. So I typed in abc and only received a, then pressed d but the guest received b and so on. While the stdio driver calls a poll function that just processes on its queue in case virtio-console can't take multiple characters at once, the muxer does not have such callbacks, so it can't empty its queue. To work around that limitation, I introduced a new timer that only gets active when the guest can not receive any more characters. In that case it polls again after a while to check if the guest is now receiving input. This patch fixes input when using -nographic on s390 for me. I think this is really a kvm issue. I assume it's because s390 idles in the kernel so you never drop to userspace to repoll the descriptor. There is no polling for the muxer. That's why it never knows when virtio-console can receive again. Maybe I'm missing something simple, but it looks to me like the muxer is polling. mux_chr_can_read() is going to eventually poll the muxed devices to figure this out. If the root of the problem is that mux_chr_can_read() isn't being invoked for a prolonged period of time, the real issue is the problem I described. Regards, Anthony Liguori This patch basically adfs timer based polling for that exact case. Alex A timer is a hacky solution. You really need to use an io thread to solve this and then you need to switch away from qemu_set_fd_handler2 to qemu_set_fd_handler() and make sure that the later breaks select whenever it's invoked. Regards, Anthony Liguori --- Please consider for stable. --- qemu-char.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 05df971..ce9df3a 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -235,6 +235,7 @@ typedef struct { IOEventHandler *chr_event[MAX_MUX]; void *ext_opaque[MAX_MUX]; CharDriverState *drv; +QEMUTimer *accept_timer; int focus; int mux_cnt; int term_got_escape; @@ -396,6 +397,13 @@ static void mux_chr_accept_input(CharDriverState *chr) d-chr_read[m](d-ext_opaque[m], d-buffer[m][d-cons[m]++ MUX_BUFFER_MASK], 1); } + +/* We're still not able to sync producer and consumer, so let's wait a bit + and try again by then. */ +if (d-prod[m] != d-cons[m]) { +qemu_mod_timer(d-accept_timer, qemu_get_clock(vm_clock) ++ (int64_t)10); +} } static int mux_chr_can_read(void *opaque) @@ -478,6 +486,8 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) chr-opaque = d; d-drv = drv; d-focus = -1; +d-accept_timer = qemu_new_timer(vm_clock, + (QEMUTimerCB*)mux_chr_accept_input, chr); chr-chr_write = mux_chr_write; chr-chr_update_read_handler = mux_chr_update_read_handler; chr-chr_accept_input = mux_chr_accept_input;
[Qemu-devel] Re: Qemu-KVM 0.12.3 and Multipath - Assertion
Hi Peter, On 03.05.2010 23:26, Peter Lieven wrote: Hi Qemu/KVM Devel Team, i'm using qemu-kvm 0.12.3 with latest Kernel 2.6.33.3. As backend we use open-iSCSI with dm-multipath. Multipath is configured to queue i/o if no path is available. If we create a failure on all paths, qemu starts to consume 100% CPU due to i/o waits which is ok so far. 1 odd thing: The Monitor Interface is not responding any more ... What es a really blocker is that KVM crashes with: kvm: /usr/src/qemu-kvm-0.12.3/hw/ide/internal.h:507: bmdma_active_if: Assertion `bmdma-unit != (uint8_t)-1' failed. after the multipath has reestablisched at least one path. Any ideas? I remember this was working with earlier kernel/kvm/qemu versions. I have the same issue on my machine, although I am using local storage (LVM or a physical disk) to write my data to. I reported the Assertion failed on March 17th to the list. Marcello and Avi had asked some question back then, but I don't know if they have come up with a fix for it. Regards André
[Qemu-devel] Patch to improve handling of server sockets
Hi, I am maintaining the tightvnc package for openSUSE and was recently confronted with an alleged vnc problem with QWMU that turned out to be a shortcoming in QEMU's code for handling TCP server sockets, which is used by the vnc and char modules. The problem occurs when the address to listen on is given as a name which resolves to multiple IP addresses the most prominent example being localhost resolving to 127.0.0.1 and ::1 . The existing code stopped walking the list of addresses returned by getaddrinfo() as soon as one socket was successfully opened and bound. The result was that a qemu instance started with -vnc localhost:42 only listened on ::1, wasn't reachable through 127.0.0.1. The fact that the code set the IPV6_V6ONLY socket option didn't help, because that option only works when the socket gets bound to the IPv6 wildcard address (::), but is useless for explicit address bindings. The attached patch against QEMU 0.11.0 extends inet_listen() to create sockets for as many addresses from the address list as possible and adapts its callers and their data structures to deal with a linked list of socket FDs rather than a single file descriptor. So far I've only done some testing with the -vnc option. More testing is needed in the qemu-char area and for the parts of the code that get triggered from QEMU's Monitor. Please review and comment. cu Reinhard P.S. Please keep me in Cc when replying.Index: qemu-char.c === --- qemu-char.c.orig +++ qemu-char.c @@ -1831,7 +1831,8 @@ return_err: /* TCP Net console */ typedef struct { -int fd, listen_fd; +int fd; +FdList *listen_fds; int connected; int max_size; int do_telnetopt; @@ -1983,6 +1984,7 @@ static void tcp_chr_read(void *opaque) TCPCharDriver *s = chr-opaque; uint8_t buf[1024]; int len, size; +FdList *fdl; if (!s-connected || s-max_size = 0) return; @@ -1993,10 +1995,9 @@ static void tcp_chr_read(void *opaque) if (size == 0) { /* connection closed */ s-connected = 0; -if (s-listen_fd = 0) { -qemu_set_fd_handler(s-listen_fd, tcp_chr_accept, NULL, chr); -} -qemu_set_fd_handler(s-fd, NULL, NULL, NULL); + for (fdl = s-listen_fds; fdl != NULL; fdl = fdl-next) +qemu_set_fd_handler(fdl-fd, tcp_chr_accept, NULL, fdl); + qemu_set_fd_handler(s-fd, NULL, NULL, NULL); closesocket(s-fd); s-fd = -1; } else if (size 0) { @@ -2045,7 +2046,8 @@ static void socket_set_nodelay(int fd) static void tcp_chr_accept(void *opaque) { -CharDriverState *chr = opaque; +FdList *fdl = opaque; +CharDriverState *chr = fdl-opaque; TCPCharDriver *s = chr-opaque; struct sockaddr_in saddr; #ifndef _WIN32 @@ -2066,7 +2068,7 @@ static void tcp_chr_accept(void *opaque) len = sizeof(saddr); addr = (struct sockaddr *)saddr; } -fd = accept(s-listen_fd, addr, len); +fd = accept(fdl-fd, addr, len); if (fd 0 errno != EINTR) { return; } else if (fd = 0) { @@ -2079,20 +2081,24 @@ static void tcp_chr_accept(void *opaque) if (s-do_nodelay) socket_set_nodelay(fd); s-fd = fd; -qemu_set_fd_handler(s-listen_fd, NULL, NULL, NULL); +for (fdl = s-listen_fds; fdl != NULL; fdl = fdl-next) + qemu_set_fd_handler(fdl-fd, NULL, NULL, NULL); tcp_chr_connect(chr); } static void tcp_chr_close(CharDriverState *chr) { TCPCharDriver *s = chr-opaque; +FdList *fdl, *fdtmp; if (s-fd = 0) { qemu_set_fd_handler(s-fd, NULL, NULL, NULL); closesocket(s-fd); } -if (s-listen_fd = 0) { -qemu_set_fd_handler(s-listen_fd, NULL, NULL, NULL); -closesocket(s-listen_fd); +for (fdl = s-listen_fds; fdl != NULL; fdl = fdtmp) { + fdtmp = fdl-next; +qemu_set_fd_handler(fdl-fd, NULL, NULL, NULL); +closesocket(fdl-fd); + free(fdl); } qemu_free(s); } @@ -2108,6 +2114,7 @@ static CharDriverState *qemu_chr_open_tc int is_waitconnect = 1; int do_nodelay = 0; const char *ptr; +FdList *sockets = NULL, *fdl, *fdtmp; ptr = host_str; while((ptr = strchr(ptr,','))) { @@ -2155,11 +2162,18 @@ static CharDriverState *qemu_chr_open_tc } else { if (is_listen) { fd = inet_listen(host_str, chr-filename + offset, 256 - offset, - SOCK_STREAM, 0); + SOCK_STREAM, 0, sockets); } else { fd = inet_connect(host_str, SOCK_STREAM); } } + +if (sockets == NULL) { + sockets = malloc(sizeof(*sockets)); + sockets-next = NULL; + sockets-fd = fd; +} + if (fd 0) goto fail; @@ -2168,7 +2182,7 @@ static CharDriverState *qemu_chr_open_tc s-connected = 0; s-fd = -1; -s-listen_fd = -1; +s-listen_fds = NULL; s-msgfd =
Re: [Qemu-devel] [PATCH] [RESEND] Make char muxer more robust wrt small FIFOs
Am 04.05.2010 um 16:34 schrieb Anthony Liguori anth...@codemonkey.ws: On 05/04/2010 09:30 AM, Alexander Graf wrote: Am 04.05.2010 um 15:44 schrieb Anthony Liguori anth...@codemonkey.ws: On 04/20/2010 11:56 AM, Alexander Graf wrote: Virtio-Console can only process one character at a time. Using it on S390 gave me strage lags where I got the character I pressed before when pressing one. So I typed in abc and only received a, then pressed d but the guest received b and so on. While the stdio driver calls a poll function that just processes on its queue in case virtio-console can't take multiple characters at once, the muxer does not have such callbacks, so it can't empty its queue. To work around that limitation, I introduced a new timer that only gets active when the guest can not receive any more characters. In that case it polls again after a while to check if the guest is now receiving input. This patch fixes input when using -nographic on s390 for me. I think this is really a kvm issue. I assume it's because s390 idles in the kernel so you never drop to userspace to repoll the descriptor. There is no polling for the muxer. That's why it never knows when virtio-console can receive again. Maybe I'm missing something simple, but it looks to me like the muxer is polling. mux_chr_can_read() is going to eventually poll the muxed devices to figure this out. If the root of the problem is that mux_chr_can_read() isn't being invoked for a prolonged period of time, the real issue is the problem I described. The problem is that the select list of fds includes the stdio fd, so that gets notified and is coupled with virtio-console, but there's nothing passing that on to mux and I don't think it'd be clever to expose internal data to the muxer to tell it about the backend fds. Alex Regards, Anthony Liguori This patch basically adfs timer based polling for that exact case. Alex A timer is a hacky solution. You really need to use an io thread to solve this and then you need to switch away from qemu_set_fd_handler2 to qemu_set_fd_handler() and make sure that the later breaks select whenever it's invoked. Regards, Anthony Liguori --- Please consider for stable. --- qemu-char.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 05df971..ce9df3a 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -235,6 +235,7 @@ typedef struct { IOEventHandler *chr_event[MAX_MUX]; void *ext_opaque[MAX_MUX]; CharDriverState *drv; +QEMUTimer *accept_timer; int focus; int mux_cnt; int term_got_escape; @@ -396,6 +397,13 @@ static void mux_chr_accept_input (CharDriverState *chr) d-chr_read[m](d-ext_opaque[m], d-buffer[m][d-cons[m]++ MUX_BUFFER_MASK], 1); } + +/* We're still not able to sync producer and consumer, so let's wait a bit + and try again by then. */ +if (d-prod[m] != d-cons[m]) { +qemu_mod_timer(d-accept_timer, qemu_get_clock(vm_clock) ++ (int64_t)10); +} } static int mux_chr_can_read(void *opaque) @@ -478,6 +486,8 @@ static CharDriverState *qemu_chr_open_mux (CharDriverState *drv) chr-opaque = d; d-drv = drv; d-focus = -1; +d-accept_timer = qemu_new_timer(vm_clock, + (QEMUTimerCB*) mux_chr_accept_input, chr); chr-chr_write = mux_chr_write; chr-chr_update_read_handler = mux_chr_update_read_handler; chr-chr_accept_input = mux_chr_accept_input;
Re: [Qemu-devel] Patch to improve handling of server sockets
On 05/04/2010 08:49 AM, Reinhard Max wrote: Hi, I am maintaining the tightvnc package for openSUSE and was recently confronted with an alleged vnc problem with QWMU that turned out to be a shortcoming in QEMU's code for handling TCP server sockets, which is used by the vnc and char modules. The problem occurs when the address to listen on is given as a name which resolves to multiple IP addresses the most prominent example being localhost resolving to 127.0.0.1 and ::1 . The existing code stopped walking the list of addresses returned by getaddrinfo() as soon as one socket was successfully opened and bound. The result was that a qemu instance started with -vnc localhost:42 only listened on ::1, wasn't reachable through 127.0.0.1. The fact that the code set the IPV6_V6ONLY socket option didn't help, because that option only works when the socket gets bound to the IPv6 wildcard address (::), but is useless for explicit address bindings. The attached patch against QEMU 0.11.0 extends inet_listen() to create sockets for as many addresses from the address list as possible and adapts its callers and their data structures to deal with a linked list of socket FDs rather than a single file descriptor. So far I've only done some testing with the -vnc option. More testing is needed in the qemu-char area and for the parts of the code that get triggered from QEMU's Monitor. 0.11.0 is pretty old. Please update your patch against the latest git. But that said, I'm not sure we're doing the wrong thing right now. Gerd, what do you think about this behavior? Regards, Anthony Liguori Please review and comment. cu Reinhard P.S. Please keep me in Cc when replying.
Re: [Qemu-devel] [PATCH] [RESEND] Make char muxer more robust wrt small FIFOs
On 05/04/2010 11:01 AM, Alexander Graf wrote: Am 04.05.2010 um 16:34 schrieb Anthony Liguori anth...@codemonkey.ws: On 05/04/2010 09:30 AM, Alexander Graf wrote: Am 04.05.2010 um 15:44 schrieb Anthony Liguori anth...@codemonkey.ws: On 04/20/2010 11:56 AM, Alexander Graf wrote: Virtio-Console can only process one character at a time. Using it on S390 gave me strage lags where I got the character I pressed before when pressing one. So I typed in abc and only received a, then pressed d but the guest received b and so on. While the stdio driver calls a poll function that just processes on its queue in case virtio-console can't take multiple characters at once, the muxer does not have such callbacks, so it can't empty its queue. To work around that limitation, I introduced a new timer that only gets active when the guest can not receive any more characters. In that case it polls again after a while to check if the guest is now receiving input. This patch fixes input when using -nographic on s390 for me. I think this is really a kvm issue. I assume it's because s390 idles in the kernel so you never drop to userspace to repoll the descriptor. There is no polling for the muxer. That's why it never knows when virtio-console can receive again. Maybe I'm missing something simple, but it looks to me like the muxer is polling. mux_chr_can_read() is going to eventually poll the muxed devices to figure this out. If the root of the problem is that mux_chr_can_read() isn't being invoked for a prolonged period of time, the real issue is the problem I described. The problem is that the select list of fds includes the stdio fd, so that gets notified and is coupled with virtio-console, but there's nothing passing that on to mux and I don't think it'd be clever to expose internal data to the muxer to tell it about the backend fds. When stdio is readable, it should invoke qemu_chr_read() with the read data which in turn ought to invoke mux_chr_read(). I'm not sure I understand what signalling is missing. Jan, does the problem Alex describes ring a bell? I seem to recall you saying that mux was still fundamentally broken but ought to work most of the time... Regards, Anthony Liguori Alex
Re: [Qemu-devel] [PATCH] [RESEND] Make char muxer more robust wrt small FIFOs
Anthony Liguori wrote: On 05/04/2010 11:01 AM, Alexander Graf wrote: Am 04.05.2010 um 16:34 schrieb Anthony Liguori anth...@codemonkey.ws: On 05/04/2010 09:30 AM, Alexander Graf wrote: Am 04.05.2010 um 15:44 schrieb Anthony Liguori anth...@codemonkey.ws: On 04/20/2010 11:56 AM, Alexander Graf wrote: Virtio-Console can only process one character at a time. Using it on S390 gave me strage lags where I got the character I pressed before when pressing one. So I typed in abc and only received a, then pressed d but the guest received b and so on. While the stdio driver calls a poll function that just processes on its queue in case virtio-console can't take multiple characters at once, the muxer does not have such callbacks, so it can't empty its queue. To work around that limitation, I introduced a new timer that only gets active when the guest can not receive any more characters. In that case it polls again after a while to check if the guest is now receiving input. This patch fixes input when using -nographic on s390 for me. I think this is really a kvm issue. I assume it's because s390 idles in the kernel so you never drop to userspace to repoll the descriptor. There is no polling for the muxer. That's why it never knows when virtio-console can receive again. Maybe I'm missing something simple, but it looks to me like the muxer is polling. mux_chr_can_read() is going to eventually poll the muxed devices to figure this out. If the root of the problem is that mux_chr_can_read() isn't being invoked for a prolonged period of time, the real issue is the problem I described. The problem is that the select list of fds includes the stdio fd, so that gets notified and is coupled with virtio-console, but there's nothing passing that on to mux and I don't think it'd be clever to expose internal data to the muxer to tell it about the backend fds. When stdio is readable, it should invoke qemu_chr_read() with the read data which in turn ought to invoke mux_chr_read(). I'm not sure I understand what signalling is missing. Jan, does the problem Alex describes ring a bell? I seem to recall you saying that mux was still fundamentally broken but ought to work most of the time... That problem was (and still is) that the muxer needs to accept characters even if the active front-end device is not in order to filter out control sequences. Once its queue is full, it will start dropping those the active device would not if directly connected. Could only be solved via some peek service on pending front-end data. I think Alex' problem can be addressed by registering qemu_set_fd_handler2(..., backend-read_poll, mux_chr_read, ...). That means the backend has to tell us about its read poll handler (if any). Jan -- Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
[Qemu-devel] [PATCH 2/5] Add hwheel to monitor mouse_move
Adds a parameter to the monitor's mouse_move command to specify the hwheel delta. Signed-off-by: Brad Jorsch ano...@users.sourceforge.net --- monitor.c |8 ++-- qemu-monitor.hx |4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/monitor.c b/monitor.c index 520d48d..baff2cf 100644 --- a/monitor.c +++ b/monitor.c @@ -1832,16 +1832,20 @@ static int mouse_button_state; static void do_mouse_move(Monitor *mon, const QDict *qdict) { -int dx, dy, dz; +int dx, dy, dz, dw; const char *dx_str = qdict_get_str(qdict, dx_str); const char *dy_str = qdict_get_str(qdict, dy_str); const char *dz_str = qdict_get_try_str(qdict, dz_str); +const char *dw_str = qdict_get_try_str(qdict, dw_str); dx = strtol(dx_str, NULL, 0); dy = strtol(dy_str, NULL, 0); dz = 0; +dw = 0; if (dz_str) dz = strtol(dz_str, NULL, 0); -kbd_mouse_event(dx, dy, dz, 0, mouse_button_state); +if (dw_str) +dw = strtol(dw_str, NULL, 0); +kbd_mouse_event(dx, dy, dz, dw, mouse_button_state); } static void do_mouse_button(Monitor *mon, const QDict *qdict) diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 5ea5748..00067ba 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -616,8 +616,8 @@ ETEXI { .name = mouse_move, -.args_type = dx_str:s,dy_str:s,dz_str:s?, -.params = dx dy [dz], +.args_type = dx_str:s,dy_str:s,dz_str:s?,dw_str:s?, +.params = dx dy [dz [dw]], .help = send mouse move events, .mhandler.cmd = do_mouse_move, }, -- 1.7.1
[Qemu-devel] [PATCH 1/5] Add function parameters for hwheel
Add a parameter for the hwheel delta to QEMUPutMouseEntry and kbd_mouse_event, and adjust all users of those to match. At the moment, all calls to kbd_mouse_event will pass 0 for the delta. Signed-off-by: Brad Jorsch ano...@users.sourceforge.net --- cocoa.m |6 +++--- console.h |4 ++-- hw/adb.c|3 ++- hw/ads7846.c|2 +- hw/escc.c |3 ++- hw/msmouse.c|2 +- hw/ps2.c|4 ++-- hw/syborg_pointer.c |2 +- hw/tsc2005.c|2 +- hw/tsc210x.c|2 +- hw/usb-hid.c|5 +++-- hw/usb-wacom.c |5 +++-- hw/vmmouse.c|3 ++- hw/xenfb.c |2 +- input.c |6 +++--- monitor.c |4 ++-- sdl.c | 10 ++ vnc.c |6 +++--- 18 files changed, 39 insertions(+), 32 deletions(-) diff --git a/cocoa.m b/cocoa.m index 56c789a..c247833 100644 --- a/cocoa.m +++ b/cocoa.m @@ -47,9 +47,9 @@ #define cgrect(nsrect) (*(CGRect *)(nsrect)) #define COCOA_MOUSE_EVENT \ if (isTabletEnabled) { \ -kbd_mouse_event((int)(p.x * 0x7FFF / (screen.width - 1)), (int)((screen.height - p.y) * 0x7FFF / (screen.height - 1)), 0, buttons); \ +kbd_mouse_event((int)(p.x * 0x7FFF / (screen.width - 1)), (int)((screen.height - p.y) * 0x7FFF / (screen.height - 1)), 0, 0, buttons); \ } else if (isMouseGrabed) { \ -kbd_mouse_event((int)[event deltaX], (int)[event deltaY], 0, buttons); \ +kbd_mouse_event((int)[event deltaX], (int)[event deltaY], 0, 0, buttons); \ } else { \ [NSApp sendEvent:event]; \ } @@ -649,7 +649,7 @@ static int cocoa_keycode_to_qemu(int keycode) break; case NSScrollWheel: if (isTabletEnabled || isMouseGrabed) { -kbd_mouse_event(0, 0, -[event deltaY], 0); +kbd_mouse_event(0, 0, -[event deltaY], 0, 0); } else { [NSApp sendEvent:event]; } diff --git a/console.h b/console.h index 6def115..7ec693d 100644 --- a/console.h +++ b/console.h @@ -21,7 +21,7 @@ typedef void QEMUPutKBDEvent(void *opaque, int keycode); typedef void QEMUPutLEDEvent(void *opaque, int ledstate); -typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); +typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int dw, int buttons_state); typedef struct QEMUPutMouseEntry { QEMUPutMouseEvent *qemu_put_mouse_event; @@ -53,7 +53,7 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry); void kbd_put_keycode(int keycode); void kbd_put_ledstate(int ledstate); -void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); +void kbd_mouse_event(int dx, int dy, int dz, int dw, int buttons_state); /* Does the current mouse generate absolute events */ int kbd_mouse_is_absolute(void); diff --git a/hw/adb.c b/hw/adb.c index 4fb7a62..88be567 100644 --- a/hw/adb.c +++ b/hw/adb.c @@ -318,7 +318,8 @@ typedef struct MouseState { } MouseState; static void adb_mouse_event(void *opaque, -int dx1, int dy1, int dz1, int buttons_state) +int dx1, int dy1, int dz1, int dw1, +int buttons_state) { ADBDevice *d = opaque; MouseState *s = d-opaque; diff --git a/hw/ads7846.c b/hw/ads7846.c index 184b3dd..544db09 100644 --- a/hw/ads7846.c +++ b/hw/ads7846.c @@ -86,7 +86,7 @@ static uint32_t ads7846_transfer(SSISlave *dev, uint32_t value) } static void ads7846_ts_event(void *opaque, -int x, int y, int z, int buttons_state) +int x, int y, int z, int w, int buttons_state) { ADS7846State *s = opaque; diff --git a/hw/escc.c b/hw/escc.c index 6d2fd36..c7b420d 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -827,7 +827,8 @@ static void handle_kbd_command(ChannelState *s, int val) } static void sunmouse_event(void *opaque, - int dx, int dy, int dz, int buttons_state) + int dx, int dy, int dz, int dw, + int buttons_state) { ChannelState *s = opaque; int ch; diff --git a/hw/msmouse.c b/hw/msmouse.c index 05f893c..f1bfd0d 100644 --- a/hw/msmouse.c +++ b/hw/msmouse.c @@ -31,7 +31,7 @@ #define MSMOUSE_HI2(n) (((n) 0xc0) 6) static void msmouse_event(void *opaque, - int dx, int dy, int dz, int buttons_state) + int dx, int dy, int dz, int dw, int buttons_state) { CharDriverState *chr = (CharDriverState *)opaque; diff --git a/hw/ps2.c b/hw/ps2.c index f0b206a..db5605d 100644 --- a/hw/ps2.c +++ b/hw/ps2.c @@ -330,7 +330,7 @@ static void ps2_mouse_send_packet(PS2MouseState *s) } static void ps2_mouse_event(void *opaque, -int dx, int dy, int dz, int buttons_state) +
[Qemu-devel] [PATCH 3/5] Pass hwheel events from the front-ends
SDL seems to report hwheel events as SDL_BUTTON_X1 and SDL_BUTTON_X2. VNC I am guessing is similar, and online docs indicate that Cocoa reports hwheel deltas in deltaX for NSScrollWheel. Signed-off-by: Brad Jorsch ano...@users.sourceforge.net --- cocoa.m |2 +- sdl.c | 12 ++-- vnc.c | 11 --- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/cocoa.m b/cocoa.m index c247833..afc1b5f 100644 --- a/cocoa.m +++ b/cocoa.m @@ -649,7 +649,7 @@ static int cocoa_keycode_to_qemu(int keycode) break; case NSScrollWheel: if (isTabletEnabled || isMouseGrabed) { -kbd_mouse_event(0, 0, -[event deltaY], 0, 0); +kbd_mouse_event(0, 0, -[event deltaY], -[event deltaX], 0); } else { [NSApp sendEvent:event]; } diff --git a/sdl.c b/sdl.c index 616a7eb..f6fabf1 100644 --- a/sdl.c +++ b/sdl.c @@ -700,8 +700,9 @@ static void sdl_refresh(DisplayState *ds) sdl_grab_start(); } } else { -int dz; +int dz, dw; dz = 0; +dw = 0; if (ev-type == SDL_MOUSEBUTTONDOWN) { buttonstate |= SDL_BUTTON(bev-button); } else { @@ -714,7 +715,14 @@ static void sdl_refresh(DisplayState *ds) dz = 1; } #endif -sdl_send_mouse_event(0, 0, dz, 0, bev-x, bev-y, +#ifdef SDL_BUTTON_X1 +if (bev-button == SDL_BUTTON_X1 ev-type == SDL_MOUSEBUTTONDOWN) { +dw = -1; +} else if (bev-button == SDL_BUTTON_X2 ev-type == SDL_MOUSEBUTTONDOWN) { +dw = 1; +} +#endif +sdl_send_mouse_event(0, 0, dz, dw, bev-x, bev-y, buttonstate); } } diff --git a/vnc.c b/vnc.c index 332c14a..c193963 100644 --- a/vnc.c +++ b/vnc.c @@ -1275,6 +1275,7 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y) { int buttons = 0; int dz = 0; +int dw = 0; if (button_mask 0x01) buttons |= MOUSE_EVENT_LBUTTON; @@ -1286,23 +1287,27 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y) dz = -1; if (button_mask 0x10) dz = 1; +if (button_mask 0x20) +dw = -1; +if (button_mask 0x40) +dw = 1; if (vs-absolute) { kbd_mouse_event(ds_get_width(vs-ds) 1 ? x * 0x7FFF / (ds_get_width(vs-ds) - 1) : 0x4000, ds_get_height(vs-ds) 1 ? y * 0x7FFF / (ds_get_height(vs-ds) - 1) : 0x4000, -dz, 0, buttons); +dz, dw, buttons); } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) { x -= 0x7FFF; y -= 0x7FFF; -kbd_mouse_event(x, y, dz, 0, buttons); +kbd_mouse_event(x, y, dz, dw, buttons); } else { if (vs-last_x != -1) kbd_mouse_event(x - vs-last_x, y - vs-last_y, -dz, 0, buttons); +dz, dw, buttons); vs-last_x = x; vs-last_y = y; } -- 1.7.1
[Qemu-devel] [PATCH 4/5] Add a horizontal wheel to the USB mouse and tablet
Adjust the USB report descriptors to indicate that the mouse and tablet have horizontal wheels, and then report the delta when polled. Signed-off-by: Brad Jorsch ano...@users.sourceforge.net --- hw/usb-hid.c | 44 1 files changed, 36 insertions(+), 8 deletions(-) diff --git a/hw/usb-hid.c b/hw/usb-hid.c index deb4731..15cc2a1 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -44,7 +44,7 @@ #define USB_KEYBOARD 3 typedef struct USBMouseState { -int dx, dy, dz, buttons_state; +int dx, dy, dz, dw, buttons_state; int x, y; int mouse_grabbed; QEMUPutMouseEntry *eh_entry; @@ -137,14 +137,14 @@ static const uint8_t qemu_mouse_config_descriptor[] = { 0x00,/* u8 country_code */ 0x01,/* u8 num_descriptors */ 0x22,/* u8 type; Report */ -52, 0, /* u16 len */ +67, 0, /* u16 len */ /* one endpoint (status change endpoint) */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* u8 ep_bmAttributes; Interrupt */ - 0x04, 0x00, /* u16 ep_wMaxPacketSize; */ + 0x05, 0x00, /* u16 ep_wMaxPacketSize; */ 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ }; @@ -192,14 +192,14 @@ static const uint8_t qemu_tablet_config_descriptor[] = { 0x00,/* u8 country_code */ 0x01,/* u8 num_descriptors */ 0x22,/* u8 type; Report */ -74, 0, /* u16 len */ +93, 0, /* u16 len */ /* one endpoint (status change endpoint) */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* u8 ep_bmAttributes; Interrupt */ - 0x08, 0x00, /* u16 ep_wMaxPacketSize; */ + 0x09, 0x00, /* u16 ep_wMaxPacketSize; */ 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ }; @@ -284,6 +284,13 @@ static const uint8_t qemu_mouse_hid_report_descriptor[] = { 0x75, 0x08,/* Report Size (8) */ 0x95, 0x03,/* Report Count (3) */ 0x81, 0x06,/* Input (Data, Variable, Relative) */ +0x05, 0x0c,/* Usage Page (Consumer Devices) */ +0x0a, 0x38, 0x02, /* Usage (AC Pan) */ +0x15, 0x81,/* Logical Minimum (-0x7f) */ +0x25, 0x7f,/* Logical Maximum (0x7f) */ +0x75, 0x08,/* Report Size (8) */ +0x95, 0x01,/* Report Count (1) */ +0x81, 0x06,/* Input (Data, Variable, Relative) */ 0xc0, /* End Collection */ 0xc0, /* End Collection */ }; @@ -324,6 +331,15 @@ static const uint8_t qemu_tablet_hid_report_descriptor[] = { 0x75, 0x08,/* Report Size (8) */ 0x95, 0x01,/* Report Count (1) */ 0x81, 0x06,/* Input (Data, Variable, Relative) */ +0x05, 0x0c,/* Usage Page (Consumer Devices) */ +0x0a, 0x38, 0x02, /* Usage (AC Pan) */ +0x15, 0x81,/* Logical Minimum (-0x7f) */ +0x25, 0x7f,/* Logical Maximum (0x7f) */ +0x35, 0x00,/* Physical Minimum (same as logical) */ +0x45, 0x00,/* Physical Maximum (same as logical) */ +0x75, 0x08,/* Report Size (8) */ +0x95, 0x01,/* Report Count (1) */ +0x81, 0x06,/* Input (Data, Variable, Relative) */ 0xc0, /* End Collection */ 0xc0, /* End Collection */ }; @@ -423,6 +439,7 @@ static void usb_mouse_event(void *opaque, s-dx += dx1; s-dy += dy1; s-dz += dz1; +s-dw += dw1; s-buttons_state = buttons_state; usb_hid_changed(hs); @@ -437,6 +454,7 @@ static void usb_tablet_event(void *opaque, s-x = x; s-y = y; s-dz += dz; +s-dw += dw; s-buttons_state = buttons_state; usb_hid_changed(hs); @@ -508,7 +526,7 @@ static inline int int_clamp(int val, int vmin, int vmax) static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len) { -int dx, dy, dz, b, l; +int dx, dy, dz, dw, b, l; USBMouseState *s = hs-ptr; if (!s-mouse_grabbed) { @@ -519,10 +537,12 @@ static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len) dx = int_clamp(s-dx, -127, 127); dy = int_clamp(s-dy, -127, 127); dz = int_clamp(s-dz, -127, 127); +dw = int_clamp(s-dw, -127, 127); s-dx -= dx; s-dy -= dy; s-dz -= dz; +s-dw -= dw; /* Appears we have to invert the wheel direction */ dz = 0 - dz; @@ -544,12 +564,15 @@
[Qemu-devel] [PATCH 5/5] Add a horizontal wheel to the exps/2 mouse
Have the emulated mouse report horizontal wheel events when in exps/2 mode. Signed-off-by: Brad Jorsch ano...@users.sourceforge.net --- hw/ps2.c | 56 +++- 1 files changed, 43 insertions(+), 13 deletions(-) diff --git a/hw/ps2.c b/hw/ps2.c index db5605d..09e4365 100644 --- a/hw/ps2.c +++ b/hw/ps2.c @@ -105,7 +105,9 @@ typedef struct { int mouse_dx; /* current values, needed for 'poll' mode */ int mouse_dy; int mouse_dz; +int mouse_dw; uint8_t mouse_buttons; +uint8_t mouse_buttons_changed; } PS2MouseState; /* Table to convert from PC scancodes to raw scancodes. */ @@ -284,11 +286,12 @@ void ps2_keyboard_set_translation(void *opaque, int mode) static void ps2_mouse_send_packet(PS2MouseState *s) { unsigned int b; -int dx1, dy1, dz1; +int dx1, dy1, dz1, dw1; dx1 = s-mouse_dx; dy1 = s-mouse_dy; dz1 = s-mouse_dz; +dw1 = s-mouse_dw; /* XXX: increase range to 8 bits ? */ if (dx1 127) dx1 = 127; @@ -299,12 +302,17 @@ static void ps2_mouse_send_packet(PS2MouseState *s) else if (dy1 -127) dy1 = -127; b = 0x08 | ((dx1 0) 4) | ((dy1 0) 5) | (s-mouse_buttons 0x07); +s-mouse_buttons_changed = ~0x07; ps2_queue(s-common, b); ps2_queue(s-common, dx1 0xff); ps2_queue(s-common, dy1 0xff); /* extra byte for IMPS/2 or IMEX */ switch(s-mouse_type) { default: +/* Just ignore the wheels if not supported */ +s-mouse_dz = 0; +s-mouse_dw = 0; +s-mouse_buttons_changed = 0x07; break; case 3: if (dz1 127) @@ -312,13 +320,29 @@ static void ps2_mouse_send_packet(PS2MouseState *s) else if (dz1 -127) dz1 = -127; ps2_queue(s-common, dz1 0xff); +s-mouse_dz -= dz1; +s-mouse_dw = 0; +s-mouse_buttons_changed = 0x07; break; case 4: -if (dz1 7) -dz1 = 7; -else if (dz1 -7) -dz1 = -7; -b = (dz1 0x0f) | ((s-mouse_buttons 0x18) 1); +/* This matches what the Linux kernel expects for exps/2 in + * drivers/input/mouse/psmouse-base.c. */ +if (dw1 != 0) { +if (dw1 31) +dw1 = 31; +else if (dw1 -31) +dw1 = -31; +b = (dw1 0x3f) | 0x40; +s-mouse_dw -= dw1; +} else { +if (dz1 7) +dz1 = 7; +else if (dz1 -7) +dz1 = -7; +b = (dz1 0x0f) | ((s-mouse_buttons 0x18) 1); +s-mouse_dz -= dz1; +s-mouse_buttons_changed = 0x07; +} ps2_queue(s-common, b); break; } @@ -326,7 +350,6 @@ static void ps2_mouse_send_packet(PS2MouseState *s) /* update deltas */ s-mouse_dx -= dx1; s-mouse_dy -= dy1; -s-mouse_dz -= dz1; } static void ps2_mouse_event(void *opaque, @@ -341,11 +364,13 @@ static void ps2_mouse_event(void *opaque, s-mouse_dx += dx; s-mouse_dy -= dy; s-mouse_dz += dz; +s-mouse_dw -= dw; +s-mouse_buttons_changed |= s-mouse_buttons ^ buttons_state; +s-mouse_buttons = buttons_state; /* XXX: SDL sometimes generates nul events: we delete them */ if (s-mouse_dx == 0 s-mouse_dy == 0 s-mouse_dz == 0 -s-mouse_buttons == buttons_state) +s-mouse_dw == 0 s-mouse_buttons_changed == 0) return; -s-mouse_buttons = buttons_state; if (!(s-mouse_status MOUSE_STATUS_REMOTE) (s-common.queue.count (PS2_QUEUE_SIZE - 16))) { @@ -353,7 +378,8 @@ static void ps2_mouse_event(void *opaque, /* if not remote, send event. Multiple events are sent if too big deltas */ ps2_mouse_send_packet(s); -if (s-mouse_dx == 0 s-mouse_dy == 0 s-mouse_dz == 0) +if (s-mouse_dx == 0 s-mouse_dy == 0 s-mouse_dz == 0 +s-mouse_dw == 0 s-mouse_buttons_changed == 0) break; } } @@ -525,7 +551,9 @@ static void ps2_mouse_reset(void *opaque) s-mouse_dx = 0; s-mouse_dy = 0; s-mouse_dz = 0; +s-mouse_dw = 0; s-mouse_buttons = 0; +s-mouse_buttons_changed = 0; } static const VMStateDescription vmstate_ps2_common = { @@ -569,9 +597,9 @@ static const VMStateDescription vmstate_ps2_keyboard = { static const VMStateDescription vmstate_ps2_mouse = { .name = ps2mouse, -.version_id = 2, -.minimum_version_id = 2, -.minimum_version_id_old = 2, +.version_id = 3, +.minimum_version_id = 3, +.minimum_version_id_old = 3, .fields = (VMStateField []) { VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State), VMSTATE_UINT8(mouse_status, PS2MouseState), @@ -583,7 +611,9 @@ static const VMStateDescription vmstate_ps2_mouse = { VMSTATE_INT32(mouse_dx, PS2MouseState),
[Qemu-devel] [RFC] [PATCH 0/5] Add horizontal wheel support to mice, where possible
The emulated mice should emulate a horizontal wheel when possible. This patch series does that for the USB mouse and tablet and the ExPS/2 mouse. As far as I can tell the vmmouse protocol doesn't handle a horizontal wheel, and I have no idea if emulating a wheel might make sense for any of the other mouse types. I've tested this using the SDL interface and an Ububtu 10.04 cd image; xev reports the correct events for all three devices, and a gedit window with sufficient text to create scrollbars scrolls correctly with both mice (didn't test the tablet). More testing would be good. See also Debian bug #579968.[1] [1] http://bugs.debian.org/579968