Re: [Qemu-devel] [RFC][PATCH 08/14 v4] introduce a new monitor command 'dump' to dump guest's memory
At 01/12/2012 09:49 PM, Luiz Capitulino Wrote: On Wed, 11 Jan 2012 08:59:24 +0800 Wen Congyang we...@cn.fujitsu.com wrote: At 01/10/2012 09:30 PM, Luiz Capitulino Wrote: On Wed, 04 Jan 2012 14:11:01 +0800 Wen Congyang we...@cn.fujitsu.com wrote: Signed-off-by: Wen Congyang we...@cn.fujitsu.com --- Makefile.target |8 +- dump.c | 588 +++ dump.h |4 + hmp-commands.hx | 16 ++ monitor.c |3 + qmp-commands.hx | 26 +++ 6 files changed, 641 insertions(+), 4 deletions(-) create mode 100644 dump.c diff --git a/Makefile.target b/Makefile.target index 29562ad..f7cc2b9 100644 --- a/Makefile.target +++ b/Makefile.target @@ -110,7 +110,7 @@ $(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \ elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \ - user-exec.o $(oslib-obj-y) + user-exec.o $(oslib-obj-y) dump.o obj-$(TARGET_HAS_BFLT) += flatload.o @@ -148,7 +148,7 @@ LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e00 LIBS+=-lmx obj-y = main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o \ -gdbstub.o user-exec.o +gdbstub.o user-exec.o dump.o obj-i386-y += ioport-user.o @@ -170,7 +170,7 @@ $(call set-vpath, $(SRC_PATH)/bsd-user) QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH) obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \ -gdbstub.o uaccess.o user-exec.o +gdbstub.o uaccess.o user-exec.o dump.o obj-i386-y += ioport-user.o @@ -186,7 +186,7 @@ endif #CONFIG_BSD_USER # System emulator target ifdef CONFIG_SOFTMMU -obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o +obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o dump.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly obj-$(CONFIG_NO_PCI) += pci-stub.o diff --git a/dump.c b/dump.c new file mode 100644 index 000..ab29a4c --- /dev/null +++ b/dump.c @@ -0,0 +1,588 @@ +/* + * QEMU dump + * + * Copyright Fujitsu, Corp. 2011 + * + * Authors: + * Wen Congyang we...@cn.fujitsu.com + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include qemu-common.h +#include unistd.h +#include elf.h +#include sys/procfs.h +#include cpu.h +#include cpu-all.h +#include targphys.h +#include monitor.h +#include kvm.h +#include dump.h +#include sysemu.h +#include bswap.h +#include memory_mapping.h + +#define CPU_CONVERT_TO_TARGET16(val) \ +({ \ +uint16_t _val = (val); \ +if (endian == ELFDATA2LSB) { \ +_val = cpu_to_le16(_val); \ +} else {\ +_val = cpu_to_be16(_val); \ +} \ +_val; \ +}) + +#define CPU_CONVERT_TO_TARGET32(val) \ +({ \ +uint32_t _val = (val); \ +if (endian == ELFDATA2LSB) { \ +_val = cpu_to_le32(_val); \ +} else {\ +_val = cpu_to_be32(_val); \ +} \ +_val; \ +}) + +#define CPU_CONVERT_TO_TARGET64(val) \ +({ \ +uint64_t _val = (val); \ +if (endian == ELFDATA2LSB) { \ +_val = cpu_to_le64(_val); \ +} else {\ +_val = cpu_to_be64(_val); \ +} \ +_val; \ +}) + +enum { +DUMP_STATE_ERROR, +DUMP_STATE_SETUP, +DUMP_STATE_CANCELLED, +DUMP_STATE_ACTIVE, +DUMP_STATE_COMPLETED, +}; + +typedef struct DumpState { +ArchDumpInfo dump_info; +MemoryMappingList list; +int phdr_num; +int state; +char *error; +Monitor *mon; +int fd; +target_phys_addr_t memory_offset; +} DumpState; + +static DumpState *dump_get_current(void) +{ +static DumpState current_dump = { +.state = DUMP_STATE_SETUP, +}; + +return current_dump; +} + +static int dump_cleanup(DumpState *s) +{ +int ret = 0; + +free_memory_mapping_list(s-list); +if (s-fd != -1) { +close(s-fd); +s-fd = -1; +} + +return ret; +} + +static void dump_error(DumpState *s, const char *reason) +{ +s-state = DUMP_STATE_ERROR; +s-error = g_strdup(reason); +dump_cleanup(s); +} + +static inline int cpuid(CPUState *env) +{ +#if defined(CONFIG_USER_ONLY) defined(CONFIG_USE_NPTL) +return env-host_tid; +#else +return env-cpu_index + 1; +#endif +} + +static int write_elf64_header(DumpState *s) +{ +Elf64_Ehdr elf_header; +int ret; +int endian = s-dump_info.d_endian; + +memset(elf_header, 0, sizeof(Elf64_Ehdr)); +memcpy(elf_header, ELFMAG, 4); +elf_header.e_ident[EI_CLASS] = ELFCLASS64; +
Re: [Qemu-devel] throwing away translated code on CPU reset
On 13 January 2012 07:55, 陳韋任 che...@iis.sinica.edu.tw wrote: On Thu, Jan 12, 2012 at 02:00:38PM +, Peter Maydell wrote: When doing TCG code translation, the target-foo translate.c code is allowed to bake assumptions into the generated code from the current values of various fields in the CPUState. This then imposes the requirement that if the field is changed then tb_flush must be called to throw away the now-incorrect generated code. However, cpu_reset() changes (unsurprisingly) lots of fields in the CPUState, but it doesn't call tb_flush()... I dig what tlb_flush does further and think maybe we don't need to call tb_flush when tlb_flush is called. First, look at tlb_flush (exec.c). It clears env's tb_jmp_cache which use GHA as an index to search if there is a translated code. Since tb_jmp_cache is reset now, QEMU is forced to call tb_find_slow which uses GPA as the index. In tb_find_slow's for loop, it compares hit TranslationBlock's various fields with current values. To be more specific, static TranslationBlock *tb_find_slow(...) { for(;;) { tb = *ptb1; if (!tb) goto not_found; if (tb-pc == pc --- Here tb-page_addr[0] == phys_page1 tb-cs_base == cs_base tb-flags == flags) { } } } What do you think? This is true, but the translated code may have assumptions about fields which are not encoded in tb_flags, if it is handling those fields with the tb_flush if field changes strategy (eg on ARM env-teecr and others). -- PMM
[Qemu-devel] [PATCH] hw/9pfs: Fix crash when mounting with synthfs
From: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com Some Fsdriver backend don't have fs_root. So check for that in migrate message. Signed-off-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com --- hw/9pfs/virtio-9p.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index e6ba6ba..dfe2025 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -986,7 +986,7 @@ static void v9fs_attach(void *opaque) s-root_fid = fid; /* disable migration */ error_set(s-migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION, - s-ctx.fs_root, s-tag); + s-ctx.fs_root ? s-ctx.fs_root : NULL, s-tag); migrate_add_blocker(s-migration_blocker); out: put_fid(pdu, fidp); -- 1.7.8.1.362.g5d6df
Re: [Qemu-devel] [PATCH][v8] megasas: LSI Megaraid SAS HBA emulation
On Thu, Jan 12, 2012 at 03:45:59PM +0100, Paolo Bonzini wrote: On 01/12/2012 11:43 AM, Hannes Reinecke wrote: +# hw/megasas.c +disable megasas_init_firmware(int xfer_len, uint64_t pa) xfer len %d pa % PRIx64 +disable megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) queue at % PRIx64 len %d head % PRIx64 tail % PRIx64 flags %x +megasas_initq_map_failed(int frame) scmd %d: failed to map queue +megasas_initq_mismatch(int queue_len, int fw_cmds) queue size %d max fw cmds %d +disable megasas_qf_found(unsigned int index, uint64_t pa) found mapped frame %x pa % PRIx64 +disable megasas_qf_new(unsigned int index, void *cmd) return new frame %x cmd %p +megasas_qf_failed(unsigned long pa) all frames busy for frame %lx +disable megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int tail, int busy) enqueue frame %x count %d countext % PRIx64 tail %x busy %d +disable megasas_qf_update(unsigned int head, unsigned int busy) update reply queue head %x busy %d +disable megasas_qf_dequeue(unsigned int index) dequeue frame %x +disable megasas_qf_map_failed(int cmd, unsigned long frame) scmd %d: frame %lu +disable megasas_qf_complete_noirq(uint64_t context) context % PRIx64 +disable megasas_qf_complete(uint64_t context, unsigned int tail, unsigned int offset, int busy, unsigned int doorbell) context % PRIx64 tail %x offset %d busy %d doorbell %x +disable megasas_handle_frame(const char *cmd, uint64_t addr, uint64_t context, uint32_t count) MFI cmd %s addr % PRIx64 context % PRIx64 count %d +megasas_frame_busy(uint64_t addr) frame % PRIx64 busy +megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) scmd %d: Unhandled MFI cmd %x +disable megasas_handle_scsi(const char *frame, const char *desc, int dev, int lun, void *sdev, unsigned long size) %s %s dev %x/%x sdev %p xfer %lu +disable megasas_scsi_target_not_present(const char *frame, const char *desc, int dev, int lun) %s %s dev %x/%x target not present +megasas_scsi_invalid_cdb_len(const char *frame, const char *desc, int dev, int lun, int len) %s %s dev %x/%x invalid cdb len %d +megasas_scsi_overflow(int cmd, const char *dir, int bytes, int len) scmd %d: %s %d of %d bytes +disable megasas_scsi_underflow(int cmd, const char *dir, int bytes, int len) scmd %d: %s %d of %d bytes +megasas_scsi_req_alloc_failed(const char *frame, int dev, int lun) %s dev %x/%x req allocation failed +disable megasas_scsi_start(int cmd, const char *desc, int len) scmd %d: %s %d bytes of data +disable megasas_scsi_nodata(int cmd) scmd %d: no data to be transferred +disable megasas_scsi_complete(int cmd, uint32_t status, int len, int xfer) scmd %d: finished with status %x, len %u/%u +disable megasas_command_complete(int cmd, uint32_t status) scmd %d: command completed, status %x +disable megasas_handle_io(int cmd, const char *frame, int dev, int lun, unsigned long lba, unsigned long count) scmd %d: %s dev %x/%x lba %lx count %lu +disable megasas_io_target_not_present(int cmd, const char *frame, int dev, int lun) scmd %d: %s dev %x/%x LUN not present +disable megasas_io_start(int cmd, const char *dir, unsigned long lba, unsigned long count, unsigned long len) scmd %d: %s start LBA %lx %lu blocks (%lu bytes) +disable megasas_io_complete(int cmd, uint32_t len) scmd %d: %d bytes completed +disable megasas_io_copy(int cmd, const char *dir, int bytes, int len, unsigned long offset) scmd %d: %s %d of %d bytes, iov offset %lu +disable megasas_io_continue(int cmd, int bytes) scmd %d: %d bytes left +megasas_iovec_map_failed(int cmd, int index, unsigned long iov_size) scmd %d: iovec %d size %lu +megasas_iovec_sgl_overflow(int cmd, int index, int limit) scmd %d: iovec count %d limit %d +megasas_iovec_sgl_underflow(int cmd, int index) scmd %d: iovec count %d +megasas_iovec_sgl_invalid(int cmd, int index, uint64_t pa, uint32_t len) scmd %d: invalid sgl element %d pa % PRIx64 len %u +megasas_iovec_len(int cmd, const char *desc, int len, int limit) scmd %d: iovec %s len %d limit %d +disable megasas_handle_dcmd(int cmd, int opcode) scmd %d: MFI DCMD opcode %x +disable megasas_finish_dcmd(int cmd, int size) scmd %d: MFI DCMD wrote %d bytes +megasas_dcmd_req_alloc_failed(int cmd, const char *desc) scmd %d: %s alloc failed +disable megasas_dcmd_internal_submit(int cmd, const char *desc, int dev) scmd %d: %s to dev %d +disable megasas_dcmd_internal_finish(int cmd, int opcode, int lun) scmd %d: DCMD finish internal cmd %x lun %d +megasas_dcmd_internal_invalid(int cmd, int opcode) scmd %d: Invalid internal DCMD %x +megasas_dcmd_unhandled(int cmd, int opcode, int len) scmd %d: opcode %x, len %d +disable megasas_dcmd_zero_sge(int cmd) scmd %d: zero DCMD sge count +megasas_dcmd_invalid_sge(int cmd, int count) scmd %d: invalid DCMD sge count %d +megasas_dcmd_map_failed(int cmd) scmd %d: Failed to
Re: [Qemu-devel] [PATCH v3 8/8] prep: Use i82378 PCI-ISA bridge for 'prep' machine
On 2012-01-13 04:09, Andreas Färber wrote: Speaker I/O, ISA bus, i8259 PIC, RTC and DMA are no longer set up individually by the machine. Effectively, no-op speaker I/O is replaced by pcspk; PIT and i82374 DMA are introduced. Signed-off-by: Hervé Poussineau hpous...@reactos.org Remove related dead, alternative code. Access i8259 IRQs via ISA bus to resolve cyclic dependency with PCI host bridge. Signed-off-by: Andreas Färber andreas.faer...@web.de Cc: Alexander Graf ag...@suse.de Cc: Jan Kiszka jan.kis...@siemens.com --- hw/ppc_prep.c | 54 +++--- 1 files changed, 11 insertions(+), 43 deletions(-) diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 747539f..9485d45 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -83,37 +83,9 @@ static const int ide_irq[2] = { 13, 13 }; static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 }; static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; -//static ISADevice *pit; - /* ISA IO ports bridge */ #define PPC_IO_BASE 0x8000 -#if 0 -/* Speaker port 0x61 */ -static int speaker_data_on; -static int dummy_refresh_clock; -#endif - -static void speaker_ioport_write (void *opaque, uint32_t addr, uint32_t val) -{ -#if 0 -speaker_data_on = (val 1) 1; -pit_set_gate(pit, 2, val 1); -#endif -} - -static uint32_t speaker_ioport_read (void *opaque, uint32_t addr) -{ -#if 0 -int out; -out = pit_get_out(pit, 2, qemu_get_clock_ns(vm_clock)); -dummy_refresh_clock ^= 1; -return (speaker_data_on 1) | pit_get_gate(pit, 2) | (out 5) | -(dummy_refresh_clock 4); -#endif -return 0; -} - /* PCI intack register */ /* Read-only register (?) */ static void PPC_intack_write (void *opaque, target_phys_addr_t addr, @@ -526,6 +498,7 @@ static void ppc_prep_init (ram_addr_t ram_size, SysBusDevice *sys; PCIHostState *pcihost; PCIBus *pci_bus; +PCIDevice *pci; ISABus *isa_bus; qemu_irq *i8259; qemu_irq *cpu_exit_irq; @@ -629,13 +602,9 @@ static void ppc_prep_init (ram_addr_t ram_size, } } -isa_mem_base = 0xc000; if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { hw_error(Only 6xx bus is supported on PREP machine\n); } -/* Hmm, prep has no pci-isa bridge ??? */ -isa_bus = isa_bus_new(NULL, get_system_io()); -i8259 = i8259_init(isa_bus, first_cpu-irq_inputs[PPC6xx_INPUT_INT]); dev = qdev_create(NULL, raven-pcihost); sys = sysbus_from_qdev(dev); @@ -648,13 +617,21 @@ static void ppc_prep_init (ram_addr_t ram_size, fprintf(stderr, Couldn't create PCI host controller.\n); exit(1); } + +/* PCI - ISA bridge */ +pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), i82378); +cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); +qdev_connect_gpio_out(pci-qdev, 0, + first_cpu-irq_inputs[PPC6xx_INPUT_INT]); +qdev_connect_gpio_out(pci-qdev, 1, *cpu_exit_irq); +isa_bus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(pci-qdev, isa.0)); + +i8259 = isa_bus-irqs; I think this is unneeded. You only access i8259[8] later on for initializing the m48t59. But that one should be creatable as ISA device now (m48t59_init_isa), no? Please check. Jan -- Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
Re: [Qemu-devel] throwing away translated code on CPU reset
On Thu, Jan 12, 2012 at 02:00:38PM +, Peter Maydell wrote: When doing TCG code translation, the target-foo translate.c code is allowed to bake assumptions into the generated code from the current values of various fields in the CPUState. This then imposes the requirement that if the field is changed then tb_flush must be called to throw away the now-incorrect generated code. However, cpu_reset() changes (unsurprisingly) lots of fields in the CPUState, but it doesn't call tb_flush()... I dig what tlb_flush does further and think maybe we don't need to call tb_flush when tlb_flush is called. First, look at tlb_flush (exec.c). It clears env's tb_jmp_cache which use GHA as an index to search if there is a translated code. Since tb_jmp_cache is reset now, QEMU is forced to call tb_find_slow which uses GPA as the index. In tb_find_slow's for loop, it compares hit TranslationBlock's various fields with current values. To be more specific, static TranslationBlock *tb_find_slow(...) { for(;;) { tb = *ptb1; if (!tb) goto not_found; if (tb-pc == pc --- Here tb-page_addr[0] == phys_page1 tb-cs_base == cs_base tb-flags == flags) { } } } What do you think? Regards, chenwj -- Wei-Ren Chen (陳韋任) Computer Systems Lab, Institute of Information Science, Academia Sinica, Taiwan (R.O.C.) Tel:886-2-2788-3799 #1667 Homepage: http://people.cs.nctu.edu.tw/~chenwj
[Qemu-devel] [PATCH v5 09/15] qmp: add query-block-jobs
Add query-block-jobs, which shows the progress of ongoing block device operations. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- blockdev.c | 33 + hmp.c| 36 hmp.h|1 + monitor.c|7 +++ qapi-schema.json | 32 qmp-commands.hx |6 ++ 6 files changed, 115 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index 35de3bc..4549c9e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -989,3 +989,36 @@ void qmp_block_job_cancel(const char *device, Error **errp) trace_qmp_block_job_cancel(job); block_job_cancel(job); } + +static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) +{ +BlockJobInfoList **prev = opaque; +BlockJob *job = bs-job; + +if (job) { +BlockJobInfoList *elem; +BlockJobInfo *info = g_new(BlockJobInfo, 1); +*info = (BlockJobInfo){ +.type = g_strdup(job-job_type-job_type), +.device = g_strdup(bdrv_get_device_name(bs)), +.len= job-len, +.offset = job-offset, +.speed = job-speed, +}; + +elem = g_new0(BlockJobInfoList, 1); +elem-value = info; + +(*prev)-next = elem; +*prev = elem; +} +} + +BlockJobInfoList *qmp_query_block_jobs(Error **errp) +{ +/* Dummy is a fake list element for holding the head pointer */ +BlockJobInfoList dummy = {}; +BlockJobInfoList *prev = dummy; +bdrv_iterate(do_qmp_query_block_jobs_one, prev); +return dummy.next; +} diff --git a/hmp.c b/hmp.c index 851885b..76e89f8 100644 --- a/hmp.c +++ b/hmp.c @@ -507,6 +507,42 @@ void hmp_info_pci(Monitor *mon) qapi_free_PciInfoList(info); } +void hmp_info_block_jobs(Monitor *mon) +{ +BlockJobInfoList *list; +Error *err = NULL; + +list = qmp_query_block_jobs(err); +assert(!err); + +if (!list) { +monitor_printf(mon, No active jobs\n); +return; +} + +while (list) { +if (strcmp(list-value-type, stream) == 0) { +monitor_printf(mon, Streaming device %s: Completed % PRId64 +of % PRId64 bytes, speed limit % PRId64 +bytes/s\n, + list-value-device, + list-value-offset, + list-value-len, + list-value-speed); +} else { +monitor_printf(mon, Type %s, device %s: Completed % PRId64 +of % PRId64 bytes, speed limit % PRId64 +bytes/s\n, + list-value-type, + list-value-device, + list-value-offset, + list-value-len, + list-value-speed); +} +list = list-next; +} +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index 0ad2004..23bfca2 100644 --- a/hmp.h +++ b/hmp.h @@ -32,6 +32,7 @@ void hmp_info_vnc(Monitor *mon); void hmp_info_spice(Monitor *mon); void hmp_info_balloon(Monitor *mon); void hmp_info_pci(Monitor *mon); +void hmp_info_block_jobs(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 01850ca..f96a296 100644 --- a/monitor.c +++ b/monitor.c @@ -2483,6 +2483,13 @@ static mon_cmd_t info_cmds[] = { .mhandler.info = hmp_info_blockstats, }, { +.name = block-jobs, +.args_type = , +.params = , +.help = show progress of ongoing block device operations, +.mhandler.info = hmp_info_block_jobs, +}, +{ .name = registers, .args_type = , .params = , diff --git a/qapi-schema.json b/qapi-schema.json index 3d23ce2..b4f6b15 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -845,6 +845,38 @@ { 'command': 'query-pci', 'returns': ['PciInfo'] } ## +# @BlockJobInfo: +# +# Information about a long-running block device operation. +# +# @type: the job type ('stream' for image streaming) +# +# @device: the block device name +# +# @len: the maximum progress value +# +# @offset: the current progress value +# +# @speed: the rate limit, bytes per second +# +# Since: 1.1 +## +{ 'type': 'BlockJobInfo', + 'data': {'type': 'str', 'device': 'str', 'len': 'int', + 'offset': 'int', 'speed': 'int'} } + +## +# @query-block-jobs: +# +# Return information about long-running block device operations. +# +# Returns: a list of @BlockJobInfo for each active block job +# +# Since: 1.1 +## +{ 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] } + +## # @quit: # # This command will cause the
[Qemu-devel] [PATCH] do not chdir(/) in qemu-nbd
When qemu-nbd becomes a daemon it calls daemon(3) with nochdir=0, so daemon(3) changes current directory to /. But at this time, qemu-nbd did not open any user-specified files yet, so by changing current directory, all non-absolute paths becomes wrong. The solution is to pass nochdir=1 to daemon(3) function. This patch is applicable for -stable. Signed-Off-By: Michael Tokarev m...@tls.msk.ru --- qemu-nbd.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index eb61c33..d84e2a7 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -429,7 +429,7 @@ int main(int argc, char **argv) pid = fork(); if (pid == 0) { close(stderr_fd[0]); -ret = qemu_daemon(0, 0); +ret = qemu_daemon(1, 0); /* Temporarily redirect stderr to the parent's pipe... */ dup2(stderr_fd[1], STDERR_FILENO); -- 1.7.2.5
Re: [Qemu-devel] [PATCH 0/2][RFC] postcopy migration: Linux char device for postcopy
Yes we plan to release patch as soon as we cleaned up the code and we get the green light from our company ( and sadly it can take month on that point..) On 13 January 2012 01:31, Takuya Yoshikawa yoshikawa.tak...@oss.ntt.co.jp wrote: (2012/01/13 10:09), Benoit Hudzia wrote: Hi, Sorry to jump to hijack the thread like that , however i would like to just to inform you that we recently achieve a milestone out of the research project I'm leading. We enhanced KVM in order to deliver post copy live migration using RDMA at kernel level. Few point on the architecture of the system : * RDMA communication engine in kernel ( you can use soft iwarp or soft ROCE if you don't have hardware acceleration, however we also support standard RDMA enabled NIC) . * Naturally Page are transferred with Zerop copy protocol * Leverage the async page fault system. * Pre paging / faulting * No context switch as everything is handled within kernel and using the page fault system. * Hybrid migration ( pre + post copy) available * Rely on an independent Kernel Module * No modification to the KVM kernel Module * Minimal Modification to the Qemu-Kvm code * We plan to add the page prioritization algo in order to optimise the pre paging algo and background transfer You can learn a little bit more and see a demo here: http://tinyurl.com/8xa2bgl I hope to be able to provide more detail on the design soon. As well as more concrete demo of the system ( live migration of VM running large enterprise apps such as ERP or In memory DB) Note: this is just a step stone as the post copy live migration mainly enable us to validate the architecture design and code. Do you have any plan to send the patch series of your implementation? Takuya -- The production of too many useful things results in too many useless people
[Qemu-devel] [PATCH v5 15/15] test: add image streaming test cases
python test-stream.py Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- test-stream.py | 208 1 files changed, 208 insertions(+), 0 deletions(-) create mode 100644 test-stream.py diff --git a/test-stream.py b/test-stream.py new file mode 100644 index 000..16cbe5d --- /dev/null +++ b/test-stream.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +import unittest +import subprocess +import re +import os +import sys; sys.path.append('QMP/') +import qmp + +def qemu_img(*args): +devnull = open('/dev/null', 'r+') +return subprocess.call(['./qemu-img'] + list(args), stdin=devnull, stdout=devnull) + +def qemu_io(*args): +args = ['./qemu-io'] + list(args) +return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0] + +class VM(object): +def __init__(self): +self._monitor_path = '/tmp/qemu-mon.%d' % os.getpid() +self._qemu_log_path = '/tmp/qemu-log.%d' % os.getpid() +self._args = ['x86_64-softmmu/qemu-system-x86_64', + '-chardev', 'socket,id=mon,path=' + self._monitor_path, + '-mon', 'chardev=mon,mode=control', '-nographic'] +self._num_drives = 0 + +def add_drive(self, path, opts=''): +options = ['if=virtio', + 'cache=none', + 'file=%s' % path, + 'id=drive%d' % self._num_drives] +if opts: +options.append(opts) + +self._args.append('-drive') +self._args.append(','.join(options)) +self._num_drives += 1 +return self + +def launch(self): +devnull = open('/dev/null', 'rb') +qemulog = open(self._qemu_log_path, 'wb') +self._qmp = qmp.QEMUMonitorProtocol(self._monitor_path, server=True) +self._popen = subprocess.Popen(self._args, stdin=devnull, stdout=qemulog, + stderr=subprocess.STDOUT) +self._qmp.accept() + +def shutdown(self): +self._qmp.cmd('quit') +self._popen.wait() +os.remove(self._monitor_path) +os.remove(self._qemu_log_path) + +def qmp(self, cmd, **args): +return self._qmp.cmd(cmd, args=args) + +def get_qmp_events(self, wait=False): +events = self._qmp.get_events(wait=wait) +self._qmp.clear_events() +return events + +index_re = re.compile(r'([^\[]+)\[([^\]]+)\]') + +class QMPTestCase(unittest.TestCase): +def dictpath(self, d, path): +Traverse a path in a nested dict +for component in path.split('/'): +m = index_re.match(component) +if m: +component, idx = m.groups() +idx = int(idx) + +if not isinstance(d, dict) or component not in d: +self.fail('failed path traversal for %s in %s' % (path, str(d))) +d = d[component] + +if m: +if not isinstance(d, list): +self.fail('path component %s in %s is not a list in %s' % (component, path, str(d))) +try: +d = d[idx] +except IndexError: +self.fail('invalid index %s in path %s in %s' % (idx, path, str(d))) +return d + +def assert_qmp(self, d, path, value): +result = self.dictpath(d, path) +self.assertEqual(result, value, 'values not equal %s and %s' % (str(result), str(value))) + +def assert_no_active_streams(self): +result = self.vm.qmp('query-block-jobs') +self.assert_qmp(result, 'return', []) + +class TestSingleDrive(QMPTestCase): +image_len = 1 * 1024 * 1024 # MB + +def setUp(self): +qemu_img('create', 'backing.img', str(TestSingleDrive.image_len)) +qemu_img('create', '-f', 'qed', '-o', 'backing_file=backing.img', 'test.qed') +self.vm = VM().add_drive('test.qed') +self.vm.launch() + +def tearDown(self): +self.vm.shutdown() +os.remove('test.qed') +os.remove('backing.img') + +def test_stream(self): +self.assert_no_active_streams() + +result = self.vm.qmp('block_stream', device='drive0') +self.assert_qmp(result, 'return', {}) + +completed = False +while not completed: +for event in self.vm.get_qmp_events(wait=True): +if event['event'] == 'BLOCK_JOB_COMPLETED': +self.assert_qmp(event, 'data/type', 'stream') +self.assert_qmp(event, 'data/device', 'drive0') +self.assert_qmp(event, 'data/offset', self.image_len) +self.assert_qmp(event, 'data/len', self.image_len) +completed = True + +self.assert_no_active_streams() + +self.assertFalse('sectors not allocated' in qemu_io('-c', 'map', 'test.qed'), + 'image file not fully populated after streaming') + +def
Re: [Qemu-devel] [PATCH][v8] megasas: LSI Megaraid SAS HBA emulation
On 01/12/2012 07:04 PM, Stefan Hajnoczi wrote: On Thu, Jan 12, 2012 at 03:45:59PM +0100, Paolo Bonzini wrote: On 01/12/2012 11:43 AM, Hannes Reinecke wrote: +# hw/megasas.c +disable megasas_init_firmware(int xfer_len, uint64_t pa) xfer len %d pa % PRIx64 +disable megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) queue at % PRIx64 len %d head % PRIx64 tail % PRIx64 flags %x +megasas_initq_map_failed(int frame) scmd %d: failed to map queue +megasas_initq_mismatch(int queue_len, int fw_cmds) queue size %d max fw cmds %d +disable megasas_qf_found(unsigned int index, uint64_t pa) found mapped frame %x pa % PRIx64 +disable megasas_qf_new(unsigned int index, void *cmd) return new frame %x cmd %p +megasas_qf_failed(unsigned long pa) all frames busy for frame %lx +disable megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int tail, int busy) enqueue frame %x count %d countext % PRIx64 tail %x busy %d +disable megasas_qf_update(unsigned int head, unsigned int busy) update reply queue head %x busy %d +disable megasas_qf_dequeue(unsigned int index) dequeue frame %x +disable megasas_qf_map_failed(int cmd, unsigned long frame) scmd %d: frame %lu +disable megasas_qf_complete_noirq(uint64_t context) context % PRIx64 +disable megasas_qf_complete(uint64_t context, unsigned int tail, unsigned int offset, int busy, unsigned int doorbell) context % PRIx64 tail %x offset %d busy %d doorbell %x +disable megasas_handle_frame(const char *cmd, uint64_t addr, uint64_t context, uint32_t count) MFI cmd %s addr % PRIx64 context % PRIx64 count %d +megasas_frame_busy(uint64_t addr) frame % PRIx64 busy +megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) scmd %d: Unhandled MFI cmd %x +disable megasas_handle_scsi(const char *frame, const char *desc, int dev, int lun, void *sdev, unsigned long size) %s %s dev %x/%x sdev %p xfer %lu +disable megasas_scsi_target_not_present(const char *frame, const char *desc, int dev, int lun) %s %s dev %x/%x target not present +megasas_scsi_invalid_cdb_len(const char *frame, const char *desc, int dev, int lun, int len) %s %s dev %x/%x invalid cdb len %d +megasas_scsi_overflow(int cmd, const char *dir, int bytes, int len) scmd %d: %s %d of %d bytes +disable megasas_scsi_underflow(int cmd, const char *dir, int bytes, int len) scmd %d: %s %d of %d bytes +megasas_scsi_req_alloc_failed(const char *frame, int dev, int lun) %s dev %x/%x req allocation failed +disable megasas_scsi_start(int cmd, const char *desc, int len) scmd %d: %s %d bytes of data +disable megasas_scsi_nodata(int cmd) scmd %d: no data to be transferred +disable megasas_scsi_complete(int cmd, uint32_t status, int len, int xfer) scmd %d: finished with status %x, len %u/%u +disable megasas_command_complete(int cmd, uint32_t status) scmd %d: command completed, status %x +disable megasas_handle_io(int cmd, const char *frame, int dev, int lun, unsigned long lba, unsigned long count) scmd %d: %s dev %x/%x lba %lx count %lu +disable megasas_io_target_not_present(int cmd, const char *frame, int dev, int lun) scmd %d: %s dev %x/%x LUN not present +disable megasas_io_start(int cmd, const char *dir, unsigned long lba, unsigned long count, unsigned long len) scmd %d: %s start LBA %lx %lu blocks (%lu bytes) +disable megasas_io_complete(int cmd, uint32_t len) scmd %d: %d bytes completed +disable megasas_io_copy(int cmd, const char *dir, int bytes, int len, unsigned long offset) scmd %d: %s %d of %d bytes, iov offset %lu +disable megasas_io_continue(int cmd, int bytes) scmd %d: %d bytes left +megasas_iovec_map_failed(int cmd, int index, unsigned long iov_size) scmd %d: iovec %d size %lu +megasas_iovec_sgl_overflow(int cmd, int index, int limit) scmd %d: iovec count %d limit %d +megasas_iovec_sgl_underflow(int cmd, int index) scmd %d: iovec count %d +megasas_iovec_sgl_invalid(int cmd, int index, uint64_t pa, uint32_t len) scmd %d: invalid sgl element %d pa % PRIx64 len %u +megasas_iovec_len(int cmd, const char *desc, int len, int limit) scmd %d: iovec %s len %d limit %d +disable megasas_handle_dcmd(int cmd, int opcode) scmd %d: MFI DCMD opcode %x +disable megasas_finish_dcmd(int cmd, int size) scmd %d: MFI DCMD wrote %d bytes +megasas_dcmd_req_alloc_failed(int cmd, const char *desc) scmd %d: %s alloc failed +disable megasas_dcmd_internal_submit(int cmd, const char *desc, int dev) scmd %d: %s to dev %d +disable megasas_dcmd_internal_finish(int cmd, int opcode, int lun) scmd %d: DCMD finish internal cmd %x lun %d +megasas_dcmd_internal_invalid(int cmd, int opcode) scmd %d: Invalid internal DCMD %x +megasas_dcmd_unhandled(int cmd, int opcode, int len) scmd %d: opcode %x, len %d +disable megasas_dcmd_zero_sge(int cmd) scmd %d: zero DCMD sge count +megasas_dcmd_invalid_sge(int cmd, int count) scmd %d: invalid DCMD sge count %d
Re: [Qemu-devel] [PATCH 0/2][RFC] postcopy migration: Linux char device for postcopy
On 13 January 2012 02:03, Isaku Yamahata yamah...@valinux.co.jp wrote: Very interesting. We can cooperate for better (postcopy) live migration. The code doesn't seem available yet, I'm eager for it. On Fri, Jan 13, 2012 at 01:09:30AM +, Benoit Hudzia wrote: Hi, Sorry to jump to hijack the thread like that , however i would like to just to inform you that we recently achieve a milestone out of the research project I'm leading. We enhanced KVM in order to deliver post copy live migration using RDMA at kernel level. Few point on the architecture of the system : * RDMA communication engine in kernel ( you can use soft iwarp or soft ROCE if you don't have hardware acceleration, however we also support standard RDMA enabled NIC) . Do you mean infiniband subsystem? Yes, basically any software or hardware implementation that support the standard RDMA / OFED vverbs stack in kernel. * Naturally Page are transferred with Zerop copy protocol * Leverage the async page fault system. * Pre paging / faulting * No context switch as everything is handled within kernel and using the page fault system. * Hybrid migration ( pre + post copy) available Ah, I've been also planing this. After pre-copy phase, is the dirty bitmap sent? We sent over the dirty bitmap yes. In order to identify what is left to be transferred . And combined with the priority algo we will then prioritise the page for the background transfer. So far I've thought naively that pre-copy phase would be finished by the number of iterations. On the other hand your choice is timeout of pre-copy phase. Do you have rationale? or it was just natural for you? The main rational behind that is any normal sys admin tend to to be human and live migration iteration cycle has no meaning for him. As a result we preferred to provide a time constraint rather than an iteration constraint. Also it is hard to estimate how much time bandwidth would be use per iteration cycle which led to poor determinism. * Rely on an independent Kernel Module * No modification to the KVM kernel Module * Minimal Modification to the Qemu-Kvm code * We plan to add the page prioritization algo in order to optimise the pre paging algo and background transfer Where do you plan to implement? in qemu or in your kernel module? This algo could be shared. Yes we plan to actually release the algo first before the RDMA post copy. The algo can be use for standard optimisation of the normal pre-copy process (as demosntrated in my talk at KVM-forum). And if the priority is reverse for the post copy page pull. My colleague Aidan shribman is done with the implentation and we are now in testing phase in order to quantify the improvement. thanks in advance. You can learn a little bit more and see a demo here: http://tinyurl.com/8xa2bgl I hope to be able to provide more detail on the design soon. As well as more concrete demo of the system ( live migration of VM running large enterprise apps such as ERP or In memory DB) Note: this is just a step stone as the post copy live migration mainly enable us to validate the architecture design and code. Regards Benoit Regards Benoit On 12 January 2012 13:59, Avi Kivity a...@redhat.com wrote: On 01/04/2012 05:03 AM, Isaku Yamahata wrote: Yes, it's quite doable in user space(qemu) with a kernel-enhancement. And it would be easy to convert a separated daemon process into a thread in qemu. I think it should be done out side of qemu process for some reasons. (I just repeat same discussion at the KVM-forum because no one remembers it) - ptrace (and its variant) ?? Some people want to investigate guest ram on host (qemu stopped or lively). ?? For example, enhance crash utility and it will attach qemu process and ?? debug guest kernel. To debug the guest kernel you don't need to stop qemu itself. ?? I agree it's a problem for qemu debugging though. - core dump ?? qemu process may core-dump. ?? As postmortem analysis, people want to investigate guest RAM. ?? Again enhance crash utility and it will read the core file and analyze ?? guest kernel. ?? When creating core, the qemu process is already dead. Yes, strong point. It precludes the above possibilities to handle fault in qemu process. I agree. -- error compiling committee.c: too many arguments to function -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at ??http://vger.kernel.org/majordomo-info.html -- The production of too many useful things results in too many useless people -- yamahata -- The production of too many useful things results in too many useless people
Re: [Qemu-devel] [PATCH 0/2][RFC] postcopy migration: Linux char device for postcopy
On 13 January 2012 02:15, Isaku Yamahata yamah...@valinux.co.jp wrote: One more question. Does your architecture/implementation (in theory) allow KVM memory features like swap, KSM, THP? * Swap: Yes we support swap to disk ( the page is pulled from swap before being send over), swap process do its job on the other side. * KSM : same , we support KSM, the KSMed page is broken down and split and they are send individually ( yes sub optimal but make the protocol less messy) and we let the KSM daemon do its job on the other side. * THP : more sticky here. Due to time constraint we decided that we will be partially supporting it. What does it means: if we encounter THP we break them down in standard page granularity as it is our current memory unit we are manipulating. As a result you can have THP on the source but you won't have THP on the other side. _ Note , we didn't explore fully the ramification of THP with RDMA, i don't know if THP play well with the MMU of HW RDMA NIC, One thing i would like to explore is if it is possible to break down the THP in standard page and then reassemble them on the other side ( do any one fo you know if it is possible to aggregate page to for a THP in kernel ? ) * cgroup : should be transparently working, but we need to do more testing to confirm that . On Fri, Jan 13, 2012 at 11:03:23AM +0900, Isaku Yamahata wrote: Very interesting. We can cooperate for better (postcopy) live migration. The code doesn't seem available yet, I'm eager for it. On Fri, Jan 13, 2012 at 01:09:30AM +, Benoit Hudzia wrote: Hi, Sorry to jump to hijack the thread like that , however i would like to just to inform you that we recently achieve a milestone out of the research project I'm leading. We enhanced KVM in order to deliver post copy live migration using RDMA at kernel level. Few point on the architecture of the system : * RDMA communication engine in kernel ( you can use soft iwarp or soft ROCE if you don't have hardware acceleration, however we also support standard RDMA enabled NIC) . Do you mean infiniband subsystem? * Naturally Page are transferred with Zerop copy protocol * Leverage the async page fault system. * Pre paging / faulting * No context switch as everything is handled within kernel and using the page fault system. * Hybrid migration ( pre + post copy) available Ah, I've been also planing this. After pre-copy phase, is the dirty bitmap sent? So far I've thought naively that pre-copy phase would be finished by the number of iterations. On the other hand your choice is timeout of pre-copy phase. Do you have rationale? or it was just natural for you? * Rely on an independent Kernel Module * No modification to the KVM kernel Module * Minimal Modification to the Qemu-Kvm code * We plan to add the page prioritization algo in order to optimise the pre paging algo and background transfer Where do you plan to implement? in qemu or in your kernel module? This algo could be shared. thanks in advance. You can learn a little bit more and see a demo here: http://tinyurl.com/8xa2bgl I hope to be able to provide more detail on the design soon. As well as more concrete demo of the system ( live migration of VM running large enterprise apps such as ERP or In memory DB) Note: this is just a step stone as the post copy live migration mainly enable us to validate the architecture design and code. Regards Benoit Regards Benoit On 12 January 2012 13:59, Avi Kivity a...@redhat.com wrote: On 01/04/2012 05:03 AM, Isaku Yamahata wrote: Yes, it's quite doable in user space(qemu) with a kernel-enhancement. And it would be easy to convert a separated daemon process into a thread in qemu. I think it should be done out side of qemu process for some reasons. (I just repeat same discussion at the KVM-forum because no one remembers it) - ptrace (and its variant) ?? Some people want to investigate guest ram on host (qemu stopped or lively). ?? For example, enhance crash utility and it will attach qemu process and ?? debug guest kernel. To debug the guest kernel you don't need to stop qemu itself. ?? I agree it's a problem for qemu debugging though. - core dump ?? qemu process may core-dump. ?? As postmortem analysis, people want to investigate guest RAM. ?? Again enhance crash utility and it will read the core file and analyze ?? guest kernel. ?? When creating core, the qemu process is already dead. Yes, strong point. It precludes the above possibilities to handle fault in qemu process. I agree. -- error compiling committee.c: too many arguments to function -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at ??http://vger.kernel.org/majordomo-info.html
Re: [Qemu-devel] [PATCH 4/4] target-i386: fix SSE rounding and flush to zero
Dong Xu Wang wdon...@linux.vnet.ibm.com writes: After applied this patch, while I was compiling on my lap, there will be an error: ./configure --enable-kvm --target-list=x86_64-softmmu make CCx86_64-softmmu/translate.o /qemu/target-i386/translate.c: In function ‘disas_insn’: /qemu/target-i386/translate.c:7547:17: error: incompatible type for argument 1 of ‘gen_helper_ldmxcsr’ /qemu/target-i386/helper.h:200:1: note: expected ‘TCGv_i32’ but argument is of type ‘TCGv_i64’ make[1]: *** [translate.o] Error 1 make: *** [subdir-x86_64-softmmu] Error 2 I see this, too.
[Qemu-devel] [PATCH 1/2] qdev: Add a 'free' method to disassociate chardev from qdev device
When a device is removed, remove the association with a chardev, if any, so that the chardev can be re-used later for other devices. Reported-by: Qunfang Zhang qzh...@redhat.com Fix-suggested-by: Markus Armbruster arm...@redhat.com Signed-off-by: Amit Shah amit.s...@redhat.com --- hw/qdev-properties.c | 11 +++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 663c2a0..02f0dae 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -680,6 +680,16 @@ static int parse_chr(DeviceState *dev, Property *prop, const char *str) return 0; } +static void free_chr(DeviceState *dev, Property *prop) +{ +CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); + +if (*ptr) { +qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); +} +} + + static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len) { CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); @@ -699,6 +709,7 @@ PropertyInfo qdev_prop_chr = { .print = print_chr, .get = get_generic, .set = set_generic, +.free = free_chr, }; /* --- netdev device --- */ -- 1.7.7.5
[Qemu-devel] [PATCH 0/2] qdev: disassociate chardev from device on device exit
When the device is going away (e.g., hot-unplug), an associated chardev should be freed and made available for use for other devices. An earlier hack did this for virtio serial ports, do it in a generic way and remove the virtio-serial specific hack. Amit Shah (2): qdev: Add a 'free' method to disassociate chardev from qdev device virtio-console: no need to remove char handlers explicitly hw/qdev-properties.c | 11 +++ hw/virtio-console.c | 10 -- 2 files changed, 11 insertions(+), 10 deletions(-) -- 1.7.7.5
[Qemu-devel] [PATCH 2/2] virtio-console: no need to remove char handlers explicitly
qdev is now equipped (thanks to the last commit) to disassociate chardevs from the qdev devices on the devices going away. So doing it in the virtio-console driver is not necessary. Since that was the only thing being done in the qdev exit method, drop it entirely. Signed-off-by: Amit Shah amit.s...@redhat.com --- hw/virtio-console.c | 10 -- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/hw/virtio-console.c b/hw/virtio-console.c index 73d866a..9275fd9 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -127,16 +127,6 @@ static int virtconsole_initfn(VirtIOSerialPort *port) static int virtconsole_exitfn(VirtIOSerialPort *port) { -VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); - -if (vcon-chr) { - /* -* Instead of closing the chardev, free it so it can be used -* for other purposes. -*/ - qemu_chr_add_handlers(vcon-chr, NULL, NULL, NULL, NULL); -} - return 0; } -- 1.7.7.5
Re: [Qemu-devel] [PATCH 2/2] virtio-console: no need to remove char handlers explicitly
On (Fri) 13 Jan 2012 [15:24:59], Amit Shah wrote: qdev is now equipped (thanks to the last commit) to disassociate chardevs from the qdev devices on the devices going away. So doing it in the virtio-console driver is not necessary. Since that was the only thing being done in the qdev exit method, drop it entirely. Commit message is correct, patch is not. Updated patch coming soon.. diff --git a/hw/virtio-console.c b/hw/virtio-console.c index 73d866a..9275fd9 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -127,16 +127,6 @@ static int virtconsole_initfn(VirtIOSerialPort *port) static int virtconsole_exitfn(VirtIOSerialPort *port) { -VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); - -if (vcon-chr) { - /* - * Instead of closing the chardev, free it so it can be used - * for other purposes. - */ - qemu_chr_add_handlers(vcon-chr, NULL, NULL, NULL, NULL); -} - return 0; } Amit
[Qemu-devel] [PATCH v2 0/2] qdev: disassociate chardev from device on device exit
When the device is going away (e.g., hot-unplug), an associated chardev should be freed and made available for use for other devices. An earlier hack did this for virtio serial ports, do it in a generic way and remove the virtio-serial specific hack. v2: - actually remove virtconsole_exitfn() Amit Shah (2): qdev: Add a 'free' method to disassociate chardev from qdev device virtio-console: no need to remove char handlers explicitly hw/qdev-properties.c | 11 +++ hw/virtio-console.c | 17 - 2 files changed, 11 insertions(+), 17 deletions(-) -- 1.7.7.5
Re: [Qemu-devel] [PATCH] qdev: fix hotplug when no -device is specified
device_del is broken for me in master: $ qemu-system-x86_64 -nodefaults -S -m 384 -vnc :0 -monitor stdio -usb QEMU 1.0.50 monitor - type 'help' for more information (qemu) device_add usb-mouse,id=foo (qemu) device_del foo Device 'foo' is in use Same for any hot-pluggable device I tried, with and without -S. git-bisect fingers this patch, which went in as commit 1de81d28.
[Qemu-devel] [PATCH v2 1/2] qdev: Add a 'free' method to disassociate chardev from qdev device
When a device is removed, remove the association with a chardev, if any, so that the chardev can be re-used later for other devices. Reported-by: Qunfang Zhang qzh...@redhat.com Fix-suggested-by: Markus Armbruster arm...@redhat.com Signed-off-by: Amit Shah amit.s...@redhat.com --- hw/qdev-properties.c | 11 +++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 663c2a0..02f0dae 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -680,6 +680,16 @@ static int parse_chr(DeviceState *dev, Property *prop, const char *str) return 0; } +static void free_chr(DeviceState *dev, Property *prop) +{ +CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); + +if (*ptr) { +qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); +} +} + + static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len) { CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); @@ -699,6 +709,7 @@ PropertyInfo qdev_prop_chr = { .print = print_chr, .get = get_generic, .set = set_generic, +.free = free_chr, }; /* --- netdev device --- */ -- 1.7.7.5
[Qemu-devel] [PATCH v2 2/2] virtio-console: no need to remove char handlers explicitly
qdev is now equipped (thanks to the last commit) to disassociate chardevs from the qdev devices on the devices going away. So doing it in the virtio-console driver is not necessary. Since that was the only thing being done in the qdev exit method, drop it entirely. Signed-off-by: Amit Shah amit.s...@redhat.com --- hw/virtio-console.c | 17 - 1 files changed, 0 insertions(+), 17 deletions(-) diff --git a/hw/virtio-console.c b/hw/virtio-console.c index 73d866a..0b28a30 100644 --- a/hw/virtio-console.c +++ b/hw/virtio-console.c @@ -125,27 +125,11 @@ static int virtconsole_initfn(VirtIOSerialPort *port) return 0; } -static int virtconsole_exitfn(VirtIOSerialPort *port) -{ -VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); - -if (vcon-chr) { - /* -* Instead of closing the chardev, free it so it can be used -* for other purposes. -*/ - qemu_chr_add_handlers(vcon-chr, NULL, NULL, NULL, NULL); -} - -return 0; -} - static VirtIOSerialPortInfo virtconsole_info = { .qdev.name = virtconsole, .qdev.size = sizeof(VirtConsole), .is_console= true, .init = virtconsole_initfn, -.exit = virtconsole_exitfn, .have_data = flush_buf, .guest_open= guest_open, .guest_close = guest_close, @@ -165,7 +149,6 @@ static VirtIOSerialPortInfo virtserialport_info = { .qdev.name = virtserialport, .qdev.size = sizeof(VirtConsole), .init = virtconsole_initfn, -.exit = virtconsole_exitfn, .have_data = flush_buf, .guest_open= guest_open, .guest_close = guest_close, -- 1.7.7.5
Re: [Qemu-devel] [PATCH][v8] megasas: LSI Megaraid SAS HBA emulation
On 01/13/2012 10:46 AM, Hannes Reinecke wrote: So, I should be removing the 'disable' keyword, then, correct? Yes. The strings are just there to avoid trace statement duplication. But if that's not a problem then I can easily convert the strings to individual trace statements. No, don't bother. Paolo
[Qemu-devel] [PULL 00/12] Trivial patches for 6 to 13 January 2012
The following changes since commit bee5a5fb11de34aa422cfc830adbd51cfc8f5b55: cris: Update paths to match the move of tests/cris (2012-01-13 11:09:56 +0100) are available in the git repository at: git://github.com/stefanha/qemu.git trivial-patches Aurelien Jarno (1): tcg-arm: fix a typo in comments Stefan Berger (1): hmp: Fix freeing of PciInfoList Stefan Hajnoczi (4): vvfat: avoid leaking file descriptor in commit_one_file() vnc: fix no-lock-key-sync strncmp() length omap_dss: correct chip[1] index in RFBI_READ/RFBI_STATUS bt-host: add missing break statement Stefan Weil (6): configure: Modify detection of supported warning options Spelling fixes in comments and documentation Add 'fall through' comments to case statements without break virtfs-proxy-helper: Fix compilation on newer systems virtfs-proxy-helper: Clean include files virtfs-proxy-helper: Add missing printf format attribute block/vvfat.c |3 +++ bt-host.c |1 + configure |2 +- docs/writing-qmp-commands.txt |2 +- exec.c|2 +- fsdev/virtfs-proxy-helper.c | 19 --- hmp.c |8 hw/omap_dss.c |4 ++-- hw/pcnet.c|1 + json-lexer.c |1 + memory.h |4 ++-- qemu-ga.c |2 +- qemu-option.c |4 tcg/arm/tcg-target.c |2 +- ui/vnc.c |2 +- 15 files changed, 28 insertions(+), 29 deletions(-) -- 1.7.7.3
[Qemu-devel] [PATCH 05/12] vnc: fix no-lock-key-sync strncmp() length
The no-lock-key-sync option is being parsed incorrectly because of an outdated strcmp() length value. Use the correct length so that invalid option names do not match. Reported-by: Dr David Alan Gilbert davidagilb...@uk.ibm.com Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- ui/vnc.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/ui/vnc.c b/ui/vnc.c index 6767ada..1869a7a 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2763,7 +2763,7 @@ int vnc_display_open(DisplayState *ds, const char *display) password = 1; /* Require password auth */ } else if (strncmp(options, reverse, 7) == 0) { reverse = 1; -} else if (strncmp(options, no-lock-key-sync, 9) == 0) { +} else if (strncmp(options, no-lock-key-sync, 16) == 0) { lock_key_sync = 0; #ifdef CONFIG_VNC_SASL } else if (strncmp(options, sasl, 4) == 0) { -- 1.7.7.3
[Qemu-devel] [PATCH 03/12] Spelling fixes in comments and documentation
From: Stefan Weil s...@weilnetz.de Codespell detected these new spelling issues. Signed-off-by: Stefan Weil s...@weilnetz.de Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- docs/writing-qmp-commands.txt |2 +- memory.h |4 ++-- qemu-ga.c |2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/writing-qmp-commands.txt b/docs/writing-qmp-commands.txt index 0472fc3..0ad51aa 100644 --- a/docs/writing-qmp-commands.txt +++ b/docs/writing-qmp-commands.txt @@ -435,7 +435,7 @@ There are a number of things to be noticed: for all QMP functions) 3. The clock variable (which will point to our QAPI type instance) is allocated by the regular g_malloc0() function. Note that we chose to - initialize the memory to zero. This is recomended for all QAPI types, as + initialize the memory to zero. This is recommended for all QAPI types, as it helps avoiding bad surprises (specially with booleans) 4. Remember that next_deadline is optional? All optional members have a 'has_TYPE_NAME' member that should be properly set by the implementation, diff --git a/memory.h b/memory.h index 70f57fb..d48b08b 100644 --- a/memory.h +++ b/memory.h @@ -561,7 +561,7 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr, * memory_region_get_ram_addr: Get the ram address associated with a memory * region * - * DO NOT USE THIS FUCNTION. This is a temporary workaround while the Xen + * DO NOT USE THIS FUNCTION. This is a temporary workaround while the Xen * code is being reworked. */ ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr); @@ -650,7 +650,7 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space); * memory_region_transaction_begin: Start a transaction. * * During a transaction, changes will be accumulated and made visible - * only when the transaction ends (is commited). + * only when the transaction ends (is committed). */ void memory_region_transaction_begin(void); diff --git a/qemu-ga.c b/qemu-ga.c index 200bb15..29e4f64 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -92,7 +92,7 @@ static void usage(const char *cmd) -v, --verbose log extra debugging information\n -V, --version print version information and exit\n -d, --daemonize become a daemon\n - -b, --blacklist comma-seperated list of RPCs to disable (no spaces, \?\ + -b, --blacklist comma-separated list of RPCs to disable (no spaces, \?\ to list available RPCs)\n -h, --helpdisplay this help and exit\n \n -- 1.7.7.3
[Qemu-devel] [PATCH 02/12] tcg-arm: fix a typo in comments
From: Aurelien Jarno aurel...@aurel32.net ARM still doesn't support 16GB buffers in 32-bit modes, replace the 16GB by 16MB in the comment. Reviewed-by: Peter Maydell peter.mayd...@linaro.org Signed-off-by: Aurelien Jarno aurel...@aurel32.net Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- exec.c |2 +- tcg/arm/tcg-target.c |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index b1d6602..7f9f730 100644 --- a/exec.c +++ b/exec.c @@ -511,7 +511,7 @@ static void code_gen_alloc(unsigned long tb_size) if (code_gen_buffer_size (512 * 1024 * 1024)) code_gen_buffer_size = (512 * 1024 * 1024); #elif defined(__arm__) -/* Keep the buffer no bigger than 16GB to branch between blocks */ +/* Keep the buffer no bigger than 16MB to branch between blocks */ if (code_gen_buffer_size 16 * 1024 * 1024) code_gen_buffer_size = 16 * 1024 * 1024; #elif defined(__s390x__) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 1d32798..5b233f5 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -843,7 +843,7 @@ static inline void tcg_out_st8(TCGContext *s, int cond, } /* The _goto case is normally between TBs within the same code buffer, - * and with the code buffer limited to 16GB we shouldn't need the long + * and with the code buffer limited to 16MB we shouldn't need the long * case. * * except to the prologue that is in its own buffer. -- 1.7.7.3
[Qemu-devel] [PATCH 01/12] configure: Modify detection of supported warning options
From: Stefan Weil s...@weilnetz.de Reversing the order of the warning options and -Werror is important when clang is used instead of gcc. It changes nothing for gcc. Signed-off-by: Stefan Weil s...@weilnetz.de Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- configure |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/configure b/configure index eb9a01d..467e87b 100755 --- a/configure +++ b/configure @@ -1105,7 +1105,7 @@ cat $TMPC EOF int main(void) { return 0; } EOF for flag in $gcc_flags; do -if compile_prog $flag -Werror ; then +if compile_prog -Werror $flag ; then QEMU_CFLAGS=$QEMU_CFLAGS $flag fi done -- 1.7.7.3
[Qemu-devel] [PATCH 04/12] vvfat: avoid leaking file descriptor in commit_one_file()
Reported-by: Dr David Alan Gilbert davidagilb...@uk.ibm.com Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- block/vvfat.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/block/vvfat.c b/block/vvfat.c index eeffc4a..9ef21dd 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2218,6 +2218,7 @@ static int commit_one_file(BDRVVVFATState* s, } if (offset 0) { if (lseek(fd, offset, SEEK_SET) != offset) { +close(fd); g_free(cluster); return -3; } @@ -2238,11 +2239,13 @@ static int commit_one_file(BDRVVVFATState* s, (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200); if (ret 0) { +close(fd); g_free(cluster); return ret; } if (write(fd, cluster, rest_size) 0) { +close(fd); g_free(cluster); return -2; } -- 1.7.7.3
[Qemu-devel] [PATCH 10/12] virtfs-proxy-helper: Clean include files
From: Stefan Weil s...@weilnetz.de The common standard include files are already included via qemu-common.h, and for the socket related include files there is qemu_socket.h, so the code can be reduced by some lines. Signed-off-by: Stefan Weil s...@weilnetz.de Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- fsdev/virtfs-proxy-helper.c | 15 ++- 1 files changed, 2 insertions(+), 13 deletions(-) diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index ce7eb79..21e9b16 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -8,31 +8,20 @@ * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. */ -#include stdio.h -#include sys/socket.h -#include string.h -#include sys/un.h -#include limits.h -#include signal.h -#include errno.h -#include stdlib.h + #include sys/resource.h -#include sys/stat.h #include getopt.h -#include unistd.h #include syslog.h #include sys/capability.h #include sys/fsuid.h -#include stdarg.h -#include stdbool.h #include sys/vfs.h -#include sys/stat.h #include sys/ioctl.h #include linux/fs.h #ifdef CONFIG_LINUX_MAGIC_H #include linux/magic.h #endif #include qemu-common.h +#include qemu_socket.h #include qemu-xattr.h #include virtio-9p-marshal.h #include hw/9pfs/virtio-9p-proxy.h -- 1.7.7.3
[Qemu-devel] [PATCH 06/12] omap_dss: correct chip[1] index in RFBI_READ/RFBI_STATUS
The RFBI_READ/RFBI_STATUS code incorrectly uses chip[0] when it should be using chip[1]. Andrzej Zaborowski bal...@zabor.org confirmed this bug since I don't know this code well. Reported-by: Dr David Alan Gilbert davidagilb...@uk.ibm.com Reviewed-by: Andrzej Zaborowski andrew.zaborow...@intel.com Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- hw/omap_dss.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/omap_dss.c b/hw/omap_dss.c index ede640b..86ed6ea 100644 --- a/hw/omap_dss.c +++ b/hw/omap_dss.c @@ -793,7 +793,7 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, if ((s-rfbi.control (1 2)) s-rfbi.chip[0]) s-rfbi.rxbuf = s-rfbi.chip[0]-read(s-rfbi.chip[0]-opaque, 1); else if ((s-rfbi.control (1 3)) s-rfbi.chip[1]) -s-rfbi.rxbuf = s-rfbi.chip[0]-read(s-rfbi.chip[0]-opaque, 1); +s-rfbi.rxbuf = s-rfbi.chip[1]-read(s-rfbi.chip[1]-opaque, 1); if (!-- s-rfbi.pixels) omap_rfbi_transfer_stop(s); break; @@ -802,7 +802,7 @@ static void omap_rfbi_write(void *opaque, target_phys_addr_t addr, if ((s-rfbi.control (1 2)) s-rfbi.chip[0]) s-rfbi.rxbuf = s-rfbi.chip[0]-read(s-rfbi.chip[0]-opaque, 0); else if ((s-rfbi.control (1 3)) s-rfbi.chip[1]) -s-rfbi.rxbuf = s-rfbi.chip[0]-read(s-rfbi.chip[0]-opaque, 0); +s-rfbi.rxbuf = s-rfbi.chip[1]-read(s-rfbi.chip[1]-opaque, 0); if (!-- s-rfbi.pixels) omap_rfbi_transfer_stop(s); break; -- 1.7.7.3
[Qemu-devel] [PATCH 11/12] virtfs-proxy-helper: Add missing printf format attribute
From: Stefan Weil s...@weilnetz.de Every function with printf like arguments must have it (see file HACKING), so add it. Signed-off-by: Stefan Weil s...@weilnetz.de Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- fsdev/virtfs-proxy-helper.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index 21e9b16..4a507d8 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -54,7 +54,7 @@ static struct option helper_opts[] = { static bool is_daemon; static bool get_version; /* IOC getversion IOCTL supported */ -static void do_log(int loglevel, const char *format, ...) +static void GCC_FMT_ATTR(2, 3) do_log(int loglevel, const char *format, ...) { va_list ap; -- 1.7.7.3
[Qemu-devel] [PATCH 09/12] virtfs-proxy-helper: Fix compilation on newer systems
From: Stefan Weil s...@weilnetz.de Include file attr/xattr.h is not available on newer systems (for example Fedora 12 or Debian Squeeze). See comments in qemu-xattr.h for more information. This file handles the system dependencies automatically. Signed-off-by: Stefan Weil s...@weilnetz.de Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- fsdev/virtfs-proxy-helper.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index 7f8def5..ce7eb79 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -27,13 +27,13 @@ #include stdbool.h #include sys/vfs.h #include sys/stat.h -#include attr/xattr.h #include sys/ioctl.h #include linux/fs.h #ifdef CONFIG_LINUX_MAGIC_H #include linux/magic.h #endif #include qemu-common.h +#include qemu-xattr.h #include virtio-9p-marshal.h #include hw/9pfs/virtio-9p-proxy.h #include fsdev/virtio-9p-marshal.h -- 1.7.7.3
[Qemu-devel] [PATCH 07/12] Add 'fall through' comments to case statements without break
From: Stefan Weil s...@weilnetz.de These comments are used by static code analysis tools and in code reviews to avoid false warnings because of missing break statements. The case statements handled here were reported by coverity. Reviewed-by: Peter Maydell peter.mayd...@linaro.org Signed-off-by: Stefan Weil s...@weilnetz.de Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- hw/pcnet.c|1 + json-lexer.c |1 + qemu-option.c |4 3 files changed, 6 insertions(+), 0 deletions(-) diff --git a/hw/pcnet.c b/hw/pcnet.c index cba253b..306dc6e 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -1505,6 +1505,7 @@ static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val) #ifdef PCNET_DEBUG printf(BCR_SWS=0x%04x\n, val); #endif +/* fall through */ case BCR_LNKST: case BCR_LED1: case BCR_LED2: diff --git a/json-lexer.c b/json-lexer.c index c21338f..3cd3285 100644 --- a/json-lexer.c +++ b/json-lexer.c @@ -301,6 +301,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush) case JSON_KEYWORD: case JSON_STRING: lexer-emit(lexer, lexer-token, new_state, lexer-x, lexer-y); +/* fall through */ case JSON_SKIP: QDECREF(lexer-token); lexer-token = qstring_new(); diff --git a/qemu-option.c b/qemu-option.c index 6b23c31..a303f87 100644 --- a/qemu-option.c +++ b/qemu-option.c @@ -214,13 +214,17 @@ static int parse_option_size(const char *name, const char *value, uint64_t *ret) switch (*postfix) { case 'T': sizef *= 1024; +/* fall through */ case 'G': sizef *= 1024; +/* fall through */ case 'M': sizef *= 1024; +/* fall through */ case 'K': case 'k': sizef *= 1024; +/* fall through */ case 'b': case '\0': *ret = (uint64_t) sizef; -- 1.7.7.3
[Qemu-devel] --enable-check-utests gone, you may have to re-run configure (was: [PATCH 10/15] test: eliminate libcheck tests and have make check use gtester)
Deserves more prominent notice, so here goes: Anthony Liguori aligu...@us.ibm.com writes: [...] @@ -733,10 +732,6 @@ for opt do ;; --enable-fdt) fdt=yes ;; - --disable-check-utests) check_utests=no - ;; - --enable-check-utests) check_utests=yes - ;; --disable-nptl) nptl=no ;; --enable-nptl) nptl=yes Just drop the option from your configure command line. [...]
Re: [Qemu-devel] [PATCH 03/30] ppc: remove ppc440 bamboo board support
On Mon, 2012-01-02 at 18:51 -0600, Anthony Liguori wrote: This board never worked with TCG. It hasn't been updated since 0.13.0. I'm fairly sure hardware doesn't exist anymore that you can run the KVM support with. It does exist, I have one :-) So let's remove it. It can always be restored later if there is interest again. Cheers, Ben. Signed-off-by: Anthony Liguori aligu...@us.ibm.com --- Makefile.target|3 +- hw/ppc440.c| 106 --- hw/ppc440.h| 21 --- hw/ppc440_bamboo.c | 215 - hw/ppc4xx_pci.c| 381 hw/virtex_ml507.c |1 - 6 files changed, 1 insertions(+), 726 deletions(-) delete mode 100644 hw/ppc440.c delete mode 100644 hw/ppc440.h delete mode 100644 hw/ppc440_bamboo.c delete mode 100644 hw/ppc4xx_pci.c diff --git a/Makefile.target b/Makefile.target index 3261383..b8ccf07 100644 --- a/Makefile.target +++ b/Makefile.target @@ -246,8 +246,7 @@ obj-ppc-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o obj-ppc-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o obj-ppc-$(CONFIG_PSERIES) += spapr_pci.o device-hotplug.o pci-hotplug.o # PowerPC 4xx boards -obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o -obj-ppc-y += ppc440.o ppc440_bamboo.o +obj-ppc-y += ppc4xx_devs.o ppc405_uc.o ppc405_boards.o # PowerPC E500 boards obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o # PowerPC 440 Xilinx ML507 reference board. diff --git a/hw/ppc440.c b/hw/ppc440.c deleted file mode 100644 index cd8a95d..000 --- a/hw/ppc440.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Qemu PowerPC 440 chip emulation - * - * Copyright 2007 IBM Corporation. - * Authors: - * Jerone Young jyou...@us.ibm.com - * Christian Ehrhardt ehrha...@linux.vnet.ibm.com - * Hollis Blanchard holl...@us.ibm.com - * - * This work is licensed under the GNU GPL license version 2 or later. - * - */ - -#include hw.h -#include pc.h -#include isa.h -#include ppc.h -#include ppc4xx.h -#include ppc440.h -#include ppc405.h -#include sysemu.h -#include kvm.h - -#define PPC440EP_PCI_CONFIG 0xeec0 -#define PPC440EP_PCI_INTACK 0xeed0 -#define PPC440EP_PCI_SPECIAL0xeed0 -#define PPC440EP_PCI_REGS 0xef40 -#define PPC440EP_PCI_IO 0xe800 -#define PPC440EP_PCI_IOLEN 0x0001 - -#define PPC440EP_SDRAM_NR_BANKS 4 - -static const unsigned int ppc440ep_sdram_bank_sizes[] = { -25620, 12820, 6420, 3220, 1620, 820, 0 -}; - -CPUState *ppc440ep_init(MemoryRegion *address_space_mem, ram_addr_t *ram_size, -PCIBus **pcip, const unsigned int pci_irq_nrs[4], -int do_init, const char *cpu_model) -{ -MemoryRegion *ram_memories -= g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories)); -target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS]; -target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS]; -CPUState *env; -qemu_irq *pic; -qemu_irq *irqs; -qemu_irq *pci_irqs; - -if (cpu_model == NULL) { -cpu_model = 440-Xilinx; // XXX: should be 440EP -} -env = cpu_init(cpu_model); -if (!env) { -fprintf(stderr, Unable to initialize CPU!\n); -exit(1); -} - -ppc_dcr_init(env, NULL, NULL); - -/* interrupt controller */ -irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); -irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env-irq_inputs)[PPC40x_INPUT_INT]; -irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env-irq_inputs)[PPC40x_INPUT_CINT]; -pic = ppcuic_init(env, irqs, 0x0C0, 0, 1); - -/* SDRAM controller */ -memset(ram_bases, 0, sizeof(ram_bases)); -memset(ram_sizes, 0, sizeof(ram_sizes)); -*ram_size = ppc4xx_sdram_adjust(*ram_size, PPC440EP_SDRAM_NR_BANKS, -ram_memories, -ram_bases, ram_sizes, -ppc440ep_sdram_bank_sizes); -/* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */ -ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories, - ram_bases, ram_sizes, do_init); - -/* PCI */ -pci_irqs = g_malloc(sizeof(qemu_irq) * 4); -pci_irqs[0] = pic[pci_irq_nrs[0]]; -pci_irqs[1] = pic[pci_irq_nrs[1]]; -pci_irqs[2] = pic[pci_irq_nrs[2]]; -pci_irqs[3] = pic[pci_irq_nrs[3]]; -*pcip = ppc4xx_pci_init(env, pci_irqs, -PPC440EP_PCI_CONFIG, -PPC440EP_PCI_INTACK, -PPC440EP_PCI_SPECIAL, -PPC440EP_PCI_REGS); -if (!*pcip) -printf(couldn't create PCI controller!\n); - -isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN); - -if
Re: [Qemu-devel] [PATCH 03/30] ppc: remove ppc440 bamboo board support
Am 13.01.2012 11:59, schrieb Benjamin Herrenschmidt: On Mon, 2012-01-02 at 18:51 -0600, Anthony Liguori wrote: This board never worked with TCG. It hasn't been updated since 0.13.0. I'm fairly sure hardware doesn't exist anymore that you can run the KVM support with. It does exist, I have one :-) Alex has already posted series to not only qdev'ify it but to also add TCG support so other people can test it. Review and testing would probably be appreciated. :) Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
[Qemu-devel] [PATCH 12/12] bt-host: add missing break statement
The switch statement in bt_host_read() is missing a break in one case. Andrzej Zaborowski andrew.zaborow...@intel.com confirmed that this is not an intentional fall-through. Reviewed-by: Stefan Weil s...@weilnetz.de Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- bt-host.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/bt-host.c b/bt-host.c index df5b7cd..0d3ad28 100644 --- a/bt-host.c +++ b/bt-host.c @@ -130,6 +130,7 @@ static void bt_host_read(void *opaque) pktlen = MIN(pkt[2] + 3, s-len); s-len -= pktlen; pkt += pktlen; +break; default: bad_pkt: -- 1.7.7.3
[Qemu-devel] [PATCH 08/12] hmp: Fix freeing of PciInfoList
From: Stefan Berger stef...@linux.vnet.ibm.com Remember the original PciInfoList in info_list and use the info variable to traverse the list. Signed-off-by: Stefan Berger stef...@linux.vnet.ibm.com Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- hmp.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hmp.c b/hmp.c index e7659d5..fd4f755 100644 --- a/hmp.c +++ b/hmp.c @@ -486,17 +486,17 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) void hmp_info_pci(Monitor *mon) { -PciInfoList *info; +PciInfoList *info_list, *info; Error *err = NULL; -info = qmp_query_pci(err); +info_list = qmp_query_pci(err); if (err) { monitor_printf(mon, PCI devices not supported\n); error_free(err); return; } -for (; info; info = info-next) { +for (info = info_list; info; info = info-next) { PciDeviceInfoList *dev; for (dev = info-value-devices; dev; dev = dev-next) { @@ -504,7 +504,7 @@ void hmp_info_pci(Monitor *mon) } } -qapi_free_PciInfoList(info); +qapi_free_PciInfoList(info_list); } void hmp_quit(Monitor *mon, const QDict *qdict) -- 1.7.7.3
[Qemu-devel] [PULL 00/17] usb patch queue: audio, xhci, usbredir
Hi, Here comes the usb patch queue. It features the patches posted a week ago for review with some minor tweaks according to the review comments: The comment in usb-audio was fixed and xhci got a codestyle cleanup. No actual code changes. I've also included the usb-redir patches posted by Hans earlier this week. please pull, Gerd The following changes since commit 515aa3c57986b3e26558d72ecaeb7545ecd30510: check-qstring: remove check.h include (2012-01-12 11:33:22 -0600) are available in the git repository at: git://git.kraxel.org/qemu usb.36 Gerd Hoffmann (10): usb-host: rip out legacy procfs support usb: track configuration and interface count in USBDevice. usb: track altsetting in USBDevice usb-desc: audio endpoint support usb: add USBEndpoint usb: add ifnum to USBEndpoint usb-desc: USBEndpoint support usb/debug: add usb_ep_dump usb: add max_packet_size to USBEndpoint usb: link packets to endpoints not devices H. Peter Anvin (1): usb: add audio device model Hans de Goede (5): usb-redir: Clear iso / irq error when stopping the stream usb-redir: Dynamically adjust iso buffering size based on ep interval usb-redir: Pre-fill our isoc input buffer before sending pkts to the host usb-redir: Try to keep our buffer size near the target size usb-redir: Improve some debugging messages Hector Martin (1): xhci: Initial xHCI implementation Makefile.objs |3 +- default-configs/pci.mak |1 + hw/pci_ids.h|3 + hw/usb-audio.c | 704 hw/usb-bt.c | 22 - hw/usb-bus.c|1 + hw/usb-ccid.c |8 - hw/usb-desc.c | 143 +++- hw/usb-desc.h |5 + hw/usb-ehci.c |3 +- hw/usb-hid.c|7 - hw/usb-hub.c|7 - hw/usb-msd.c| 10 - hw/usb-musb.c |3 +- hw/usb-net.c| 14 - hw/usb-ohci.c |4 +- hw/usb-serial.c |7 - hw/usb-uhci.c |3 +- hw/usb-wacom.c |7 - hw/usb-xhci.c | 2748 +++ hw/usb.c| 125 +++- hw/usb.h| 44 +- trace-events|1 + usb-linux.c | 452 ++-- usb-redir.c | 118 ++- 25 files changed, 3972 insertions(+), 471 deletions(-) create mode 100644 hw/usb-audio.c create mode 100644 hw/usb-xhci.c
Re: [Qemu-devel] [PATCH v3 0/8] qdev'ify PReP PCI host bridge and add PCI-to-ISA bridge
On 13.01.2012, at 04:09, Andreas Färber wrote: Hello, Here's an updated initial qdev'ification series for PReP, as prerequisite for Anthony's second QOM series. As stated before, this is NOT a complete conversion of all PReP devices and of all those shared with x86. Please comment on what's there, not on what may be done, too. I'm sitting on these patches for over a year now, so let's start getting some of it merged so that we can move on with QOM and get some of the design issues fixed that kept the pc87312 Super I/O and 40P machine from getting merged in the first place! Regards, Andreas Looks good to me. Reviewed-by: Alexander Graf ag...@suse.de Alex Changes since v2: * Simplify I/O byte swaps. * Convert I/O from old_mmio to MemoryRegion ops. * Drop pci_prep_init() and instantiate the PCI host bridge in the machine, reintroducing PREPPCIState extension. * Connect IRQs via qdev after instantiating. Suggested by Alex. * Add a rebased PCI-to-ISA-bridge from the 40P series on top, to show why some suggestions from v2 and IRC don't work out. * Merge fix-up by Hervé: Add indirection for late-connected out[0] IRQ. * Add VMState for i82374 and i82378. * From i82378 drop the I/O address translation duplicated from the board. * Rebase i82378 onto Memory API. http://patchwork.ozlabs.org/patch/100250/ http://patchwork.ozlabs.org/patch/100272/ * Add new patch from Hervé to wire up the PCI-to-ISA bridge for 'prep'. Changes since v1: * Use the new .vendor_id etc. in PCIDeviceInfo * Rename from PRePPCI to Raven, adopt naming scheme from i440FX * Rebase onto multiple Memory API conversions * Split into PCIDevice and SysBus patches, leave out PREPPCIState changes http://patchwork.ozlabs.org/patch/100268/ Cc: Hervé Poussineau hpous...@reactos.org Cc: Anthony Liguori aligu...@us.ibm.com Cc: Alexander Graf ag...@suse.de Andreas Färber (8): prep: qdev'ify Raven host bridge (PCIDevice) prep_pci: Simplify I/O endianness prep_pci: Update I/O to MemoryRegion ops prep: qdev'ify Raven host bridge (SysBus) MAINTAINERS: Add PCI host bridge files to PReP machine prep: Add i82374 DMA emulation prep: Add i82378 PCI-to-ISA bridge emulation prep: Use i82378 PCI-ISA bridge for 'prep' machine MAINTAINERS |1 + Makefile.objs |2 + default-configs/ppc-softmmu.mak |3 + hw/i82374.c | 154 hw/i82378.c | 252 +++ hw/pci_ids.h|1 + hw/ppc_prep.c | 77 +--- hw/prep_pci.c | 181 +--- hw/prep_pci.h | 11 -- 9 files changed, 553 insertions(+), 129 deletions(-) create mode 100644 hw/i82374.c create mode 100644 hw/i82378.c delete mode 100644 hw/prep_pci.h -- 1.7.7
[Qemu-devel] [PATCH 05/17] usb: add audio device model
From: H. Peter Anvin h...@linux.intel.com This brings a usb audio device to qemu. Output only, fixed at 16bit stereo @ 48 Hz. Based on a patch from H. Peter Anvin h...@linux.intel.com Usage: add '-device usb-audio' to your qemu command line. Works sorta ok on a idle machine. Known issues: * Is *very* sensitive to latencies. * Burns quite some CPU due to usb polling. In short: It brings the qemu usb emulation to its limits. Enjoy! Signed-off-by: Gerd Hoffmann kra...@redhat.com --- Makefile.objs |2 +- hw/usb-audio.c | 704 hw/usb-net.c |3 - hw/usb.h |7 + 4 files changed, 712 insertions(+), 4 deletions(-) create mode 100644 hw/usb-audio.c diff --git a/Makefile.objs b/Makefile.objs index 4f6d26c..8956cb9 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -102,7 +102,7 @@ common-obj-y += scsi-disk.o cdrom.o common-obj-y += scsi-generic.o scsi-bus.o common-obj-y += hid.o common-obj-y += usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o -common-obj-y += usb-serial.o usb-net.o usb-bus.o usb-desc.o +common-obj-y += usb-serial.o usb-net.o usb-bus.o usb-desc.o usb-audio.o common-obj-$(CONFIG_SSI) += ssi.o common-obj-$(CONFIG_SSI_SD) += ssi-sd.o common-obj-$(CONFIG_SD) += sd.o diff --git a/hw/usb-audio.c b/hw/usb-audio.c new file mode 100644 index 000..b22d578 --- /dev/null +++ b/hw/usb-audio.c @@ -0,0 +1,704 @@ +/* + * QEMU USB audio device + * + * written by: + * H. Peter Anvin h...@linux.intel.com + * Gerd Hoffmann kra...@redhat.com + * + * lousely based on usb net device code which is: + * + * Copyright (c) 2006 Thomas Sailer + * Copyright (c) 2008 Andrzej Zaborowski + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the Software), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include qemu-common.h +#include usb.h +#include usb-desc.h +#include hw.h +#include audiodev.h +#include audio/audio.h + +#define USBAUDIO_VENDOR_NUM 0x46f4 /* CRC16() of QEMU */ +#define USBAUDIO_PRODUCT_NUM0x0002 + +#define DEV_CONFIG_VALUE1 /* The one and only */ + +/* Descriptor subtypes for AC interfaces */ +#define DST_AC_HEADER 1 +#define DST_AC_INPUT_TERMINAL 2 +#define DST_AC_OUTPUT_TERMINAL 3 +#define DST_AC_FEATURE_UNIT 6 +/* Descriptor subtypes for AS interfaces */ +#define DST_AS_GENERAL 1 +#define DST_AS_FORMAT_TYPE 2 +/* Descriptor subtypes for endpoints */ +#define DST_EP_GENERAL 1 + +enum usb_audio_strings { +STRING_NULL, +STRING_MANUFACTURER, +STRING_PRODUCT, +STRING_SERIALNUMBER, +STRING_CONFIG, +STRING_USBAUDIO_CONTROL, +STRING_INPUT_TERMINAL, +STRING_FEATURE_UNIT, +STRING_OUTPUT_TERMINAL, +STRING_NULL_STREAM, +STRING_REAL_STREAM, +}; + +static const USBDescStrings usb_audio_stringtable = { +[STRING_MANUFACTURER] = QEMU, +[STRING_PRODUCT]= QEMU USB Audio, +[STRING_SERIALNUMBER] = 1, +[STRING_CONFIG] = Audio Configuration, +[STRING_USBAUDIO_CONTROL] = Audio Device, +[STRING_INPUT_TERMINAL] = Audio Output Pipe, +[STRING_FEATURE_UNIT] = Audio Output Volume Control, +[STRING_OUTPUT_TERMINAL]= Audio Output Terminal, +[STRING_NULL_STREAM]= Audio Output - Disabled, +[STRING_REAL_STREAM]= Audio Output - 48 kHz Stereo, +}; + +#define U16(x) ((x) 0xff), (((x) 8) 0xff) +#define U24(x) U16(x), (((x) 16) 0xff) +#define U32(x) U24(x), (((x) 24) 0xff) + +/* + * A Basic Audio Device uses these specific values + */ +#define USBAUDIO_PACKET_SIZE 192 +#define USBAUDIO_SAMPLE_RATE 48000 +#define USBAUDIO_PACKET_INTERVAL 1 + +static const USBDescIface desc_iface[] = { +{ +.bInterfaceNumber = 0, +.bNumEndpoints = 0, +.bInterfaceClass = USB_CLASS_AUDIO, +.bInterfaceSubClass= USB_SUBCLASS_AUDIO_CONTROL, +.bInterfaceProtocol
Re: [Qemu-devel] [PATCH 03/30] ppc: remove ppc440 bamboo board support
On 01/13/2012 12:04 PM, Andreas Färber wrote: This board never worked with TCG. It hasn't been updated since 0.13.0. I'm fairly sure hardware doesn't exist anymore that you can run the KVM support with. It does exist, I have one:-) Alex has already posted series to not only qdev'ify it but to also add TCG support so other people can test it. Review and testing would probably be appreciated.:) The work that you guys are putting in modernizing the PPC boards is really cool. Please, let's start working on the 1.1 changelog now so that it doesn't get lost! Paolo
Re: [Qemu-devel] [PATCH] do not chdir(/) in qemu-nbd
On Fri, Jan 13, 2012 at 9:04 AM, Michael Tokarev m...@tls.msk.ru wrote: When qemu-nbd becomes a daemon it calls daemon(3) with nochdir=0, so daemon(3) changes current directory to /. But at this time, qemu-nbd did not open any user-specified files yet, so by changing current directory, all non-absolute paths becomes wrong. The solution is to pass nochdir=1 to daemon(3) function. It's polite to chdir(/) so that file systems can be unmounted (even more important when chroot was involved, but I think qemu-nbd doesn't do that). Is it possible to manually do a chdir(/) later on after we've opened necessary files? Stefan
Re: [Qemu-devel] [PATCH 0/3] acpi_piix4: Add CPU eject handling
On 2012-01-13 12:11, Vasilis Liaskovitis wrote: This patch series adds support for CPU _EJ0 callback in Seabios and qemu-kvm. The first patch defines the CPU eject bitmap in Seabios and writes to it during the callback. The second patch adds empty stub functions to qemu-kvm to handle the bitmap writes. Please work against upstream (uq/master for kvm-related patches), not qemu-kvm. It possibly makes no technical difference here, but we do not want to let the code bases needlessly diverge again. If if does make a difference and upstream lacks further bits, push them first. Thanks, Jan -- Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
Re: [Qemu-devel] [PATCH 3/3] acpi_piix4: Call KVM_SETSTATE_VCPU ioctl on cpu ejection
On 2012-01-13 12:11, Vasilis Liaskovitis wrote: Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com --- hw/acpi_piix4.c | 21 + 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 8bf30dd..12eef55 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -502,6 +502,27 @@ static uint32_t cpuej_read(void *opaque, uint32_t addr) static void cpuej_write(void *opaque, uint32_t addr, uint32_t val) { +struct kvm_vcpu_state state; +CPUState *env; +int cpu; +int ret; + +cpu = ffs(val); +/* zero means no bit was set, i.e. no CPU ejection happened */ +if (!cpu) + return; +cpu--; +env = cpu_phyid_to_cpu((uint64_t)cpu); +if (env != NULL) { +if (env-state == CPU_STATE_ZAPREQ) { +state.vcpu_id = env-cpu_index; +state.state = 1; +ret = kvm_vm_ioctl(env-kvm_state, KVM_SETSTATE_VCPU, state); That breaks in the absence of KVM or if it is not enabled. Also, where was this IOCTL introduced? Where are the linux header changes? +if (ret) +fprintf(stderr, KVM_SETSTATE_VCPU failed: %s\n, +strerror(ret)); +} +} PIIX4_DPRINTF(cpuej write %x == %d\n, addr, val); } Jan -- Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
[Qemu-devel] [PATCH 15/17] usb-redir: Pre-fill our isoc input buffer before sending pkts to the host
From: Hans de Goede hdego...@redhat.com This is something which should have been done from the first version of usb-redir, but wasn't. Signed-off-by: Hans de Goede hdego...@redhat.com Signed-off-by: Gerd Hoffmann kra...@redhat.com --- usb-redir.c | 16 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/usb-redir.c b/usb-redir.c index 99a12d5..cdd929a 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -60,7 +60,9 @@ struct endp_data { uint8_t iso_error; /* For reporting iso errors to the HC */ uint8_t interrupt_started; uint8_t interrupt_error; +uint8_t bufpq_prefilled; QTAILQ_HEAD(, buf_packet) bufpq; +int bufpq_size; int bufpq_target_size; }; @@ -296,6 +298,7 @@ static struct buf_packet *bufp_alloc(USBRedirDevice *dev, bufp-len= len; bufp-status = status; QTAILQ_INSERT_TAIL(dev-endpoint[EP2I(ep)].bufpq, bufp, next); +dev-endpoint[EP2I(ep)].bufpq_size++; return bufp; } @@ -303,6 +306,7 @@ static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp, uint8_t ep) { QTAILQ_REMOVE(dev-endpoint[EP2I(ep)].bufpq, bufp, next); +dev-endpoint[EP2I(ep)].bufpq_size--; free(bufp-data); g_free(bufp); } @@ -374,14 +378,26 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, usbredirparser_do_write(dev-parser); DPRINTF(iso stream started ep %02X\n, ep); dev-endpoint[EP2I(ep)].iso_started = 1; +dev-endpoint[EP2I(ep)].bufpq_prefilled = 0; } if (ep USB_DIR_IN) { struct buf_packet *isop; +if (dev-endpoint[EP2I(ep)].iso_started +!dev-endpoint[EP2I(ep)].bufpq_prefilled) { +if (dev-endpoint[EP2I(ep)].bufpq_size +dev-endpoint[EP2I(ep)].bufpq_target_size) { +return usbredir_handle_status(dev, 0, 0); +} +dev-endpoint[EP2I(ep)].bufpq_prefilled = 1; +} + isop = QTAILQ_FIRST(dev-endpoint[EP2I(ep)].bufpq); if (isop == NULL) { DPRINTF2(iso-token-in ep %02X, no isop\n, ep); +/* Re-fill the buffer */ +dev-endpoint[EP2I(ep)].bufpq_prefilled = 0; /* Check iso_error for stream errors, otherwise its an underrun */ status = dev-endpoint[EP2I(ep)].iso_error; dev-endpoint[EP2I(ep)].iso_error = 0; -- 1.7.1
[Qemu-devel] [PATCH 13/17] usb-redir: Clear iso / irq error when stopping the stream
From: Hans de Goede hdego...@redhat.com And ignore status messages from the client which arrive after stream stop (the stream stop send to the client and an error status reported by the client my cross each other due to network latency). Signed-off-by: Hans de Goede hdego...@redhat.com Signed-off-by: Gerd Hoffmann kra...@redhat.com --- usb-redir.c |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/usb-redir.c b/usb-redir.c index 2b53cf3..81a35c6 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -410,6 +410,7 @@ static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep) DPRINTF(iso stream stopped ep %02X\n, ep); dev-endpoint[EP2I(ep)].iso_started = 0; } +dev-endpoint[EP2I(ep)].iso_error = 0; usbredir_free_bufpq(dev, ep); } @@ -522,6 +523,7 @@ static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev, DPRINTF(interrupt recv stopped ep %02X\n, ep); dev-endpoint[EP2I(ep)].interrupt_started = 0; } +dev-endpoint[EP2I(ep)].interrupt_error = 0; usbredir_free_bufpq(dev, ep); } @@ -1029,7 +1031,7 @@ static void usbredir_iso_stream_status(void *priv, uint32_t id, DPRINTF(iso status %d ep %02X id %u\n, iso_stream_status-status, ep, id); -if (!dev-dev.attached) { +if (!dev-dev.attached || !dev-endpoint[EP2I(ep)].iso_started) { return; } @@ -1050,7 +1052,7 @@ static void usbredir_interrupt_receiving_status(void *priv, uint32_t id, DPRINTF(interrupt recv status %d ep %02X id %u\n, interrupt_receiving_status-status, ep, id); -if (!dev-dev.attached) { +if (!dev-dev.attached || !dev-endpoint[EP2I(ep)].interrupt_started) { return; } -- 1.7.1
[Qemu-devel] [PATCH 01/17] usb-host: rip out legacy procfs support
This patch removes support for parsing /proc/bus/usb/devices for device discovery. The code lacks a few features compared to the sysfs code and is also bitrotting as everybody has sysfs these days. This implies having sysfs mounted is mandatory now to use the usb-host driver. udev isn't required though. qemu will prefer the udev-managed device nodes below /dev/bus/usb, but in case this directory isn't preset qemu will use the device nodes below /proc/bus/usb (default usbfs mount point). Bottom line: make sure you have both sysfs and usbfs mounted properly, and everything should continue to work as it did before. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- usb-linux.c | 327 --- 1 files changed, 42 insertions(+), 285 deletions(-) diff --git a/usb-linux.c b/usb-linux.c index 749ce71..c68e194 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -66,23 +66,9 @@ typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port, #define DPRINTF(...) #endif -#define USBDBG_DEVOPENED husb: opened %s/devices\n - -#define USBPROCBUS_PATH /proc/bus/usb #define PRODUCT_NAME_SZ 32 #define MAX_ENDPOINTS 15 #define MAX_PORTLEN 16 -#define USBDEVBUS_PATH /dev/bus/usb -#define USBSYSBUS_PATH /sys/bus/usb - -static char *usb_host_device_path; - -#define USB_FS_NONE 0 -#define USB_FS_PROC 1 -#define USB_FS_DEV 2 -#define USB_FS_SYS 3 - -static int usb_fs_type; /* endpoint association data */ #define ISO_FRAME_DESC_PER_URB 32 @@ -431,6 +417,31 @@ static void usb_host_async_cancel(USBDevice *dev, USBPacket *p) } } +static int usb_host_open_device(int bus, int addr) +{ +const char *usbfs = NULL; +char filename[32]; +struct stat st; +int fd, rc; + +rc = stat(/dev/bus/usb, st); +if (rc == 0 S_ISDIR(st.st_mode)) { +/* udev-created device nodes available */ +usbfs = /dev/bus/usb; +} else { +/* fallback: usbfs mounted below /proc */ +usbfs = /proc/bus/usb; +} + +snprintf(filename, sizeof(filename), %s/%03d/%03d, + usbfs, bus, addr); +fd = open(filename, O_RDWR | O_NONBLOCK); +if (fd 0) { +fprintf(stderr, husb: open %s: %s\n, filename, strerror(errno)); +} +return fd; +} + static int usb_host_claim_port(USBHostDevice *s) { #ifdef USBDEVFS_CLAIM_PORT @@ -460,12 +471,7 @@ static int usb_host_claim_port(USBHostDevice *s) return -1; } -if (!usb_host_device_path) { -return -1; -} -snprintf(line, sizeof(line), %s/%03d/%03d, - usb_host_device_path, s-match.bus_num, hub_addr); -s-hub_fd = open(line, O_RDWR | O_NONBLOCK); +s-hub_fd = usb_host_open_device(s-match.bus_num, hub_addr); if (s-hub_fd 0) { return -1; } @@ -522,10 +528,6 @@ static int usb_linux_get_num_interfaces(USBHostDevice *s) char device_name[64], line[1024]; int num_interfaces = 0; -if (usb_fs_type != USB_FS_SYS) { -return -1; -} - sprintf(device_name, %d-%s, s-bus_num, s-port); if (!usb_host_read_file(line, sizeof(line), bNumInterfaces, device_name)) { @@ -1090,41 +1092,21 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, static uint8_t usb_linux_get_alt_setting(USBHostDevice *s, uint8_t configuration, uint8_t interface) { -uint8_t alt_setting; -struct usb_ctrltransfer ct; -int ret; - -if (usb_fs_type == USB_FS_SYS) { -char device_name[64], line[1024]; -int alt_setting; +char device_name[64], line[1024]; +int alt_setting; -sprintf(device_name, %d-%s:%d.%d, s-bus_num, s-port, -(int)configuration, (int)interface); +sprintf(device_name, %d-%s:%d.%d, s-bus_num, s-port, +(int)configuration, (int)interface); -if (!usb_host_read_file(line, sizeof(line), bAlternateSetting, -device_name)) { -goto usbdevfs; -} -if (sscanf(line, %d, alt_setting) != 1) { -goto usbdevfs; -} -return alt_setting; -} - -usbdevfs: -ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE; -ct.bRequest = USB_REQ_GET_INTERFACE; -ct.wValue = 0; -ct.wIndex = interface; -ct.wLength = 1; -ct.data = alt_setting; -ct.timeout = 50; -ret = ioctl(s-fd, USBDEVFS_CONTROL, ct); -if (ret 0) { +if (!usb_host_read_file(line, sizeof(line), bAlternateSetting, +device_name)) { +/* Assume alt 0 on error */ +return 0; +} +if (sscanf(line, %d, alt_setting) != 1) { /* Assume alt 0 on error */ return 0; } - return alt_setting; } @@ -1273,7 +1255,6 @@ static int usb_host_open(USBHostDevice *dev, int bus_num, const char *prod_name, int speed) { int fd = -1, ret; -char buf[1024]; trace_usb_host_open_started(bus_num, addr); @@
[Qemu-devel] [PATCH 04/17] usb-desc: audio endpoint support
Add support for audio endpoints which have two more fields in the descriptor. Also add support for extra class specific endpoint descriptors. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb-desc.c | 14 +++--- hw/usb-desc.h |5 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/hw/usb-desc.c b/hw/usb-desc.c index b9996a1..9c38661 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -192,9 +192,10 @@ int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len) int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len) { -uint8_t bLength = 0x07; +uint8_t bLength = ep-is_audio ? 0x09 : 0x07; +uint8_t extralen = ep-extra ? ep-extra[0] : 0; -if (len bLength) { +if (len bLength + extralen) { return -1; } @@ -205,8 +206,15 @@ int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len) dest[0x04] = usb_lo(ep-wMaxPacketSize); dest[0x05] = usb_hi(ep-wMaxPacketSize); dest[0x06] = ep-bInterval; +if (ep-is_audio) { +dest[0x07] = ep-bRefresh; +dest[0x08] = ep-bSynchAddress; +} +if (ep-extra) { +memcpy(dest + bLength, ep-extra, extralen); +} -return bLength; +return bLength + extralen; } int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len) diff --git a/hw/usb-desc.h b/hw/usb-desc.h index 5c14e4a..d6e07ea 100644 --- a/hw/usb-desc.h +++ b/hw/usb-desc.h @@ -71,6 +71,11 @@ struct USBDescEndpoint { uint8_t bmAttributes; uint16_t wMaxPacketSize; uint8_t bInterval; +uint8_t bRefresh; +uint8_t bSynchAddress; + +uint8_t is_audio; /* has bRefresh + bSynchAddress */ +uint8_t *extra; }; struct USBDescOther { -- 1.7.1
[Qemu-devel] [PATCH 10/17] usb/debug: add usb_ep_dump
Add function to dump endpoint data, for debugging purposes. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb.c| 40 hw/usb.h|1 + usb-linux.c |3 +++ 3 files changed, 44 insertions(+), 0 deletions(-) diff --git a/hw/usb.c b/hw/usb.c index 6ba063a..f07cb9d 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -427,6 +427,46 @@ void usb_ep_init(USBDevice *dev) } } +void usb_ep_dump(USBDevice *dev) +{ +static const char *tname[] = { +[USB_ENDPOINT_XFER_CONTROL] = control, +[USB_ENDPOINT_XFER_ISOC]= isoc, +[USB_ENDPOINT_XFER_BULK]= bulk, +[USB_ENDPOINT_XFER_INT] = int, +}; +int ifnum, ep, first; + +fprintf(stderr, Device \%s\, config %d\n, +dev-product_desc, dev-configuration); +for (ifnum = 0; ifnum 16; ifnum++) { +first = 1; +for (ep = 0; ep USB_MAX_ENDPOINTS; ep++) { +if (dev-ep_in[ep].type != USB_ENDPOINT_XFER_INVALID +dev-ep_in[ep].ifnum == ifnum) { +if (first) { +first = 0; +fprintf(stderr, Interface %d, alternative %d\n, +ifnum, dev-altsetting[ifnum]); +} +fprintf(stderr, Endpoint %d, IN, %s\n, ep, +tname[dev-ep_in[ep].type]); +} +if (dev-ep_out[ep].type != USB_ENDPOINT_XFER_INVALID +dev-ep_out[ep].ifnum == ifnum) { +if (first) { +first = 0; +fprintf(stderr, Interface %d, alternative %d\n, +ifnum, dev-altsetting[ifnum]); +} +fprintf(stderr, Endpoint %d, OUT, %s\n, ep, +tname[dev-ep_out[ep].type]); +} +} +} +fprintf(stderr, --\n); +} + struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep) { struct USBEndpoint *eps = pid == USB_TOKEN_IN ? dev-ep_in : dev-ep_out; diff --git a/hw/usb.h b/hw/usb.h index 60e8858..c35ff74 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -333,6 +333,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p); void usb_cancel_packet(USBPacket * p); void usb_ep_init(USBDevice *dev); +void usb_ep_dump(USBDevice *dev); struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep); uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep); uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep); diff --git a/usb-linux.c b/usb-linux.c index cb66ef3..2a7b748 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -1214,6 +1214,9 @@ static int usb_linux_update_endp_table(USBHostDevice *s) i += descriptors[i]; } } +#ifdef DEBUG +usb_ep_dump(s-dev); +#endif return 0; } -- 1.7.1
[Qemu-devel] [PATCH 08/17] usb: add ifnum to USBEndpoint
Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb.c| 14 ++ hw/usb.h|3 +++ usb-linux.c |1 + 3 files changed, 18 insertions(+), 0 deletions(-) diff --git a/hw/usb.c b/hw/usb.c index 5d6baaf..6ba063a 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -422,6 +422,8 @@ void usb_ep_init(USBDevice *dev) for (ep = 0; ep USB_MAX_ENDPOINTS; ep++) { dev-ep_in[ep].type = USB_ENDPOINT_XFER_INVALID; dev-ep_out[ep].type = USB_ENDPOINT_XFER_INVALID; +dev-ep_in[ep].ifnum = 0; +dev-ep_out[ep].ifnum = 0; } } @@ -444,3 +446,15 @@ void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type) struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); uep-type = type; } + +uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep) +{ +struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); +return uep-ifnum; +} + +void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum) +{ +struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); +uep-ifnum = ifnum; +} diff --git a/hw/usb.h b/hw/usb.h index 85cbe71..60e8858 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -175,6 +175,7 @@ struct USBDescString { struct USBEndpoint { uint8_t type; +uint8_t ifnum; }; /* definition of a USB device */ @@ -334,7 +335,9 @@ void usb_cancel_packet(USBPacket * p); void usb_ep_init(USBDevice *dev); struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep); uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep); +uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep); void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type); +void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum); void usb_attach(USBPort *port); void usb_detach(USBPort *port); diff --git a/usb-linux.c b/usb-linux.c index 9967975..cb66ef3 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -1206,6 +1206,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s) assert(usb_ep_get_type(s-dev, pid, ep) == USB_ENDPOINT_XFER_INVALID); usb_ep_set_type(s-dev, pid, ep, type); +usb_ep_set_ifnum(s-dev, pid, ep, interface); epd = get_endp(s, pid, ep); epd-halted = 0; -- 1.7.1
[Qemu-devel] [PATCH 03/17] usb: track altsetting in USBDevice
Also handle {GET,SET}_INTERFACE in common code (usb-desc.c). Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb-bt.c | 22 - hw/usb-ccid.c |8 -- hw/usb-desc.c | 71 +++ hw/usb-hid.c|7 - hw/usb-hub.c|7 - hw/usb-msd.c| 10 --- hw/usb-net.c| 11 hw/usb-serial.c |7 - hw/usb-wacom.c |7 - hw/usb.h|8 ++ trace-events|1 + usb-linux.c | 10 +++ 12 files changed, 90 insertions(+), 79 deletions(-) diff --git a/hw/usb-bt.c b/hw/usb-bt.c index f30eec1..0c1270b 100644 --- a/hw/usb-bt.c +++ b/hw/usb-bt.c @@ -28,7 +28,6 @@ struct USBBtState { USBDevice dev; struct HCIInfo *hci; -int altsetting; int config; #define CFIFO_LEN_MASK 255 @@ -362,7 +361,6 @@ static void usb_bt_handle_reset(USBDevice *dev) s-outcmd.len = 0; s-outacl.len = 0; s-outsco.len = 0; -s-altsetting = 0; } static int usb_bt_handle_control(USBDevice *dev, USBPacket *p, @@ -402,26 +400,6 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p, case EndpointOutRequest | USB_REQ_SET_FEATURE: goto fail; break; -case InterfaceRequest | USB_REQ_GET_INTERFACE: -if (value != 0 || (index ~1) || length != 1) -goto fail; -if (index == 1) -data[0] = s-altsetting; -else -data[0] = 0; -ret = 1; -break; -case InterfaceOutRequest | USB_REQ_SET_INTERFACE: -if ((index ~1) || length != 0 || -(index == 1 (value 0 || value 4)) || -(index == 0 value != 0)) { -printf(%s: Wrong SET_INTERFACE request (%i, %i)\n, -__FUNCTION__, index, value); -goto fail; -} -s-altsetting = value; -ret = 0; -break; case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) 8): if (s-config) usb_bt_fifo_out_enqueue(s, s-outcmd, s-hci-cmd_send, diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c index cd349f3..e9935ad 100644 --- a/hw/usb-ccid.c +++ b/hw/usb-ccid.c @@ -611,14 +611,6 @@ static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request, } switch (request) { -case DeviceRequest | USB_REQ_GET_INTERFACE: -data[0] = 0; -ret = 1; -break; -case InterfaceOutRequest | USB_REQ_SET_INTERFACE: -ret = 0; -break; - /* Class specific requests. */ case InterfaceOutClass | CCID_CONTROL_ABORT: DPRINTF(s, 1, ccid_control abort UNIMPLEMENTED\n); diff --git a/hw/usb-desc.c b/hw/usb-desc.c index b52561a..b9996a1 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -223,6 +223,54 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len) /* -- */ +static const USBDescIface *usb_desc_find_interface(USBDevice *dev, + int nif, int alt) +{ +const USBDescIface *iface; +int g, i; + +if (!dev-config) { +return NULL; +} +for (g = 0; g dev-config-nif_groups; g++) { +for (i = 0; i dev-config-if_groups[g].nif; i++) { +iface = dev-config-if_groups[g].ifs[i]; +if (iface-bInterfaceNumber == nif +iface-bAlternateSetting == alt) { +return iface; +} +} +} +for (i = 0; i dev-config-nif; i++) { +iface = dev-config-ifs[i]; +if (iface-bInterfaceNumber == nif +iface-bAlternateSetting == alt) { +return iface; +} +} +return NULL; +} + +static int usb_desc_set_interface(USBDevice *dev, int index, int value) +{ +const USBDescIface *iface; +int old; + +iface = usb_desc_find_interface(dev, index, value); +if (iface == NULL) { +return -1; +} + +old = dev-altsetting[index]; +dev-altsetting[index] = value; +dev-ifaces[index] = iface; + +if (dev-info-set_interface old != value) { +dev-info-set_interface(dev, index, old, value); +} +return 0; +} + static int usb_desc_set_config(USBDevice *dev, int value) { int i; @@ -237,12 +285,22 @@ static int usb_desc_set_config(USBDevice *dev, int value) dev-configuration = value; dev-ninterfaces = dev-device-confs[i].bNumInterfaces; dev-config = dev-device-confs + i; +assert(dev-ninterfaces = USB_MAX_INTERFACES); } } if (i dev-device-bNumConfigurations) { return -1; } } + +for (i = 0; i dev-ninterfaces; i++) { +usb_desc_set_interface(dev, i, 0); +} +for (; i USB_MAX_INTERFACES; i++) { +dev-altsetting[i] = 0; +dev-ifaces[i] = NULL; +} + return 0;
[Qemu-devel] [PATCH 09/17] usb-desc: USBEndpoint support
Initialize USBEndpoint structs from USBDesc* data. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb-desc.c | 22 ++ 1 files changed, 22 insertions(+), 0 deletions(-) diff --git a/hw/usb-desc.c b/hw/usb-desc.c index 9c38661..0768334 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -231,6 +231,27 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len) /* -- */ +static void usb_desc_ep_init(USBDevice *dev) +{ +const USBDescIface *iface; +int i, e, pid, ep; + +usb_ep_init(dev); +for (i = 0; i dev-ninterfaces; i++) { +iface = dev-ifaces[i]; +if (iface == NULL) { +continue; +} +for (e = 0; e iface-bNumEndpoints; e++) { +pid = (iface-eps[e].bEndpointAddress USB_DIR_IN) ? +USB_TOKEN_IN : USB_TOKEN_OUT; +ep = iface-eps[e].bEndpointAddress 0x0f; +usb_ep_set_type(dev, pid, ep, iface-eps[e].bmAttributes 0x03); +usb_ep_set_ifnum(dev, pid, ep, iface-bInterfaceNumber); +} +} +} + static const USBDescIface *usb_desc_find_interface(USBDevice *dev, int nif, int alt) { @@ -272,6 +293,7 @@ static int usb_desc_set_interface(USBDevice *dev, int index, int value) old = dev-altsetting[index]; dev-altsetting[index] = value; dev-ifaces[index] = iface; +usb_desc_ep_init(dev); if (dev-info-set_interface old != value) { dev-info-set_interface(dev, index, old, value); -- 1.7.1
Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
On 11 January 2012 22:41, Peter Maydell peter.mayd...@linaro.org wrote: On 11 January 2012 16:31, Mark Langsdorf mark.langsd...@calxeda.com wrote: This patch series adds support for the Calxeda Highbank SoC. It depends on my previous patch series various ARM fixes for Calxeda Highbank and ahci: convert ahci_reset to use AHCIState. Some of the patches are carried over from Various ARM fixes for Calxeda Highbank and were reviewed but not accepted in that series. So, are there in fact any patches from the various ARM fixes for Calxeda Highbank series which this series depends on and which haven't been committed to master? It looks to me as if all the patches from that series either (a) were put into this one or (b) were committed, but did I miss anything? Mark: ping? I'm just waiting for an answer to this and also to the question about the secondary boot protocol (see my email replying to patch 5/5) before I take these into arm-devs.next... Does anybody object to my taking the AHCI patches along with this series via arm-devs.next ? (other than patch v4 which goes via target-arm.next) [I got an Acked-by: from Kevin over irc regarding these and will do this.] -- PMM
Re: [Qemu-devel] [PATCH v2] qemu-ga: add guest-set-support-level command
On Thu, 12 Jan 2012 17:32:32 -0600 Michael Roth mdr...@linux.vnet.ibm.com wrote: On 01/12/2012 12:57 PM, Luiz Capitulino wrote: On Wed, 11 Jan 2012 17:56:05 -0600 Michael Rothmdr...@linux.vnet.ibm.com wrote: Recently commands where introduced on the mailing that involved adding commands to the guest agent that could potentially break older versions of QEMU. While it's okay to expect that qemu-ga can be updated to support newer host features, it's unrealistic to require a host to be updated to support qemu-ga features, or to expect that qemu-ga should be downgraded in these circumstances, especially considering that a large mix of guests/agents may be running on a particular host. To address this, we introduce here a mechanism to set qemu-ga's feature-set to one that is known to be compatible with the host/QEMU running the guest. As new commands/options are added, we can maintain backward-compatibility by adding conditional checks to filter out host-incompatible functionality based on the host-specified support level (generally analogous to the host QEMU version) set by the client. The current default/minimum support level supports all versions of QEMU that have had qemu-ga in-tree (0.15.0, 1.0.0) and so should be backward-compatible with existing hosts/clients. The approach looks fine to me. I have a few review comments below. Signed-off-by: Michael Rothmdr...@linux.vnet.ibm.com --- qapi-schema-guest.json | 31 - qemu-ga.c | 46 qga/guest-agent-commands.c | 13 qga/guest-agent-core.h | 11 ++ 4 files changed, 100 insertions(+), 1 deletions(-) diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json index 5f8a18d..32bc041 100644 --- a/qapi-schema-guest.json +++ b/qapi-schema-guest.json @@ -43,15 +43,44 @@ # # Since: 0.15.0 ## +{ 'type': 'GuestAgentSupportLevel', + 'data': { 'major': 'int', 'minor': 'int', 'micro': 'int' } } This and GuestAgentCommandInfo are missing good documentation. Looks like we don't document types as we do in qapi-schema.json. I think we should. Agreed, I'll precede this with a patch to add the documentation for existing types, and update this patch accordingly. { 'type': 'GuestAgentCommandInfo', 'data': { 'name': 'str', 'enabled': 'bool' } } { 'type': 'GuestAgentInfo', 'data': { 'version': 'str', -'supported_commands': ['GuestAgentCommandInfo'] } } +'supported_commands': ['GuestAgentCommandInfo'] +'support_level': 'GuestAgentSupportLevel' } } { 'command': 'guest-info', 'returns': 'GuestAgentInfo' } For example, something important that's is not totally clear to me just by reading the command definition is if 'support_level' refers to the support level that can be changed by a client. ## +# @guest-set-support-level: +# +# Set guest agent feature-set to one that is compatible with/supported by +# the host. +# +# Certain commands/options may have dependencies on host +# version/support-level, such as specific QEMU features (such +# dependencies will be noted in this schema). By default we assume 1.0.0, +# which is backward-compatible with QEMU 0.15.0/1.0, and should be compatible +# with later versions of QEMU as well. To enable newer guest agent features, +# this command must be issued to raise the support-level to one corresponding +# to supported host QEMU/KVM/etc capabilities. +# +# The currently set support level is obtainable via the guest-info command. +# +# @level: Desired host support-level, generally= host QEMU version +# level. Note that undefined behavior may occur if a support-level is +# provided that exceeds the capabilities of the version of QEMU currently +# running the guest. It's also better to note that if @level 1.0.0 then the support level will be set to 1.0.0. I must've looked at this like 5 times and made a mental note to do that, but in the end it escaped me... Hehe, happens. There's one more issue below. +# +# Returns: Nothing on success +# +{ 'command': 'guest-set-support-level', + 'data':{ 'major': 'int', 'minor': 'int', '*micro': 'int' } } + +## # @guest-shutdown: # # Initiate guest-activated shutdown. Note: this is an asynchronous diff --git a/qemu-ga.c b/qemu-ga.c index 200bb15..6840233 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -28,6 +28,7 @@ #include qerror.h #include error_int.h #include qapi/qmp-core.h +#include qga-qapi-types.h #define QGA_VIRTIO_PATH_DEFAULT /dev/virtio-ports/org.qemu.guest_agent.0 #define QGA_PIDFILE_DEFAULT /var/run/qemu-ga.pid @@ -102,6 +103,45 @@ static void usage(const char *cmd) static void conn_channel_close(GAState *s); +static
Re: [Qemu-devel] [PATCH 03/30] ppc: remove ppc440 bamboo board support
On 13.01.2012, at 12:45, Paolo Bonzini wrote: On 01/13/2012 12:04 PM, Andreas Färber wrote: This board never worked with TCG. It hasn't been updated since 0.13.0. I'm fairly sure hardware doesn't exist anymore that you can run the KVM support with. It does exist, I have one:-) Alex has already posted series to not only qdev'ify it but to also add TCG support so other people can test it. Review and testing would probably be appreciated.:) The work that you guys are putting in modernizing the PPC boards is really cool. Please, let's start working on the 1.1 changelog now so that it doesn't get lost! Good point :). I'm not sure how useful something like Qdev'ified board xxx really is in a changelog though. It's mostly invisible to users. Alex
[Qemu-devel] [PATCH 11/17] usb: add max_packet_size to USBEndpoint
Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb-desc.c |2 ++ hw/usb.c | 37 + hw/usb.h |4 usb-linux.c | 31 +-- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/hw/usb-desc.c b/hw/usb-desc.c index 0768334..b3eb97b 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -248,6 +248,8 @@ static void usb_desc_ep_init(USBDevice *dev) ep = iface-eps[e].bEndpointAddress 0x0f; usb_ep_set_type(dev, pid, ep, iface-eps[e].bmAttributes 0x03); usb_ep_set_ifnum(dev, pid, ep, iface-bInterfaceNumber); +usb_ep_set_max_packet_size(dev, pid, ep, + iface-eps[e].wMaxPacketSize); } } } diff --git a/hw/usb.c b/hw/usb.c index f07cb9d..0f163b4 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -449,8 +449,9 @@ void usb_ep_dump(USBDevice *dev) fprintf(stderr, Interface %d, alternative %d\n, ifnum, dev-altsetting[ifnum]); } -fprintf(stderr, Endpoint %d, IN, %s\n, ep, -tname[dev-ep_in[ep].type]); +fprintf(stderr, Endpoint %d, IN, %s, %d max\n, ep, +tname[dev-ep_in[ep].type], +dev-ep_in[ep].max_packet_size); } if (dev-ep_out[ep].type != USB_ENDPOINT_XFER_INVALID dev-ep_out[ep].ifnum == ifnum) { @@ -459,8 +460,9 @@ void usb_ep_dump(USBDevice *dev) fprintf(stderr, Interface %d, alternative %d\n, ifnum, dev-altsetting[ifnum]); } -fprintf(stderr, Endpoint %d, OUT, %s\n, ep, -tname[dev-ep_out[ep].type]); +fprintf(stderr, Endpoint %d, OUT, %s, %d max\n, ep, +tname[dev-ep_out[ep].type], +dev-ep_out[ep].max_packet_size); } } } @@ -498,3 +500,30 @@ void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum) struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); uep-ifnum = ifnum; } + +void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep, +uint16_t raw) +{ +struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); +int size, microframes; + +size = raw 0x7ff; +switch ((raw 11) 3) { +case 1: +microframes = 2; +break; +case 2: +microframes = 3; +break; +default: +microframes = 1; +break; +} +uep-max_packet_size = size * microframes; +} + +int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep) +{ +struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); +return uep-max_packet_size; +} diff --git a/hw/usb.h b/hw/usb.h index c35ff74..5ea984c 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -176,6 +176,7 @@ struct USBDescString { struct USBEndpoint { uint8_t type; uint8_t ifnum; +int max_packet_size; }; /* definition of a USB device */ @@ -339,6 +340,9 @@ uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep); uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep); void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type); void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum); +void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep, +uint16_t raw); +int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep); void usb_attach(USBPort *port); void usb_detach(USBPort *port); diff --git a/usb-linux.c b/usb-linux.c index 2a7b748..56898dd 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -83,7 +83,6 @@ struct endp_data { AsyncURB *iso_urb; int iso_urb_idx; int iso_buffer_used; -int max_packet_size; int inflight; }; @@ -259,26 +258,6 @@ static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep) return get_endp(s, pid, ep)-iso_buffer_used; } -static void set_max_packet_size(USBHostDevice *s, int pid, int ep, -uint8_t *descriptor) -{ -int raw = descriptor[4] + (descriptor[5] 8); -int size, microframes; - -size = raw 0x7ff; -switch ((raw 11) 3) { -case 1: microframes = 2; break; -case 2: microframes = 3; break; -default: microframes = 1; break; -} -get_endp(s, pid, ep)-max_packet_size = size * microframes; -} - -static int get_max_packet_size(USBHostDevice *s, int pid, int ep) -{ -return get_endp(s, pid, ep)-max_packet_size; -} - /* * Async URB state. * We always allocate iso packet descriptors even for bulk transfers @@ -674,7 +653,7 @@ static void usb_host_handle_destroy(USBDevice *dev) static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep) { AsyncURB *aurb; -int i, j, len = get_max_packet_size(s, pid, ep); +int i, j, len =
[Qemu-devel] [PATCH 12/17] usb: link packets to endpoints not devices
Add USBEndpoint for the control endpoint to USBDevices. Link async packets to the USBEndpoint instead of the USBDevice. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb-ehci.c |3 ++- hw/usb-musb.c |3 ++- hw/usb-ohci.c |4 +++- hw/usb-uhci.c |3 ++- hw/usb.c | 12 ++-- hw/usb.h |4 +++- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index 7c926c0..a305661 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -715,7 +715,8 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev) EHCIQueue *q, *tmp; QTAILQ_FOREACH_SAFE(q, ehci-queues, next, tmp) { -if (q-packet.owner != dev) { +if (q-packet.owner == NULL || +q-packet.owner-dev != dev) { continue; } ehci_free_queue(q); diff --git a/hw/usb-musb.c b/hw/usb-musb.c index 01e2e7c..4f528d2 100644 --- a/hw/usb-musb.c +++ b/hw/usb-musb.c @@ -812,7 +812,8 @@ static void musb_async_cancel_device(MUSBState *s, USBDevice *dev) for (ep = 0; ep 16; ep++) { for (dir = 0; dir 2; dir++) { -if (s-ep[ep].packey[dir].p.owner != dev) { +if (s-ep[ep].packey[dir].p.owner == NULL || +s-ep[ep].packey[dir].p.owner-dev != dev) { continue; } usb_cancel_packet(s-ep[ep].packey[dir].p); diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c index 81488c4..69463d2 100644 --- a/hw/usb-ohci.c +++ b/hw/usb-ohci.c @@ -1707,7 +1707,9 @@ static void ohci_mem_write(void *opaque, static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev) { -if (ohci-async_td ohci-usb_packet.owner == dev) { +if (ohci-async_td +ohci-usb_packet.owner != NULL +ohci-usb_packet.owner-dev == dev) { usb_cancel_packet(ohci-usb_packet); ohci-async_td = 0; } diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index f8912e2..25d4e8c 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -245,7 +245,8 @@ static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev) UHCIAsync *curr, *n; QTAILQ_FOREACH_SAFE(curr, s-async_pending, next, n) { -if (curr-packet.owner != dev) { +if (curr-packet.owner == NULL || +curr-packet.owner-dev != dev) { continue; } uhci_async_unlink(s, curr); diff --git a/hw/usb.c b/hw/usb.c index 0f163b4..860538a 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -329,7 +329,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) ret = dev-info-handle_packet(dev, p); if (ret == USB_RET_ASYNC) { if (p-owner == NULL) { -p-owner = dev; +p-owner = usb_ep_get(dev, p-pid, p-devep); } else { /* We'll end up here when usb_handle_packet is called * recursively due to a hub being in the chain. Nothing @@ -357,7 +357,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) void usb_cancel_packet(USBPacket * p) { assert(p-owner != NULL); -p-owner-info-cancel_packet(p-owner, p); +p-owner-dev-info-cancel_packet(p-owner-dev, p); p-owner = NULL; } @@ -419,11 +419,16 @@ void usb_ep_init(USBDevice *dev) { int ep; +dev-ep_ctl.type = USB_ENDPOINT_XFER_CONTROL; +dev-ep_ctl.ifnum = 0; +dev-ep_ctl.dev = dev; for (ep = 0; ep USB_MAX_ENDPOINTS; ep++) { dev-ep_in[ep].type = USB_ENDPOINT_XFER_INVALID; dev-ep_out[ep].type = USB_ENDPOINT_XFER_INVALID; dev-ep_in[ep].ifnum = 0; dev-ep_out[ep].ifnum = 0; +dev-ep_in[ep].dev = dev; +dev-ep_out[ep].dev = dev; } } @@ -472,6 +477,9 @@ void usb_ep_dump(USBDevice *dev) struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep) { struct USBEndpoint *eps = pid == USB_TOKEN_IN ? dev-ep_in : dev-ep_out; +if (ep == 0) { +return dev-ep_ctl; +} assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT); assert(ep 0 ep = USB_MAX_ENDPOINTS); return eps + ep - 1; diff --git a/hw/usb.h b/hw/usb.h index 5ea984c..0776463 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -177,6 +177,7 @@ struct USBEndpoint { uint8_t type; uint8_t ifnum; int max_packet_size; +USBDevice *dev; }; /* definition of a USB device */ @@ -204,6 +205,7 @@ struct USBDevice { int32_t setup_len; int32_t setup_index; +USBEndpoint ep_ctl; USBEndpoint ep_in[USB_MAX_ENDPOINTS]; USBEndpoint ep_out[USB_MAX_ENDPOINTS]; @@ -317,7 +319,7 @@ struct USBPacket { QEMUIOVector iov; int result; /* transfer length or USB_RET_* status code */ /* Internal use by the USB layer. */ -USBDevice *owner; +USBEndpoint *owner; }; void usb_packet_init(USBPacket *p); -- 1.7.1
[Qemu-devel] [PATCH 14/17] usb-redir: Dynamically adjust iso buffering size based on ep interval
From: Hans de Goede hdego...@redhat.com Note the bufpq_target_size id stored in the endpoint info struct, even though it only used once. This is done because it will be referenced from other code in a follow up patch. Signed-off-by: Hans de Goede hdego...@redhat.com Signed-off-by: Gerd Hoffmann kra...@redhat.com --- usb-redir.c | 53 - 1 files changed, 48 insertions(+), 5 deletions(-) diff --git a/usb-redir.c b/usb-redir.c index 81a35c6..99a12d5 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -61,6 +61,7 @@ struct endp_data { uint8_t interrupt_started; uint8_t interrupt_error; QTAILQ_HEAD(, buf_packet) bufpq; +int bufpq_target_size; }; struct USBRedirDevice { @@ -332,15 +333,42 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, uint8_t ep) { int status, len; - if (!dev-endpoint[EP2I(ep)].iso_started !dev-endpoint[EP2I(ep)].iso_error) { struct usb_redir_start_iso_stream_header start_iso = { .endpoint = ep, -/* TODO maybe do something with these depending on ep interval? */ -.pkts_per_urb = 32, -.no_urbs = 3, }; +int pkts_per_sec; + +if (dev-dev.speed == USB_SPEED_HIGH) { +pkts_per_sec = 8000 / dev-endpoint[EP2I(ep)].interval; +} else { +pkts_per_sec = 1000 / dev-endpoint[EP2I(ep)].interval; +} +/* Testing has shown that we need circa 60 ms buffer */ +dev-endpoint[EP2I(ep)].bufpq_target_size = (pkts_per_sec * 60) / 1000; + +/* Aim for approx 100 interrupts / second on the client to + balance latency and interrupt load */ +start_iso.pkts_per_urb = pkts_per_sec / 100; +if (start_iso.pkts_per_urb 1) { +start_iso.pkts_per_urb = 1; +} else if (start_iso.pkts_per_urb 32) { +start_iso.pkts_per_urb = 32; +} + +start_iso.no_urbs = (dev-endpoint[EP2I(ep)].bufpq_target_size + + start_iso.pkts_per_urb - 1) / +start_iso.pkts_per_urb; +/* Output endpoints pre-fill only 1/2 of the packets, keeping the rest + as overflow buffer. Also see the usbredir protocol documentation */ +if (!(ep USB_DIR_IN)) { +start_iso.no_urbs *= 2; +} +if (start_iso.no_urbs 16) { +start_iso.no_urbs = 16; +} + /* No id, we look at the ep when receiving a status back */ usbredirparser_send_start_iso_stream(dev-parser, 0, start_iso); usbredirparser_do_write(dev-parser); @@ -961,9 +989,24 @@ static void usbredir_ep_info(void *priv, dev-endpoint[i].type = ep_info-type[i]; dev-endpoint[i].interval = ep_info-interval[i]; dev-endpoint[i].interface = ep_info-interface[i]; -if (dev-endpoint[i].type != usb_redir_type_invalid) { +switch (dev-endpoint[i].type) { +case usb_redir_type_invalid: +break; +case usb_redir_type_iso: +case usb_redir_type_interrupt: +if (dev-endpoint[i].interval == 0) { +ERROR(Received 0 interval for isoc or irq endpoint\n); +usbredir_device_disconnect(dev); +} +/* Fall through */ +case usb_redir_type_control: +case usb_redir_type_bulk: DPRINTF(ep: %02X type: %d interface: %d\n, I2EP(i), dev-endpoint[i].type, dev-endpoint[i].interface); +break; +default: +ERROR(Received invalid endpoint type\n); +usbredir_device_disconnect(dev); } } } -- 1.7.1
[Qemu-devel] [PATCH 17/17] usb-redir: Improve some debugging messages
From: Hans de Goede hdego...@redhat.com Signed-off-by: Hans de Goede hdego...@redhat.com Signed-off-by: Gerd Hoffmann kra...@redhat.com --- usb-redir.c | 13 - 1 files changed, 8 insertions(+), 5 deletions(-) diff --git a/usb-redir.c b/usb-redir.c index 147e237..79d29ec 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -395,7 +395,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, /* No id, we look at the ep when receiving a status back */ usbredirparser_send_start_iso_stream(dev-parser, 0, start_iso); usbredirparser_do_write(dev-parser); -DPRINTF(iso stream started ep %02X\n, ep); +DPRINTF(iso stream started pkts/sec %d pkts/urb %d urbs %d ep %02X\n, +pkts_per_sec, start_iso.pkts_per_urb, start_iso.no_urbs, ep); dev-endpoint[EP2I(ep)].iso_started = 1; dev-endpoint[EP2I(ep)].bufpq_prefilled = 0; dev-endpoint[EP2I(ep)].bufpq_dropping_packets = 0; @@ -415,7 +416,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, isop = QTAILQ_FIRST(dev-endpoint[EP2I(ep)].bufpq); if (isop == NULL) { -DPRINTF2(iso-token-in ep %02X, no isop\n, ep); +DPRINTF(iso-token-in ep %02X, no isop, iso_error: %d\n, +ep, dev-endpoint[EP2I(ep)].iso_error); /* Re-fill the buffer */ dev-endpoint[EP2I(ep)].bufpq_prefilled = 0; /* Check iso_error for stream errors, otherwise its an underrun */ @@ -423,8 +425,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, dev-endpoint[EP2I(ep)].iso_error = 0; return usbredir_handle_status(dev, status, 0); } -DPRINTF2(iso-token-in ep %02X status %d len %d\n, ep, isop-status, - isop-len); +DPRINTF2(iso-token-in ep %02X status %d len %d queue-size: %d\n, ep, + isop-status, isop-len, dev-endpoint[EP2I(ep)].bufpq_size); status = isop-status; if (status != usb_redir_success) { @@ -434,7 +436,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, len = isop-len; if (len p-iov.size) { -ERROR(received iso data is larger then packet ep %02X\n, ep); +ERROR(received iso data is larger then packet ep %02X (%d %d)\n, + ep, len, (int)p-iov.size); bufp_free(dev, isop, ep); return USB_RET_NAK; } -- 1.7.1
[Qemu-devel] [PATCH 07/17] usb: add USBEndpoint
Start maintaining endpoint state at USBDevice level. Add USBEndpoint struct and some helper functions to deal with it. For now it contains the endpoint type only. Moved over some bits from usb-linux.c Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb-bus.c |1 + hw/usb.c | 30 +++ hw/usb.h | 14 usb-linux.c | 63 ++--- 4 files changed, 74 insertions(+), 34 deletions(-) diff --git a/hw/usb-bus.c b/hw/usb-bus.c index bd4afa7..016a3f2 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -75,6 +75,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) dev-info = info; dev-auto_attach = 1; QLIST_INIT(dev-strings); +usb_ep_init(dev); rc = usb_claim_port(dev); if (rc != 0) { return rc; diff --git a/hw/usb.c b/hw/usb.c index 2216efe..5d6baaf 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -414,3 +414,33 @@ void usb_packet_cleanup(USBPacket *p) { qemu_iovec_destroy(p-iov); } + +void usb_ep_init(USBDevice *dev) +{ +int ep; + +for (ep = 0; ep USB_MAX_ENDPOINTS; ep++) { +dev-ep_in[ep].type = USB_ENDPOINT_XFER_INVALID; +dev-ep_out[ep].type = USB_ENDPOINT_XFER_INVALID; +} +} + +struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep) +{ +struct USBEndpoint *eps = pid == USB_TOKEN_IN ? dev-ep_in : dev-ep_out; +assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT); +assert(ep 0 ep = USB_MAX_ENDPOINTS); +return eps + ep - 1; +} + +uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep) +{ +struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); +return uep-type; +} + +void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type) +{ +struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); +uep-type = type; +} diff --git a/hw/usb.h b/hw/usb.h index b2c9479..85cbe71 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -144,6 +144,7 @@ #define USB_ENDPOINT_XFER_ISOC 1 #define USB_ENDPOINT_XFER_BULK 2 #define USB_ENDPOINT_XFER_INT 3 +#define USB_ENDPOINT_XFER_INVALID 255 typedef struct USBBus USBBus; typedef struct USBBusOps USBBusOps; @@ -151,6 +152,7 @@ typedef struct USBPort USBPort; typedef struct USBDevice USBDevice; typedef struct USBDeviceInfo USBDeviceInfo; typedef struct USBPacket USBPacket; +typedef struct USBEndpoint USBEndpoint; typedef struct USBDesc USBDesc; typedef struct USBDescID USBDescID; @@ -171,6 +173,10 @@ struct USBDescString { #define USB_MAX_ENDPOINTS 15 #define USB_MAX_INTERFACES 16 +struct USBEndpoint { +uint8_t type; +}; + /* definition of a USB device */ struct USBDevice { DeviceState qdev; @@ -196,6 +202,9 @@ struct USBDevice { int32_t setup_len; int32_t setup_index; +USBEndpoint ep_in[USB_MAX_ENDPOINTS]; +USBEndpoint ep_out[USB_MAX_ENDPOINTS]; + QLIST_HEAD(, USBDescString) strings; const USBDescDevice *device; @@ -322,6 +331,11 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p); void usb_packet_complete(USBDevice *dev, USBPacket *p); void usb_cancel_packet(USBPacket * p); +void usb_ep_init(USBDevice *dev); +struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep); +uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep); +void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type); + void usb_attach(USBPort *port); void usb_detach(USBPort *port); void usb_reset(USBPort *port); diff --git a/usb-linux.c b/usb-linux.c index ded0726..9967975 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -67,12 +67,10 @@ typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port, #endif #define PRODUCT_NAME_SZ 32 -#define MAX_ENDPOINTS 15 #define MAX_PORTLEN 16 /* endpoint association data */ #define ISO_FRAME_DESC_PER_URB 32 -#define INVALID_EP_TYPE 255 /* devio.c limits single requests to 16k */ #define MAX_USBFS_BUFFER_SIZE 16384 @@ -80,7 +78,6 @@ typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port, typedef struct AsyncURB AsyncURB; struct endp_data { -uint8_t type; uint8_t halted; uint8_t iso_started; AsyncURB *iso_urb; @@ -110,8 +107,8 @@ typedef struct USBHostDevice { uint32_t iso_urb_count; Notifier exit; -struct endp_data ep_in[MAX_ENDPOINTS]; -struct endp_data ep_out[MAX_ENDPOINTS]; +struct endp_data ep_in[USB_MAX_ENDPOINTS]; +struct endp_data ep_out[USB_MAX_ENDPOINTS]; QLIST_HEAD(, AsyncURB) aurbs; /* Host side address */ @@ -133,6 +130,19 @@ static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name); static int usb_linux_update_endp_table(USBHostDevice *s); +static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p) +{ +static const int usbfs[] = { +[USB_ENDPOINT_XFER_CONTROL] = USBDEVFS_URB_TYPE_CONTROL, +[USB_ENDPOINT_XFER_ISOC]=
[Qemu-devel] [PATCH 16/17] usb-redir: Try to keep our buffer size near the target size
From: Hans de Goede hdego...@redhat.com Before this patch we would allow the (iso) buffer to grow unlimited (and it would under certain circumstances) leading to way too high latencies for iso data streams. Signed-off-by: Hans de Goede hdego...@redhat.com Signed-off-by: Gerd Hoffmann kra...@redhat.com --- usb-redir.c | 30 +++--- 1 files changed, 27 insertions(+), 3 deletions(-) diff --git a/usb-redir.c b/usb-redir.c index cdd929a..147e237 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -61,6 +61,7 @@ struct endp_data { uint8_t interrupt_started; uint8_t interrupt_error; uint8_t bufpq_prefilled; +uint8_t bufpq_dropping_packets; QTAILQ_HEAD(, buf_packet) bufpq; int bufpq_size; int bufpq_target_size; @@ -290,16 +291,34 @@ static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p) } } -static struct buf_packet *bufp_alloc(USBRedirDevice *dev, +static void bufp_alloc(USBRedirDevice *dev, uint8_t *data, int len, int status, uint8_t ep) { -struct buf_packet *bufp = g_malloc(sizeof(struct buf_packet)); +struct buf_packet *bufp; + +if (!dev-endpoint[EP2I(ep)].bufpq_dropping_packets +dev-endpoint[EP2I(ep)].bufpq_size +2 * dev-endpoint[EP2I(ep)].bufpq_target_size) { +DPRINTF(bufpq overflow, dropping packets ep %02X\n, ep); +dev-endpoint[EP2I(ep)].bufpq_dropping_packets = 1; +} +/* Since we're interupting the stream anyways, drop enough packets to get + back to our target buffer size */ +if (dev-endpoint[EP2I(ep)].bufpq_dropping_packets) { +if (dev-endpoint[EP2I(ep)].bufpq_size +dev-endpoint[EP2I(ep)].bufpq_target_size) { +free(data); +return; +} +dev-endpoint[EP2I(ep)].bufpq_dropping_packets = 0; +} + +bufp = g_malloc(sizeof(struct buf_packet)); bufp-data = data; bufp-len= len; bufp-status = status; QTAILQ_INSERT_TAIL(dev-endpoint[EP2I(ep)].bufpq, bufp, next); dev-endpoint[EP2I(ep)].bufpq_size++; -return bufp; } static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp, @@ -379,6 +398,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, DPRINTF(iso stream started ep %02X\n, ep); dev-endpoint[EP2I(ep)].iso_started = 1; dev-endpoint[EP2I(ep)].bufpq_prefilled = 0; +dev-endpoint[EP2I(ep)].bufpq_dropping_packets = 0; } if (ep USB_DIR_IN) { @@ -505,6 +525,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev, usbredirparser_do_write(dev-parser); DPRINTF(interrupt recv started ep %02X\n, ep); dev-endpoint[EP2I(ep)].interrupt_started = 1; +/* We don't really want to drop interrupt packets ever, but + having some upper limit to how much we buffer is good. */ +dev-endpoint[EP2I(ep)].bufpq_target_size = 1000; +dev-endpoint[EP2I(ep)].bufpq_dropping_packets = 0; } intp = QTAILQ_FIRST(dev-endpoint[EP2I(ep)].bufpq); -- 1.7.1
[Qemu-devel] [PATCH 02/17] usb: track configuration and interface count in USBDevice.
Move fields from USBHostDevice to USBDevice. Add bits to usb-desc.c to fill them for emulated devices too. Also allow to set configuration 0 (== None) for emulated devices. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/usb-desc.c | 34 ++ hw/usb.h |3 +++ usb-linux.c | 21 + 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/hw/usb-desc.c b/hw/usb-desc.c index ae2d384..b52561a 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -223,6 +223,29 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len) /* -- */ +static int usb_desc_set_config(USBDevice *dev, int value) +{ +int i; + +if (value == 0) { +dev-configuration = 0; +dev-ninterfaces = 0; +dev-config = NULL; +} else { +for (i = 0; i dev-device-bNumConfigurations; i++) { +if (dev-device-confs[i].bConfigurationValue == value) { +dev-configuration = value; +dev-ninterfaces = dev-device-confs[i].bNumInterfaces; +dev-config = dev-device-confs + i; +} +} +if (i dev-device-bNumConfigurations) { +return -1; +} +} +return 0; +} + static void usb_desc_setdefaults(USBDevice *dev) { const USBDesc *desc = dev-info-usb_desc; @@ -237,7 +260,7 @@ static void usb_desc_setdefaults(USBDevice *dev) dev-device = desc-high; break; } -dev-config = dev-device-confs; +usb_desc_set_config(dev, 0); } void usb_desc_init(USBDevice *dev) @@ -408,7 +431,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, int request, int value, int index, int length, uint8_t *data) { const USBDesc *desc = dev-info-usb_desc; -int i, ret = -1; +int ret = -1; assert(desc != NULL); switch(request) { @@ -427,12 +450,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, ret = 1; break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: -for (i = 0; i dev-device-bNumConfigurations; i++) { -if (dev-device-confs[i].bConfigurationValue == value) { -dev-config = dev-device-confs + i; -ret = 0; -} -} +ret = usb_desc_set_config(dev, value); trace_usb_set_config(dev-addr, value, ret); break; diff --git a/hw/usb.h b/hw/usb.h index c6e1870..1ef53a1 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -188,6 +188,9 @@ struct USBDevice { QLIST_HEAD(, USBDescString) strings; const USBDescDevice *device; + +int configuration; +int ninterfaces; const USBDescConfig *config; }; diff --git a/usb-linux.c b/usb-linux.c index c68e194..3aaa93b 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -106,8 +106,6 @@ typedef struct USBHostDevice { uint8_t descr[8192]; int descr_len; -int configuration; -int ninterfaces; int closing; uint32_t iso_urb_count; Notifier exit; @@ -547,8 +545,8 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) int ret, i; if (configuration == 0) { /* address state - ignore */ -dev-ninterfaces = 0; -dev-configuration = 0; +dev-dev.ninterfaces = 0; +dev-dev.configuration = 0; return 1; } @@ -606,8 +604,8 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) trace_usb_host_claim_interfaces(dev-bus_num, dev-addr, nb_interfaces, configuration); -dev-ninterfaces = nb_interfaces; -dev-configuration = configuration; +dev-dev.ninterfaces = nb_interfaces; +dev-dev.configuration = configuration; return 1; fail: @@ -624,7 +622,7 @@ static int usb_host_release_interfaces(USBHostDevice *s) trace_usb_host_release_interfaces(s-bus_num, s-addr); -for (i = 0; i s-ninterfaces; i++) { +for (i = 0; i s-dev.ninterfaces; i++) { ret = ioctl(s-fd, USBDEVFS_RELEASEINTERFACE, i); if (ret 0) { perror(USBDEVFS_RELEASEINTERFACE); @@ -1123,7 +1121,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s) s-ep_out[i].type = INVALID_EP_TYPE; } -if (s-configuration == 0) { +if (s-dev.configuration == 0) { /* not configured yet -- leave all endpoints disabled */ return 0; } @@ -1138,12 +1136,11 @@ static int usb_linux_update_endp_table(USBHostDevice *s) if (descriptors[i + 1] != USB_DT_CONFIG) { fprintf(stderr, invalid descriptor data\n); return 1; -} else if (descriptors[i + 5] != s-configuration) { -DPRINTF(not requested configuration %d\n, s-configuration); +} else if (descriptors[i + 5] != s-dev.configuration) { +DPRINTF(not requested configuration
Re: [Qemu-devel] [PATCH] do not chdir(/) in qemu-nbd
On 13.01.2012 15:57, Stefan Hajnoczi wrote: On Fri, Jan 13, 2012 at 9:04 AM, Michael Tokarev m...@tls.msk.ru wrote: When qemu-nbd becomes a daemon it calls daemon(3) with nochdir=0, so daemon(3) changes current directory to /. But at this time, qemu-nbd did not open any user-specified files yet, so by changing current directory, all non-absolute paths becomes wrong. The solution is to pass nochdir=1 to daemon(3) function. It's polite to chdir(/) so that file systems can be unmounted (even more important when chroot was involved, but I think qemu-nbd doesn't do that). Is it possible to manually do a chdir(/) later on after we've opened necessary files? Yes that was something I wasn't happy about too -- lack of chdir(/) in daemons is annoying. But instead of adding a chdir later, I'll try to rearrange code a bit to do all init in the parent instead. Will send a follow-up. Thanks, /mjt
Re: [Qemu-devel] [PATCH] do not chdir(/) in qemu-nbd
On Fri, Jan 13, 2012 at 04:47:35PM +0400, Michael Tokarev wrote: On 13.01.2012 15:57, Stefan Hajnoczi wrote: On Fri, Jan 13, 2012 at 9:04 AM, Michael Tokarev m...@tls.msk.ru wrote: When qemu-nbd becomes a daemon it calls daemon(3) with nochdir=0, so daemon(3) changes current directory to /. But at this time, qemu-nbd did not open any user-specified files yet, so by changing current directory, all non-absolute paths becomes wrong. The solution is to pass nochdir=1 to daemon(3) function. It's polite to chdir(/) so that file systems can be unmounted (even more important when chroot was involved, but I think qemu-nbd doesn't do that). Is it possible to manually do a chdir(/) later on after we've opened necessary files? Yes that was something I wasn't happy about too -- lack of chdir(/) in daemons is annoying. But instead of adding a chdir later, I'll try to rearrange code a bit to do all init in the parent instead. Or just canonicalize all relative paths before daemonizing. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
[Qemu-devel] [PATCH v5 00/15] block: generic image streaming
Note: This is a resend of v5 because the emails I sent earlier today disappeared. This series adds the 'block_stream' command which copies the contents of a backing file into the image file while the VM is running. The series builds on the zero detection features which I sent out before Christmas. I suggest grabbing my git tree to try it out without merging this dependency: https://github.com/stefanha/qemu/tree/image-streaming-api The image streaming HMP/QMP commands are documented in the patch and also described here: http://wiki.qemu.org/Features/LiveBlockMigration/ImageStreamingAPI The basic idea is to execute 'block_stream virtio0' while the guest is running. Progress can be monitored using 'info block-jobs'. When the streaming operation completes it raises a QMP event. Note: The last patch includes includes a Python test script called test-stream.py, I do not propose to merge it. When run in a QEMU source tree it performs basic image streaming QMP tests. v5: * Handle block_job_create() failure [Luiz] * Mark BLOCK_JOB_COMPLETED error field optional [Luiz] * Mark block_stream base parameter optional [Luiz] * Check bdrv_getlength() failure and don't call twice [Kevin] * Rename id to backing_file in bdrv_find_backing_image() [Kevin] * Rename BaseIdNotFound qerror to BaseNotFound [Kevin] * Document BaseNotFound qerror from block_stream * Document that qemu_co_sleep_ns() needs main loop [Kevin] * Make bdrv_co_is_allocated_base() private to block/stream.c [Kevin] * Clean up commit messages v4: * Drop SQMP/EQMP docs from qmp-commands.hx [Luiz] * Follow QAPI doc conventions [Luiz] * Document QMP events in QMP/qmp-events.txt [Luiz] * Protect against hotplug, resize, eject, etc [Kevin] * Move block job functions from header to block.c [Kevin] * Return error from bdrg_change_backing_file() [Kevin] * Merge Marcelo's block_stream base partial streaming series [Marcelo] Marcelo Tosatti (4): block: add bdrv_find_backing_image add QERR_BASE_NOT_FOUND block: add support for partial streaming docs: describe live block operations Stefan Hajnoczi (11): coroutine: add co_sleep_ns() coroutine sleep function block: check bdrv_in_use() before blockdev operations block: add BlockJob interface for long-running operations block: add image streaming block job block: rate-limit streaming operations qmp: add block_stream command qmp: add block_job_set_speed command qmp: add block_job_cancel command qmp: add query-block-jobs blockdev: make image streaming safe across hotplug test: add image streaming test cases Makefile.objs |2 + QMP/qmp-events.txt | 53 ++ block.c | 70 + block.h |2 + block/stream.c | 260 +++ block_int.h | 44 blockdev.c | 199 +++- docs/live-block-ops.txt | 58 +++ hmp-commands.hx | 41 hmp.c | 68 hmp.h |4 + monitor.c | 13 +++ monitor.h |2 + qapi-schema.json| 116 + qemu-coroutine-sleep.c | 38 +++ qemu-coroutine.h|9 ++ qerror.c|8 ++ qerror.h|6 + qmp-commands.hx | 24 + test-stream.py | 208 + trace-events|9 ++ 21 files changed, 1233 insertions(+), 1 deletions(-) create mode 100644 block/stream.c create mode 100644 docs/live-block-ops.txt create mode 100644 qemu-coroutine-sleep.c create mode 100644 test-stream.py -- 1.7.7.3
[Qemu-devel] [PATCH v5 01/15] coroutine: add co_sleep_ns() coroutine sleep function
Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- Makefile.objs |1 + qemu-coroutine-sleep.c | 38 ++ qemu-coroutine.h |9 + 3 files changed, 48 insertions(+), 0 deletions(-) create mode 100644 qemu-coroutine-sleep.c diff --git a/Makefile.objs b/Makefile.objs index 4f6d26c..f4f52e0 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -13,6 +13,7 @@ oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o ### # coroutines coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o +coroutine-obj-y += qemu-coroutine-sleep.o ifeq ($(CONFIG_UCONTEXT_COROUTINE),y) coroutine-obj-$(CONFIG_POSIX) += coroutine-ucontext.o else diff --git a/qemu-coroutine-sleep.c b/qemu-coroutine-sleep.c new file mode 100644 index 000..fd65274 --- /dev/null +++ b/qemu-coroutine-sleep.c @@ -0,0 +1,38 @@ +/* + * QEMU coroutine sleep + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczistefa...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include qemu-coroutine.h +#include qemu-timer.h + +typedef struct CoSleepCB { +QEMUTimer *ts; +Coroutine *co; +} CoSleepCB; + +static void co_sleep_cb(void *opaque) +{ +CoSleepCB *sleep_cb = opaque; + +qemu_free_timer(sleep_cb-ts); +qemu_coroutine_enter(sleep_cb-co, NULL); +} + +void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns) +{ +CoSleepCB sleep_cb = { +.co = qemu_coroutine_self(), +}; +sleep_cb.ts = qemu_new_timer(clock, SCALE_NS, co_sleep_cb, sleep_cb); +qemu_mod_timer(sleep_cb.ts, qemu_get_clock_ns(clock) + ns); +qemu_coroutine_yield(); +} diff --git a/qemu-coroutine.h b/qemu-coroutine.h index 8a55fe1..34c15d4 100644 --- a/qemu-coroutine.h +++ b/qemu-coroutine.h @@ -17,6 +17,7 @@ #include stdbool.h #include qemu-queue.h +#include qemu-timer.h /** * Coroutines are a mechanism for stack switching and can be used for @@ -199,4 +200,12 @@ void qemu_co_rwlock_wrlock(CoRwlock *lock); */ void qemu_co_rwlock_unlock(CoRwlock *lock); +/** + * Yield the coroutine for a given duration + * + * Note this function uses timers and hence only works when a main loop is in + * use. See main-loop.h and do not use from qemu-tool programs. + */ +void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns); + #endif /* QEMU_COROUTINE_H */ -- 1.7.7.3
[Qemu-devel] [PATCH v5 15/15] test: add image streaming test cases
python test-stream.py Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- test-stream.py | 208 1 files changed, 208 insertions(+), 0 deletions(-) create mode 100644 test-stream.py diff --git a/test-stream.py b/test-stream.py new file mode 100644 index 000..16cbe5d --- /dev/null +++ b/test-stream.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +import unittest +import subprocess +import re +import os +import sys; sys.path.append('QMP/') +import qmp + +def qemu_img(*args): +devnull = open('/dev/null', 'r+') +return subprocess.call(['./qemu-img'] + list(args), stdin=devnull, stdout=devnull) + +def qemu_io(*args): +args = ['./qemu-io'] + list(args) +return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0] + +class VM(object): +def __init__(self): +self._monitor_path = '/tmp/qemu-mon.%d' % os.getpid() +self._qemu_log_path = '/tmp/qemu-log.%d' % os.getpid() +self._args = ['x86_64-softmmu/qemu-system-x86_64', + '-chardev', 'socket,id=mon,path=' + self._monitor_path, + '-mon', 'chardev=mon,mode=control', '-nographic'] +self._num_drives = 0 + +def add_drive(self, path, opts=''): +options = ['if=virtio', + 'cache=none', + 'file=%s' % path, + 'id=drive%d' % self._num_drives] +if opts: +options.append(opts) + +self._args.append('-drive') +self._args.append(','.join(options)) +self._num_drives += 1 +return self + +def launch(self): +devnull = open('/dev/null', 'rb') +qemulog = open(self._qemu_log_path, 'wb') +self._qmp = qmp.QEMUMonitorProtocol(self._monitor_path, server=True) +self._popen = subprocess.Popen(self._args, stdin=devnull, stdout=qemulog, + stderr=subprocess.STDOUT) +self._qmp.accept() + +def shutdown(self): +self._qmp.cmd('quit') +self._popen.wait() +os.remove(self._monitor_path) +os.remove(self._qemu_log_path) + +def qmp(self, cmd, **args): +return self._qmp.cmd(cmd, args=args) + +def get_qmp_events(self, wait=False): +events = self._qmp.get_events(wait=wait) +self._qmp.clear_events() +return events + +index_re = re.compile(r'([^\[]+)\[([^\]]+)\]') + +class QMPTestCase(unittest.TestCase): +def dictpath(self, d, path): +Traverse a path in a nested dict +for component in path.split('/'): +m = index_re.match(component) +if m: +component, idx = m.groups() +idx = int(idx) + +if not isinstance(d, dict) or component not in d: +self.fail('failed path traversal for %s in %s' % (path, str(d))) +d = d[component] + +if m: +if not isinstance(d, list): +self.fail('path component %s in %s is not a list in %s' % (component, path, str(d))) +try: +d = d[idx] +except IndexError: +self.fail('invalid index %s in path %s in %s' % (idx, path, str(d))) +return d + +def assert_qmp(self, d, path, value): +result = self.dictpath(d, path) +self.assertEqual(result, value, 'values not equal %s and %s' % (str(result), str(value))) + +def assert_no_active_streams(self): +result = self.vm.qmp('query-block-jobs') +self.assert_qmp(result, 'return', []) + +class TestSingleDrive(QMPTestCase): +image_len = 1 * 1024 * 1024 # MB + +def setUp(self): +qemu_img('create', 'backing.img', str(TestSingleDrive.image_len)) +qemu_img('create', '-f', 'qed', '-o', 'backing_file=backing.img', 'test.qed') +self.vm = VM().add_drive('test.qed') +self.vm.launch() + +def tearDown(self): +self.vm.shutdown() +os.remove('test.qed') +os.remove('backing.img') + +def test_stream(self): +self.assert_no_active_streams() + +result = self.vm.qmp('block_stream', device='drive0') +self.assert_qmp(result, 'return', {}) + +completed = False +while not completed: +for event in self.vm.get_qmp_events(wait=True): +if event['event'] == 'BLOCK_JOB_COMPLETED': +self.assert_qmp(event, 'data/type', 'stream') +self.assert_qmp(event, 'data/device', 'drive0') +self.assert_qmp(event, 'data/offset', self.image_len) +self.assert_qmp(event, 'data/len', self.image_len) +completed = True + +self.assert_no_active_streams() + +self.assertFalse('sectors not allocated' in qemu_io('-c', 'map', 'test.qed'), + 'image file not fully populated after streaming') + +def
[Qemu-devel] [PATCH v5 02/15] block: check bdrv_in_use() before blockdev operations
Long-running block operations like block migration and image streaming must have continual access to their block device. It is not safe to perform operations like hotplug, eject, change, resize, commit, or external snapshot while a long-running operation is in progress. This patch adds the missing bdrv_in_use() checks so that block migration and image streaming never have the rug pulled out from underneath them. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- block.c|4 blockdev.c | 16 +++- 2 files changed, 19 insertions(+), 1 deletions(-) diff --git a/block.c b/block.c index 967a583..daf92c2 100644 --- a/block.c +++ b/block.c @@ -1020,6 +1020,10 @@ int bdrv_commit(BlockDriverState *bs) return -EACCES; } +if (bdrv_in_use(bs) || bdrv_in_use(bs-backing_hd)) { +return -EBUSY; +} + backing_drv = bs-backing_hd-drv; ro = bs-backing_hd-read_only; strncpy(filename, bs-backing_hd-filename, sizeof(filename)); diff --git a/blockdev.c b/blockdev.c index c832782..6d78b36 100644 --- a/blockdev.c +++ b/blockdev.c @@ -592,12 +592,18 @@ void do_commit(Monitor *mon, const QDict *qdict) if (!strcmp(device, all)) { bdrv_commit_all(); } else { +int ret; + bs = bdrv_find(device); if (!bs) { qerror_report(QERR_DEVICE_NOT_FOUND, device); return; } -bdrv_commit(bs); +ret = bdrv_commit(bs); +if (ret == -EBUSY) { +qerror_report(QERR_DEVICE_IN_USE, device); +return; +} } } @@ -616,6 +622,10 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } +if (bdrv_in_use(bs)) { +error_set(errp, QERR_DEVICE_IN_USE, device); +return; +} pstrcpy(old_filename, sizeof(old_filename), bs-filename); @@ -667,6 +677,10 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, static int eject_device(Monitor *mon, BlockDriverState *bs, int force) { +if (bdrv_in_use(bs)) { +qerror_report(QERR_DEVICE_IN_USE, bdrv_get_device_name(bs)); +return -1; +} if (!bdrv_dev_has_removable_media(bs)) { qerror_report(QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs)); return -1; -- 1.7.7.3
[Qemu-devel] [PATCH] usb-ehci: Clear the portstatus powner bit on device disconnect
According to the EHCI spec port ownerhsip should revert to the EHCI controller on device disconnect. This fixes the problem of a port getting stuck on USB 1 when using redirection and plugging in a USB 2 device after a USB 1 device has been redirected. Signed-off-by: Hans de Goede hdego...@redhat.com --- hw/usb-ehci.c |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index a946e1d..69bcc4b 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -764,6 +764,11 @@ static void ehci_detach(USBPort *port) USBPort *companion = s-companion_ports[port-index]; companion-ops-detach(companion); companion-dev = NULL; +/* + * EHCI spec 4.2.2: When a disconnect occurs... On the event, + * the port ownership is returned immediately to the EHCI controller. + */ +*portsc = ~PORTSC_POWNER; return; } -- 1.7.7.4
[Qemu-devel] [PATCH v5 07/15] qmp: add block_job_set_speed command
Add block_job_set_speed, which sets the maximum speed for a background block operation. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- blockdev.c | 25 + hmp-commands.hx | 14 ++ hmp.c| 11 +++ hmp.h|1 + qapi-schema.json | 22 ++ qmp-commands.hx |6 ++ 6 files changed, 79 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index ba973b0..2dfca40 100644 --- a/blockdev.c +++ b/blockdev.c @@ -947,3 +947,28 @@ void qmp_block_stream(const char *device, bool has_base, trace_qmp_block_stream(bs, bs-job); } + +static BlockJob *find_block_job(const char *device) +{ +BlockDriverState *bs; + +bs = bdrv_find(device); +if (!bs || !bs-job) { +return NULL; +} +return bs-job; +} + +void qmp_block_job_set_speed(const char *device, int64_t value, Error **errp) +{ +BlockJob *job = find_block_job(device); + +if (!job) { +error_set(errp, QERR_DEVICE_NOT_ACTIVE, device); +return; +} + +if (block_job_set_speed(job, value) 0) { +error_set(errp, QERR_NOT_SUPPORTED); +} +} diff --git a/hmp-commands.hx b/hmp-commands.hx index dc6c8c3..12b8433 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -84,6 +84,20 @@ Copy data from a backing file into a block device. ETEXI { +.name = block_job_set_speed, +.args_type = device:B,value:o, +.params = device value, +.help = set maximum speed for a background block operation, +.mhandler.cmd = hmp_block_job_set_speed, +}, + +STEXI +@item block_job_set_stream +@findex block_job_set_stream +Set maximum speed for a background block operation. +ETEXI + +{ .name = eject, .args_type = force:-f,device:B, .params = [-f] device, diff --git a/hmp.c b/hmp.c index b6e5913..1144d53 100644 --- a/hmp.c +++ b/hmp.c @@ -690,3 +690,14 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, error); } + +void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict) +{ +Error *error = NULL; +const char *device = qdict_get_str(qdict, device); +int64_t value = qdict_get_int(qdict, value); + +qmp_block_job_set_speed(device, value, error); + +hmp_handle_error(mon, error); +} diff --git a/hmp.h b/hmp.h index b55c295..2c871ea 100644 --- a/hmp.h +++ b/hmp.h @@ -50,5 +50,6 @@ void hmp_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); void hmp_block_stream(Monitor *mon, const QDict *qdict); +void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict); #endif diff --git a/qapi-schema.json b/qapi-schema.json index 3821982..5872096 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1307,3 +1307,25 @@ # Since: 1.1 ## { 'command': 'block_stream', 'data': { 'device': 'str', '*base': 'str' } } + +## +# @block_job_set_speed: +# +# Set maximum speed for a background block operation. +# +# This command can only be issued when there is an active block job. +# +# Throttling can be disabled by setting the speed to 0. +# +# @device: the device name +# +# @value: the maximum speed, in bytes per second +# +# Returns: Nothing on success +# If the job type does not support throttling, NotSupported +# If streaming is not active on this device, DeviceNotActive +# +# Since: 1.1 +## +{ 'command': 'block_job_set_speed', + 'data': { 'device': 'str', 'value': 'int' } } diff --git a/qmp-commands.hx b/qmp-commands.hx index b9ebb76..dc6bc2e 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -661,6 +661,12 @@ EQMP }, { +.name = block_job_set_speed, +.args_type = device:B,value:o, +.mhandler.cmd_new = qmp_marshal_input_block_job_set_speed, +}, + +{ .name = blockdev-snapshot-sync, .args_type = device:B,snapshot-file:s,format:s?, .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_sync, -- 1.7.7.3
Re: [Qemu-devel] Mixed USB 1.1 and USB 2.0 on the same port
On 01/04/2012 05:52 PM, Erik Rull wrote: erik.r...@rdsoftware.de wrote: On 12/31/11 13:11, Erik Rull wrote: Hi all, how can I use a USB 1.1 device on the USB 2.0 bus? Currently the EHCI implementation complains that the device is mismatches the USB version. -readconfig docs/ich9-ehci-uhci.cfg cheers, Gerd Thanks for the hint. It looks better now. But some things are still a bit strange.Hi, Sequence: device_add usb-host,bus=ehci.0,hostbus=2,hostport=1.4 Plug in a USB 2.0 printer (gets detected by the guest, printing is possible, no bluescreen, it just works) Remove the USB 2.0 printer Plug in a USB 1.1 dongle Gets detected, etc., fine Remove the USB 1.1 dongle Plug in the USB 2.0 printer again Guest complains now, that a USB 2.0 device was plugged into a USB 1.1 port = printer is now 1.1 and does not work as if EHCI is missing now = reboot guest, everything is fine again?? Any idea what could have happened here? Same behavior when using a 2.0 USB key and the USB 1.1 dongle - also on other ports - the transfer rate is horrible after having removed the USB 1.1 device and reconnected the 2.0 device. Exchanging the two USB 2.0 devices on the same port without having the 1.1 device plugged in is fine! Any hint what is wrong here would be great. Best regards, Erik Additional Information: This behavior is present on a Linux guest as well! After having removed the 1.1 Dongle and plugged in the printer, the Linux guest detects the hardware via the UHCI kernel drivers and tells me to use a faster hub for max. performance. It looks as if the speed downgrade by the 1.1 device cannot be reversed at runtime. I've managed to reproduce this and written a fix for it. I've just send a patch for this to the list. I've also attached this patch here for your convenience. Regards, Hans From 0b5059a8c0ae45c66caf5947f66b5c5cae81f622 Mon Sep 17 00:00:00 2001 From: Hans de Goede hdego...@redhat.com Date: Fri, 13 Jan 2012 14:26:26 +0100 Subject: [PATCH] usb-ehci: Clear the portstatus powner bit on device disconnect According to the EHCI spec port ownerhsip should revert to the EHCI controller on device disconnect. This fixes the problem of a port getting stuck on USB 1 when using redirection and plugging in a USB 2 device after a USB 1 device has been redirected. Signed-off-by: Hans de Goede hdego...@redhat.com --- hw/usb-ehci.c |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index a946e1d..69bcc4b 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -764,6 +764,11 @@ static void ehci_detach(USBPort *port) USBPort *companion = s-companion_ports[port-index]; companion-ops-detach(companion); companion-dev = NULL; +/* + * EHCI spec 4.2.2: When a disconnect occurs... On the event, + * the port ownership is returned immediately to the EHCI controller. + */ +*portsc = ~PORTSC_POWNER; return; } -- 1.7.7.4
Re: [Qemu-devel] [PATCH] do not chdir(/) in qemu-nbd
On 01/13/2012 01:47 PM, Michael Tokarev wrote: But instead of adding a chdir later, I'll try to rearrange code a bit to do all init in the parent instead. That's not possible, because when you fork you lose all threads except the main thread. That's why the daemon() was moved very early. Your patch is okay if you also add a chdir(/) later on. Paolo
[Qemu-devel] [PATCH 1/3][Seabios] Add bitmap for cpu _EJ0 callback
Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com --- src/acpi-dsdt.dsl |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl index 7082b65..71d8ac4 100644 --- a/src/acpi-dsdt.dsl +++ b/src/acpi-dsdt.dsl @@ -650,8 +650,15 @@ DefinitionBlock ( Store(DerefOf(Index(CPON, Arg0)), Local0) If (Local0) { Return(0xF) } Else { Return(0x0) } } +/* CPU eject notify method */ +OperationRegion(PREJ, SystemIO, 0xaf20, 32) +Field (PREJ, ByteAcc, NoLock, Preserve) +{ +PRE, 256 +} Method (CPEJ, 2, NotSerialized) { // _EJ0 method - eject callback +Store(ShiftLeft(1, Arg0), PRE) Sleep(200) } -- 1.7.7.3
[Qemu-devel] [PATCH v5 11/15] block: add bdrv_find_backing_image
From: Marcelo Tosatti mtosa...@redhat.com Add bdrv_find_backing_image: given a BlockDriverState pointer, and an id, traverse the backing image chain to locate the id. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- block.c | 18 ++ block.h |2 ++ 2 files changed, 20 insertions(+), 0 deletions(-) diff --git a/block.c b/block.c index d588ee8..d8ae716 100644 --- a/block.c +++ b/block.c @@ -2614,6 +2614,24 @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs, return -ENOTSUP; } +BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, +const char *backing_file) +{ +if (!bs-drv) { +return NULL; +} + +if (bs-backing_hd) { +if (strcmp(bs-backing_file, backing_file) == 0) { +return bs-backing_hd; +} else { +return bdrv_find_backing_image(bs-backing_hd, backing_file); +} +} + +return NULL; +} + #define NB_SUFFIXES 4 char *get_human_readable_size(char *buf, int buf_size, int64_t size) diff --git a/block.h b/block.h index 51b90c7..05c8c83 100644 --- a/block.h +++ b/block.h @@ -153,6 +153,8 @@ int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors); int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); +BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, +const char *backing_file); int bdrv_truncate(BlockDriverState *bs, int64_t offset); int64_t bdrv_getlength(BlockDriverState *bs); int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); -- 1.7.7.3
[Qemu-devel] [PATCH 2/3] acpi_piix4: Add stub functions for CPU eject callback
Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com --- hw/acpi_piix4.c | 15 +++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index d5743b6..8bf30dd 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -37,6 +37,7 @@ #define GPE_BASE 0xafe0 #define PROC_BASE 0xaf00 +#define PROC_EJ_BASE 0xaf20 #define GPE_LEN 4 #define PCI_BASE 0xae00 #define PCI_EJ_BASE 0xae08 @@ -493,6 +494,17 @@ static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val) PIIX4_DPRINTF(pcihotplug write %x == %d\n, addr, val); } +static uint32_t cpuej_read(void *opaque, uint32_t addr) +{ +PIIX4_DPRINTF(cpuej read %x\n, addr); +return 0; +} + +static void cpuej_write(void *opaque, uint32_t addr, uint32_t val) +{ +PIIX4_DPRINTF(cpuej write %x == %d\n, addr, val); +} + static uint32_t pciej_read(void *opaque, uint32_t addr) { PIIX4_DPRINTF(pciej read %x\n, addr); @@ -553,6 +565,9 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s) register_ioport_write(PROC_BASE, 32, 1, gpe_writeb, s); register_ioport_read(PROC_BASE, 32, 1, gpe_readb, s); +register_ioport_write(PROC_EJ_BASE, 32, 1, cpuej_write, s); +register_ioport_read(PROC_EJ_BASE, 32, 1, cpuej_read, s); + register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status); register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, pci0_status); -- 1.7.7.3
[Qemu-devel] [PATCH] qdev: fix device_del by refactoring reference counting
Commit 8eb0283 broken device_del by having too overzealous reference counting checks. Move the reference count checks to qdev_free(), make sure to remove the parent link on free, and decrement the reference count on property removal. Reported-by: Markus Armbruster arm...@redhat.com Signed-off-by: Anthony Liguori aligu...@us.ibm.com --- hw/qdev.c | 45 +++-- 1 files changed, 39 insertions(+), 6 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index d0cf66d..e59f345 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -376,11 +376,6 @@ int qdev_unplug(DeviceState *dev) } assert(dev-info-unplug != NULL); -if (dev-ref != 0) { -qerror_report(QERR_DEVICE_IN_USE, dev-id?:); -return -1; -} - qdev_hot_removed = true; return dev-info-unplug(dev); @@ -465,6 +460,29 @@ static void qdev_property_del_all(DeviceState *dev) } } +static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp) +{ +DeviceProperty *prop; + +QTAILQ_FOREACH(prop, dev-properties, node) { +if (strstart(prop-type, child, NULL) prop-opaque == child) { +break; +} +} + +g_assert(prop != NULL); + +QTAILQ_REMOVE(dev-properties, prop, node); + +if (prop-release) { +prop-release(dev, prop-name, prop-opaque); +} + +g_free(prop-name); +g_free(prop-type); +g_free(prop); +} + /* Unlink device from bus and free the structure. */ void qdev_free(DeviceState *dev) { @@ -491,6 +509,12 @@ void qdev_free(DeviceState *dev) prop-info-free(dev, prop); } } +if (dev-parent) { +qdev_property_del_child(dev-parent, dev, NULL); +} +if (dev-ref != 0) { +qerror_report(QERR_DEVICE_IN_USE, dev-id?:); +} g_free(dev); } @@ -1239,6 +1263,14 @@ static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque, g_free(path); } +static void qdev_release_child_property(DeviceState *dev, const char *name, +void *opaque) +{ +DeviceState *child = opaque; + +qdev_unref(child); +} + void qdev_property_add_child(DeviceState *dev, const char *name, DeviceState *child, Error **errp) { @@ -1247,7 +1279,8 @@ void qdev_property_add_child(DeviceState *dev, const char *name, type = g_strdup_printf(child%s, child-info-name); qdev_property_add(dev, name, type, qdev_get_child_property, - NULL, NULL, child, errp); + NULL, qdev_release_child_property, + child, errp); qdev_ref(child); g_assert(child-parent == NULL); -- 1.7.4.1
[Qemu-devel] [PATCH v5 13/15] block: add support for partial streaming
From: Marcelo Tosatti mtosa...@redhat.com Add support for streaming data from an intermediate section of the image chain (see patch and documentation for details). Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- block/stream.c | 91 +-- block_int.h|3 +- blockdev.c | 11 -- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/block/stream.c b/block/stream.c index 93f0305..7532f5e 100644 --- a/block/stream.c +++ b/block/stream.c @@ -57,6 +57,7 @@ typedef struct StreamBlockJob { BlockJob common; RateLimit limit; BlockDriverState *base; +char backing_file_id[1024]; } StreamBlockJob; static int coroutine_fn stream_populate(BlockDriverState *bs, @@ -75,10 +76,76 @@ static int coroutine_fn stream_populate(BlockDriverState *bs, return bdrv_co_readv(bs, sector_num, nb_sectors, qiov); } +/* + * Given an image chain: [BASE] - [INTER1] - [INTER2] - [TOP] + * + * Return true if the given sector is allocated in top. + * Return false if the given sector is allocated in intermediate images. + * Return true otherwise. + * + * 'pnum' is set to the number of sectors (including and immediately following + * the specified sector) that are known to be in the same + * allocated/unallocated state. + * + */ +static int coroutine_fn is_allocated_base(BlockDriverState *top, + BlockDriverState *base, + int64_t sector_num, + int nb_sectors, int *pnum) +{ +BlockDriverState *intermediate; +int ret, n; + +ret = bdrv_co_is_allocated(top, sector_num, nb_sectors, n); +if (ret) { +*pnum = n; +return ret; +} + +/* + * Is the unallocated chunk [sector_num, n] also + * unallocated between base and top? + */ +intermediate = top-backing_hd; + +while (intermediate) { +int pnum_inter; + +/* reached base */ +if (intermediate == base) { +*pnum = n; +return 1; +} +ret = bdrv_co_is_allocated(intermediate, sector_num, nb_sectors, + pnum_inter); +if (ret 0) { +return ret; +} else if (ret) { +*pnum = pnum_inter; +return 0; +} + +/* + * [sector_num, nb_sectors] is unallocated on top but intermediate + * might have + * + * [sector_num+x, nr_sectors] allocated. + */ +if (n pnum_inter) { +n = pnum_inter; +} + +intermediate = intermediate-backing_hd; +} + +return 1; +} + static void coroutine_fn stream_run(void *opaque) { StreamBlockJob *s = opaque; BlockDriverState *bs = s-common.bs; +BlockDriverState *base = s-base; int64_t sector_num, end; int ret = 0; int n; @@ -101,8 +168,15 @@ retry: break; } -ret = bdrv_co_is_allocated(bs, sector_num, - STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, n); + +if (base) { +ret = is_allocated_base(bs, base, sector_num, +STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, n); +} else { +ret = bdrv_co_is_allocated(bs, sector_num, + STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, + n); +} trace_stream_one_iteration(s, sector_num, n, ret); if (ret == 0) { if (s-common.speed) { @@ -119,6 +193,7 @@ retry: if (ret 0) { break; } +ret = 0; /* Publish progress */ s-common.offset += n * BDRV_SECTOR_SIZE; @@ -132,7 +207,11 @@ retry: bdrv_disable_copy_on_read(bs); if (sector_num == end ret == 0) { -ret = bdrv_change_backing_file(bs, NULL, NULL); +const char *base_id = NULL; +if (base) { +base_id = s-backing_file_id; +} +ret = bdrv_change_backing_file(bs, base_id, NULL); } qemu_vfree(buf); @@ -158,7 +237,8 @@ static BlockJobType stream_job_type = { }; int stream_start(BlockDriverState *bs, BlockDriverState *base, - BlockDriverCompletionFunc *cb, void *opaque) + const char *base_id, BlockDriverCompletionFunc *cb, + void *opaque) { StreamBlockJob *s; Coroutine *co; @@ -169,6 +249,9 @@ int stream_start(BlockDriverState *bs, BlockDriverState *base, } s-base = base; +if (base_id) { +pstrcpy(s-backing_file_id, sizeof(s-backing_file_id), base_id); +} co = qemu_coroutine_create(stream_run); trace_stream_start(bs, base, s, co, opaque); diff --git a/block_int.h b/block_int.h index c7c9178..ed92884 100644 --- a/block_int.h +++ b/block_int.h @@
[Qemu-devel] [PATCH] qemu-test: add device-del test case
Signed-off-by: Anthony Liguori aligu...@us.ibm.com --- tests/device-del.sh | 91 +++ 1 files changed, 91 insertions(+), 0 deletions(-) create mode 100755 tests/device-del.sh diff --git a/tests/device-del.sh b/tests/device-del.sh new file mode 100755 index 000..3af4e2f --- /dev/null +++ b/tests/device-del.sh @@ -0,0 +1,91 @@ +#!/bin/sh + +canary=** waiting for hotplug ** +canary2=** waiting for remove ** + +in_host() { +tmpdisk=$tmpdir/disk.img + +# make sure to test various of -device, anonymous, and named +extra_arg=`choose -device virtio-balloon-pci -device virtio-balloon-pci,id=balloon0 none` + +if test $extra_arg = none; then + extra_arg= +fi + +qemu-img create -f qcow2 $tmpdisk 10G + +start_qemu -nographic -enable-kvm $extra_arg + +while qemu_is_okay; do + if grep $canary $tmplog /dev/null; then + out=`hmp drive_add auto file=$tmpdisk,if=none,id=hd0` + if test $(echo $out) != OK; then + echo drive_add failed! + echo $out + rm $tmpdisk + kill $pid + return 1 + fi + + qmp device_add --driver=virtio-blk-pci --drive=hd0 --id=hd0 + rc=$? + if test $rc != 0; then + echo device_add failed! + rm $tmpdisk + kill $pid + return 1 + fi + + echo ** waiting for guest to see device ** + + while qemu_is_okay; do + if grep $canary2 $tmplog /dev/null; then + qmp device_del --id=hd0 + rc=$? + if test $rc != 0; then + echo device_del failed! + rm $tmpdisk + kill $pid + return 1 + fi + + while qemu_is_okay; do + sleep 1 + done + + break + fi + sleep 1 + done + + break + fi + sleep 1 +done + +get_qemu_status +rc=$? + +rm -f $tmpdisk + +return $rc +} + +in_guest() { +echo +echo $canary +while ! grep vda /proc/partitions /dev/null; do + sleep 1 +done +echo $canary2 +while grep vda /proc/partitions /dev/null; do + sleep 1 +done +} + +if test $QEMU_TEST; then +in_host +else +in_guest +fi -- 1.7.4.1
[Qemu-devel] [PATCH v5 12/15] add QERR_BASE_NOT_FOUND
From: Marcelo Tosatti mtosa...@redhat.com This qerror will be raised when a given streaming base (backing file) cannot be found. Signed-off-by: Marcelo Tosatti mtosa...@redhat.com Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- qapi-schema.json |1 + qerror.c |4 qerror.h |3 +++ 3 files changed, 8 insertions(+), 0 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index b4f6b15..b778639 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1335,6 +1335,7 @@ # If streaming is already active on this device, DeviceInUse # If @device does not exist, DeviceNotFound # If image streaming is not supported by this device, NotSupported +# If @base does not exist, BaseNotFound # # Since: 1.1 ## diff --git a/qerror.c b/qerror.c index feb3d35..272243491 100644 --- a/qerror.c +++ b/qerror.c @@ -49,6 +49,10 @@ static const QErrorStringTable qerror_table[] = { .desc = Device '%(device)' can't go on a %(bad_bus_type) bus, }, { +.error_fmt = QERR_BASE_NOT_FOUND, +.desc = Base '%(base)' not found, +}, +{ .error_fmt = QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, .desc = Block format '%(format)' used by device '%(name)' does not support feature '%(feature)', }, diff --git a/qerror.h b/qerror.h index 095ba9d..4351fe3 100644 --- a/qerror.h +++ b/qerror.h @@ -54,6 +54,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_BAD_BUS_FOR_DEVICE \ { 'class': 'BadBusForDevice', 'data': { 'device': %s, 'bad_bus_type': %s } } +#define QERR_BASE_NOT_FOUND \ +{ 'class': 'BaseNotFound', 'data': { 'base': %s } } + #define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \ { 'class': 'BlockFormatFeatureNotSupported', 'data': { 'format': %s, 'name': %s, 'feature': %s } } -- 1.7.7.3
[Qemu-devel] [PATCH 3/3] acpi_piix4: Call KVM_SETSTATE_VCPU ioctl on cpu ejection
Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com --- hw/acpi_piix4.c | 21 + 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 8bf30dd..12eef55 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -502,6 +502,27 @@ static uint32_t cpuej_read(void *opaque, uint32_t addr) static void cpuej_write(void *opaque, uint32_t addr, uint32_t val) { +struct kvm_vcpu_state state; +CPUState *env; +int cpu; +int ret; + +cpu = ffs(val); +/* zero means no bit was set, i.e. no CPU ejection happened */ +if (!cpu) + return; +cpu--; +env = cpu_phyid_to_cpu((uint64_t)cpu); +if (env != NULL) { +if (env-state == CPU_STATE_ZAPREQ) { +state.vcpu_id = env-cpu_index; +state.state = 1; +ret = kvm_vm_ioctl(env-kvm_state, KVM_SETSTATE_VCPU, state); +if (ret) +fprintf(stderr, KVM_SETSTATE_VCPU failed: %s\n, +strerror(ret)); +} +} PIIX4_DPRINTF(cpuej write %x == %d\n, addr, val); } -- 1.7.7.3
[Qemu-devel] [PATCH v5 10/15] blockdev: make image streaming safe across hotplug
Unplugging a storage interface like virtio-blk causes the host block device to be deleted too. Long-running operations like block migration must take a DriveInfo reference to prevent the BlockDriverState from being freed. For image streaming we can do the same thing. Note that it is not possible to acquire/release the drive reference in block.c where the block job functions live because drive_get_ref()/drive_put_ref() are blockdev.c functions. Calling them from block.c would be a layering violation - tools like qemu-img don't even link against blockdev.c. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- blockdev.c | 38 ++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index 4549c9e..45a6ba6 100644 --- a/blockdev.c +++ b/blockdev.c @@ -202,6 +202,37 @@ void drive_get_ref(DriveInfo *dinfo) dinfo-refcount++; } +typedef struct { +QEMUBH *bh; +DriveInfo *dinfo; +} DrivePutRefBH; + +static void drive_put_ref_bh(void *opaque) +{ +DrivePutRefBH *s = opaque; + +drive_put_ref(s-dinfo); +qemu_bh_delete(s-bh); +g_free(s); +} + +/* + * Release a drive reference in a BH + * + * It is not possible to use drive_put_ref() from a callback function when the + * callers still need the drive. In such cases we schedule a BH to release the + * reference. + */ +static void drive_put_ref_bh_schedule(DriveInfo *dinfo) +{ +DrivePutRefBH *s; + +s = g_new(DrivePutRefBH, 1); +s-bh = qemu_bh_new(drive_put_ref_bh, s); +s-dinfo = dinfo; +qemu_bh_schedule(s-bh); +} + static int parse_block_error_action(const char *buf, int is_read) { if (!strcmp(buf, ignore)) { @@ -917,6 +948,8 @@ static void block_stream_cb(void *opaque, int ret) monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj); } qobject_decref(obj); + +drive_put_ref_bh_schedule(drive_get_by_blockdev(bs)); } void qmp_block_stream(const char *device, bool has_base, @@ -949,6 +982,11 @@ void qmp_block_stream(const char *device, bool has_base, } } +/* Grab a reference so hotplug does not delete the BlockDriverState from + * underneath us. + */ +drive_get_ref(drive_get_by_blockdev(bs)); + trace_qmp_block_stream(bs, bs-job); } -- 1.7.7.3
[Qemu-devel] [PATCH v5 06/15] qmp: add block_stream command
Add the block_stream command, which starts copy backing file contents into the image file. Also add the BLOCK_JOB_COMPLETED QMP event which is emitted when image streaming completes. Later patches add control over the background copy speed, cancelation, and querying running streaming operations. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- QMP/qmp-events.txt | 29 ++ blockdev.c | 67 hmp-commands.hx| 13 ++ hmp.c | 11 hmp.h |1 + monitor.c |3 ++ monitor.h |1 + qapi-schema.json | 32 qerror.c |4 +++ qerror.h |3 ++ qmp-commands.hx|6 trace-events |4 +++ 12 files changed, 174 insertions(+), 0 deletions(-) diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index af586ec..0cd2275 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -264,3 +264,32 @@ Example: Note: If action is reset, shutdown, or pause the WATCHDOG event is followed respectively by the RESET, SHUTDOWN, or STOP events. + + +BLOCK_JOB_COMPLETED +--- + +Emitted when a block job has completed. + +Data: + +- type: Job type (stream for image streaming, json-string) +- device: Device name (json-string) +- len: Maximum progress value (json-int) +- offset: Current progress value (json-int) + On success this is equal to len. + On failure this is less than len. +- speed:Rate limit, bytes per second (json-int) +- error:Error message (json-string, optional) + Only present on failure. This field contains a human-readable + error message. There are no semantics other than that streaming + has failed and clients should not try to interpret the error + string. + +Example: + +{ event: BLOCK_JOB_COMPLETED, + data: { type: stream, device: virtio-disk0, + len: 10737418240, offset: 10737418240, + speed: 0 }, + timestamp: { seconds: 1267061043, microseconds: 959568 } } diff --git a/blockdev.c b/blockdev.c index 6d78b36..ba973b0 100644 --- a/blockdev.c +++ b/blockdev.c @@ -13,9 +13,11 @@ #include qerror.h #include qemu-option.h #include qemu-config.h +#include qemu-objects.h #include sysemu.h #include block_int.h #include qmp-commands.h +#include trace.h static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); @@ -880,3 +882,68 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp) return; } } + +static QObject *qobject_from_block_job(BlockJob *job) +{ +return qobject_from_jsonf({ 'type': %s, + 'device': %s, + 'len': % PRId64 , + 'offset': % PRId64 , + 'speed': % PRId64 }, + job-job_type-job_type, + bdrv_get_device_name(job-bs), + job-len, + job-offset, + job-speed); +} + +static void block_stream_cb(void *opaque, int ret) +{ +BlockDriverState *bs = opaque; +QObject *obj; + +trace_block_stream_cb(bs, bs-job, ret); + +assert(bs-job); +obj = qobject_from_block_job(bs-job); +if (ret 0) { +QDict *dict = qobject_to_qdict(obj); +qdict_put(dict, error, qstring_from_str(strerror(-ret))); +} + +monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj); +qobject_decref(obj); +} + +void qmp_block_stream(const char *device, bool has_base, + const char *base, Error **errp) +{ +BlockDriverState *bs; +int ret; + +bs = bdrv_find(device); +if (!bs) { +error_set(errp, QERR_DEVICE_NOT_FOUND, device); +return; +} + +/* Base device not supported */ +if (base) { +error_set(errp, QERR_NOT_SUPPORTED); +return; +} + +ret = stream_start(bs, NULL, block_stream_cb, bs); +if (ret 0) { +switch (ret) { +case -EBUSY: +error_set(errp, QERR_DEVICE_IN_USE, device); +return; +default: +error_set(errp, QERR_NOT_SUPPORTED); +return; +} +} + +trace_qmp_block_stream(bs, bs-job); +} diff --git a/hmp-commands.hx b/hmp-commands.hx index a586498..dc6c8c3 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -69,6 +69,19 @@ but should be used with extreme caution. Note that this command only resizes image files, it can not resize block devices like LVM volumes. ETEXI +{ +.name = block_stream, +.args_type = device:B,base:s?, +.params = device [base], +.help = copy data from a backing file into a block device, +.mhandler.cmd = hmp_block_stream, +}, +
Re: [Qemu-devel] [PATCH 0/3] acpi_piix4: Add CPU eject handling
On Fri, Jan 13, 2012 at 12:58:10PM +0100, Jan Kiszka wrote: Please work against upstream (uq/master for kvm-related patches), not qemu-kvm. It possibly makes no technical difference here, but we do not want to let the code bases needlessly diverge again. If if does make a difference and upstream lacks further bits, push them first. Apologies, I will from now on. thanks, - Vasilis
[Qemu-devel] [PATCH v5 09/15] qmp: add query-block-jobs
Add query-block-jobs, which shows the progress of ongoing block device operations. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- blockdev.c | 33 + hmp.c| 36 hmp.h|1 + monitor.c|7 +++ qapi-schema.json | 32 qmp-commands.hx |6 ++ 6 files changed, 115 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index 35de3bc..4549c9e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -989,3 +989,36 @@ void qmp_block_job_cancel(const char *device, Error **errp) trace_qmp_block_job_cancel(job); block_job_cancel(job); } + +static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) +{ +BlockJobInfoList **prev = opaque; +BlockJob *job = bs-job; + +if (job) { +BlockJobInfoList *elem; +BlockJobInfo *info = g_new(BlockJobInfo, 1); +*info = (BlockJobInfo){ +.type = g_strdup(job-job_type-job_type), +.device = g_strdup(bdrv_get_device_name(bs)), +.len= job-len, +.offset = job-offset, +.speed = job-speed, +}; + +elem = g_new0(BlockJobInfoList, 1); +elem-value = info; + +(*prev)-next = elem; +*prev = elem; +} +} + +BlockJobInfoList *qmp_query_block_jobs(Error **errp) +{ +/* Dummy is a fake list element for holding the head pointer */ +BlockJobInfoList dummy = {}; +BlockJobInfoList *prev = dummy; +bdrv_iterate(do_qmp_query_block_jobs_one, prev); +return dummy.next; +} diff --git a/hmp.c b/hmp.c index 851885b..76e89f8 100644 --- a/hmp.c +++ b/hmp.c @@ -507,6 +507,42 @@ void hmp_info_pci(Monitor *mon) qapi_free_PciInfoList(info); } +void hmp_info_block_jobs(Monitor *mon) +{ +BlockJobInfoList *list; +Error *err = NULL; + +list = qmp_query_block_jobs(err); +assert(!err); + +if (!list) { +monitor_printf(mon, No active jobs\n); +return; +} + +while (list) { +if (strcmp(list-value-type, stream) == 0) { +monitor_printf(mon, Streaming device %s: Completed % PRId64 +of % PRId64 bytes, speed limit % PRId64 +bytes/s\n, + list-value-device, + list-value-offset, + list-value-len, + list-value-speed); +} else { +monitor_printf(mon, Type %s, device %s: Completed % PRId64 +of % PRId64 bytes, speed limit % PRId64 +bytes/s\n, + list-value-type, + list-value-device, + list-value-offset, + list-value-len, + list-value-speed); +} +list = list-next; +} +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index 0ad2004..23bfca2 100644 --- a/hmp.h +++ b/hmp.h @@ -32,6 +32,7 @@ void hmp_info_vnc(Monitor *mon); void hmp_info_spice(Monitor *mon); void hmp_info_balloon(Monitor *mon); void hmp_info_pci(Monitor *mon); +void hmp_info_block_jobs(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 01850ca..f96a296 100644 --- a/monitor.c +++ b/monitor.c @@ -2483,6 +2483,13 @@ static mon_cmd_t info_cmds[] = { .mhandler.info = hmp_info_blockstats, }, { +.name = block-jobs, +.args_type = , +.params = , +.help = show progress of ongoing block device operations, +.mhandler.info = hmp_info_block_jobs, +}, +{ .name = registers, .args_type = , .params = , diff --git a/qapi-schema.json b/qapi-schema.json index 3d23ce2..b4f6b15 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -845,6 +845,38 @@ { 'command': 'query-pci', 'returns': ['PciInfo'] } ## +# @BlockJobInfo: +# +# Information about a long-running block device operation. +# +# @type: the job type ('stream' for image streaming) +# +# @device: the block device name +# +# @len: the maximum progress value +# +# @offset: the current progress value +# +# @speed: the rate limit, bytes per second +# +# Since: 1.1 +## +{ 'type': 'BlockJobInfo', + 'data': {'type': 'str', 'device': 'str', 'len': 'int', + 'offset': 'int', 'speed': 'int'} } + +## +# @query-block-jobs: +# +# Return information about long-running block device operations. +# +# Returns: a list of @BlockJobInfo for each active block job +# +# Since: 1.1 +## +{ 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] } + +## # @quit: # # This command will cause the
[Qemu-devel] [PATCH v5 08/15] qmp: add block_job_cancel command
Add block_job_cancel, which stops an active block streaming operation. When the operation has been cancelled the new BLOCK_JOB_CANCELLED event is emitted. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- QMP/qmp-events.txt | 24 blockdev.c | 19 ++- hmp-commands.hx| 14 ++ hmp.c | 10 ++ hmp.h |1 + monitor.c |3 +++ monitor.h |1 + qapi-schema.json | 29 + qmp-commands.hx|6 ++ trace-events |1 + 10 files changed, 107 insertions(+), 1 deletions(-) diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index 0cd2275..06cb404 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -293,3 +293,27 @@ Example: len: 10737418240, offset: 10737418240, speed: 0 }, timestamp: { seconds: 1267061043, microseconds: 959568 } } + + +BLOCK_JOB_CANCELLED +--- + +Emitted when a block job has been cancelled. + +Data: + +- type: Job type (stream for image streaming, json-string) +- device: Device name (json-string) +- len: Maximum progress value (json-int) +- offset: Current progress value (json-int) + On success this is equal to len. + On failure this is less than len. +- speed:Rate limit, bytes per second (json-int) + +Example: + +{ event: BLOCK_JOB_CANCELLED, + data: { type: stream, device: virtio-disk0, + len: 10737418240, offset: 134217728, + speed: 0 }, + timestamp: { seconds: 1267061043, microseconds: 959568 } } diff --git a/blockdev.c b/blockdev.c index 2dfca40..35de3bc 100644 --- a/blockdev.c +++ b/blockdev.c @@ -911,7 +911,11 @@ static void block_stream_cb(void *opaque, int ret) qdict_put(dict, error, qstring_from_str(strerror(-ret))); } -monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj); +if (block_job_is_cancelled(bs-job)) { +monitor_protocol_event(QEVENT_BLOCK_JOB_CANCELLED, obj); +} else { +monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj); +} qobject_decref(obj); } @@ -972,3 +976,16 @@ void qmp_block_job_set_speed(const char *device, int64_t value, Error **errp) error_set(errp, QERR_NOT_SUPPORTED); } } + +void qmp_block_job_cancel(const char *device, Error **errp) +{ +BlockJob *job = find_block_job(device); + +if (!job) { +error_set(errp, QERR_DEVICE_NOT_ACTIVE, device); +return; +} + +trace_qmp_block_job_cancel(job); +block_job_cancel(job); +} diff --git a/hmp-commands.hx b/hmp-commands.hx index 12b8433..b991ee0 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -98,6 +98,20 @@ Set maximum speed for a background block operation. ETEXI { +.name = block_job_cancel, +.args_type = device:B, +.params = device, +.help = stop an active block streaming operation, +.mhandler.cmd = hmp_block_job_cancel, +}, + +STEXI +@item block_job_cancel +@findex block_job_cancel +Stop an active block streaming operation. +ETEXI + +{ .name = eject, .args_type = force:-f,device:B, .params = [-f] device, diff --git a/hmp.c b/hmp.c index 1144d53..851885b 100644 --- a/hmp.c +++ b/hmp.c @@ -701,3 +701,13 @@ void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, error); } + +void hmp_block_job_cancel(Monitor *mon, const QDict *qdict) +{ +Error *error = NULL; +const char *device = qdict_get_str(qdict, device); + +qmp_block_job_cancel(device, error); + +hmp_handle_error(mon, error); +} diff --git a/hmp.h b/hmp.h index 2c871ea..0ad2004 100644 --- a/hmp.h +++ b/hmp.h @@ -51,5 +51,6 @@ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); void hmp_block_stream(Monitor *mon, const QDict *qdict); void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict); +void hmp_block_job_cancel(Monitor *mon, const QDict *qdict); #endif diff --git a/monitor.c b/monitor.c index bb42580..01850ca 100644 --- a/monitor.c +++ b/monitor.c @@ -482,6 +482,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) case QEVENT_BLOCK_JOB_COMPLETED: event_name = BLOCK_JOB_COMPLETED; break; +case QEVENT_BLOCK_JOB_CANCELLED: +event_name = BLOCK_JOB_CANCELLED; +break; default: abort(); break; diff --git a/monitor.h b/monitor.h index 7324236..86c997d 100644 --- a/monitor.h +++ b/monitor.h @@ -36,6 +36,7 @@ typedef enum MonitorEvent { QEVENT_SPICE_INITIALIZED, QEVENT_SPICE_DISCONNECTED, QEVENT_BLOCK_JOB_COMPLETED, +QEVENT_BLOCK_JOB_CANCELLED, QEVENT_MAX, } MonitorEvent; diff --git a/qapi-schema.json b/qapi-schema.json index
Re: [Qemu-devel] [0/9] Bugfixes and pseries enhancements
On 12.01.2012, at 06:46, David Gibson wrote: This series has two parts. THe first has a few bugfixes for generic qemu code. The second has a number of pseries machine specific enhancements and bugfixes. They are included in the one series because some of the pseries specific patches rely on the generic bugfixes (in the sense that they expose the bugs more badly than they were previously). I've posted some of the generic fixes before, this series respins the first one (load_image_targphys()) with a minor tweak, the rest are unchanged. I put all of them in my tree for now, waiting for you to figure the PCI host limit piece out with Michael. Alex
Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
Am 13.01.2012 13:14, schrieb Peter Maydell: On 11 January 2012 22:41, Peter Maydell peter.mayd...@linaro.org wrote: Does anybody object to my taking the AHCI patches along with this series via arm-devs.next ? (other than patch v4 which goes via target-arm.next) [I got an Acked-by: from Kevin over irc regarding these and will do this.] FWIW I don't object. Either the maintainership of AHCI doesn't fall under IDE or Kevin is busy - possibly both? Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
On 13.01.2012, at 15:15, Andreas Färber wrote: Am 13.01.2012 13:14, schrieb Peter Maydell: On 11 January 2012 22:41, Peter Maydell peter.mayd...@linaro.org wrote: Does anybody object to my taking the AHCI patches along with this series via arm-devs.next ? (other than patch v4 which goes via target-arm.next) [I got an Acked-by: from Kevin over irc regarding these and will do this.] FWIW I don't object. Either the maintainership of AHCI doesn't fall under IDE or Kevin is busy - possibly both? It falls under IDE and Kevin acked them :) Alex
[Qemu-devel] [PATCH 0/3] acpi_piix4: Add CPU eject handling
This patch series adds support for CPU _EJ0 callback in Seabios and qemu-kvm. The first patch defines the CPU eject bitmap in Seabios and writes to it during the callback. The second patch adds empty stub functions to qemu-kvm to handle the bitmap writes. The third patch defines the eject method to handle the CPU_DEAD event in Liu Ping Fan's cpu lifecycle/destruction patchseries, see: http://patchwork.ozlabs.org/patch/127832/ This ACPI implementation can be used instead of the cpustate virtio/pci device in the original series. Vasilis Liaskovitis (2): acpi_piix4: Add CPU ejection handling acpi_piix4: Call KVM_SETSTATE_VCPU ioctl on cpu ejection hw/acpi_piix4.c | 36 1 files changed, 36 insertions(+), 0 deletions(-) -- 1.7.7.3
[Qemu-devel] [PATCH v5 03/15] block: add BlockJob interface for long-running operations
Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- block.c | 48 block_int.h | 40 2 files changed, 88 insertions(+), 0 deletions(-) diff --git a/block.c b/block.c index daf92c2..d588ee8 100644 --- a/block.c +++ b/block.c @@ -3877,3 +3877,51 @@ out: return ret; } + +void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, + BlockDriverCompletionFunc *cb, void *opaque) +{ +BlockJob *job; + +if (bs-job || bdrv_in_use(bs)) { +return NULL; +} +bdrv_set_in_use(bs, 1); + +job = g_malloc0(job_type-instance_size); +job-job_type = job_type; +job-bs= bs; +job-cb= cb; +job-opaque= opaque; +bs-job = job; +return job; +} + +void block_job_complete(BlockJob *job, int ret) +{ +BlockDriverState *bs = job-bs; + +assert(bs-job == job); +job-cb(job-opaque, ret); +bs-job = NULL; +g_free(job); +bdrv_set_in_use(bs, 0); +} + +int block_job_set_speed(BlockJob *job, int64_t value) +{ +if (!job-job_type-set_speed) { +return -ENOTSUP; +} +return job-job_type-set_speed(job, value); +} + +void block_job_cancel(BlockJob *job) +{ +job-cancelled = true; +} + +bool block_job_is_cancelled(BlockJob *job) +{ +return job-cancelled; +} diff --git a/block_int.h b/block_int.h index 5362180..316443e 100644 --- a/block_int.h +++ b/block_int.h @@ -69,6 +69,36 @@ typedef struct BlockIOBaseValue { uint64_t ios[2]; } BlockIOBaseValue; +typedef void BlockJobCancelFunc(void *opaque); +typedef struct BlockJob BlockJob; +typedef struct BlockJobType { +/** Derived BlockJob struct size */ +size_t instance_size; + +/** String describing the operation, part of query-block-jobs QMP API */ +const char *job_type; + +/** Optional callback for job types that support setting a speed limit */ +int (*set_speed)(BlockJob *job, int64_t value); +} BlockJobType; + +/** + * Long-running operation on a BlockDriverState + */ +struct BlockJob { +const BlockJobType *job_type; +BlockDriverState *bs; +bool cancelled; + +/* These fields are published by the query-block-jobs QMP API */ +int64_t offset; +int64_t len; +int64_t speed; + +BlockDriverCompletionFunc *cb; +void *opaque; +}; + struct BlockDriver { const char *format_name; int instance_size; @@ -269,6 +299,9 @@ struct BlockDriverState { void *private; QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; + +/* long-running background operation */ +BlockJob *job; }; struct BlockDriverAIOCB { @@ -292,4 +325,11 @@ void bdrv_set_io_limits(BlockDriverState *bs, int is_windows_drive(const char *filename); #endif +void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, + BlockDriverCompletionFunc *cb, void *opaque); +void block_job_complete(BlockJob *job, int ret); +int block_job_set_speed(BlockJob *job, int64_t value); +void block_job_cancel(BlockJob *job); +bool block_job_is_cancelled(BlockJob *job); + #endif /* BLOCK_INT_H */ -- 1.7.7.3
Re: [Qemu-devel] [PATCH 3/3] acpi_piix4: Call KVM_SETSTATE_VCPU ioctl on cpu ejection
On Fri, Jan 13, 2012 at 12:58:53PM +0100, Jan Kiszka wrote: On 2012-01-13 12:11, Vasilis Liaskovitis wrote: Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com --- hw/acpi_piix4.c | 21 + 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 8bf30dd..12eef55 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -502,6 +502,27 @@ static uint32_t cpuej_read(void *opaque, uint32_t addr) static void cpuej_write(void *opaque, uint32_t addr, uint32_t val) { +struct kvm_vcpu_state state; +CPUState *env; +int cpu; +int ret; + +cpu = ffs(val); +/* zero means no bit was set, i.e. no CPU ejection happened */ +if (!cpu) + return; +cpu--; +env = cpu_phyid_to_cpu((uint64_t)cpu); +if (env != NULL) { +if (env-state == CPU_STATE_ZAPREQ) { +state.vcpu_id = env-cpu_index; +state.state = 1; +ret = kvm_vm_ioctl(env-kvm_state, KVM_SETSTATE_VCPU, state); That breaks in the absence of KVM or if it is not enabled. Right, I will rework. Do we expect icc-bus related changes on a CPU unplug? This patch does not handle this yet. Also, where was this IOCTL introduced? Where are the linux header changes? The headers are here: http://patchwork.ozlabs.org/patch/127834/ And the ioctl is introduced here: http://patchwork.ozlabs.org/patch/127828/ Though the actual ioctl code seems to have dropped through the cracks in the above patch. A sample implementation against 3.1.0 is below, but I have not included it in the patch series. I expect the ioctl implementation to be part of Liu 's kernel kvm-related series. In any case, this third patch depends on the cpu zap/lifecycle patchseries and perhaps should be reviewed separately from the first 2. diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 6d3a724..8dd9ebd 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2095,6 +2095,22 @@ static long kvm_vm_ioctl(struct file *filp, r = kvm_ioeventfd(kvm, data); break; } + case KVM_SETSTATE_VCPU: { + struct kvm_vcpu_state vcpu_state; + struct kvm_vcpu *vcpu; + int idx; + r = -EFAULT; + if (copy_from_user(vcpu_state, argp, + sizeof(struct kvm_vcpu_state))) + goto out; + idx = srcu_read_lock(kvm-srcu); + kvm_for_each_vcpu(vcpu, kvm) + if (vcpu_state.vcpu_id == vcpu-vcpu_id) + vcpu-state = vcpu_state.state; + srcu_read_unlock(kvm-srcu, idx); + r = 0; + break; + } #ifdef CONFIG_KVM_APIC_ARCHITECTURE case KVM_SET_BOOT_CPU_ID: r = 0;
Re: [Qemu-devel] [PATCH 03/30] ppc: remove ppc440 bamboo board support
Am 13.01.2012 13:30, schrieb Alexander Graf: On 13.01.2012, at 12:45, Paolo Bonzini wrote: On 01/13/2012 12:04 PM, Andreas Färber wrote: This board never worked with TCG. It hasn't been updated since 0.13.0. I'm fairly sure hardware doesn't exist anymore that you can run the KVM support with. It does exist, I have one:-) Alex has already posted series to not only qdev'ify it but to also add TCG support so other people can test it. Review and testing would probably be appreciated.:) The work that you guys are putting in modernizing the PPC boards is really cool. Please, let's start working on the 1.1 changelog now so that it doesn't get lost! Good point :). I'm not sure how useful something like Qdev'ified board xxx really is in a changelog though. It's mostly invisible to users. This is inviting a flame war on whether users read Change Logs and whether a Change Log needs to be useful to them. ;) I concur with Paolo that TCG support for Bamboo is worth mentioning (user-visible feature) and so would a new, real PReP machine if we manage in time. The conversions could be summarized under a QOM heading. But since neither has been applied to master yet, we should wait with the Change Log update. But thanks for the reminder, good idea! Andreas http://wiki.qemu.org/ChangeLog/1.1 -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Re: [Qemu-devel] Serious regression of 9p read performance, huge amount of openat syscalls on plain file descriptors
The regression does not exist in the way that I suspected - it's just that the default for 9p mount option msize=4096 causes the bad performance when reading large files on the guest. I was mislead because... a) mount -o remount,msize=...,... seems to work (with mount reporting the changed value afterwards), but it doesn't - only the msize chosen at first mount time is relevant/used. b) gdb lied to me: catch syscall openat Catchpoint 1 (syscall 'openat' [295]) I learned the hard way that the system supplied gdb made wrong assumptions on which syscall number is associated with what function. In fact, the so often used syscall was preadv, not openat. Thus my only suggestion is to change the default for msize= to 131072 (128k), this results in a speed up from ~ 30MB/s to ~ 290MB/s in the large-file reading use case. Regards, Lutz Vieweg On 01/12/2012 07:42 PM, Lutz Vieweg wrote: Hi all, I have been using 9p mounts on guests for quite some time, and enjoyed their nice performance. But not anymore: I noticed that just dd-ing large plain files to /dev/zero on the guest system became very slow, even if the data is completely in the cache of the host. The rate maxes at ~ 30MB/s while the qemu process on the host eats lots of CPU). Both qemu (from source repository) and host kernel (3.1.6) were upgraded since the last good benchmark, so this could be the result of some recent change... Looking for the cause I noticed that the qemu process, according to strace, does an insane amount of openat syscalls - about 820 per second! - while the guest system is reading the file (in 64kB chunks, if that matters). I guess it's no wonder that this huge amount of open operations per second will slow down whatever I/O qemu is trying to do. Especially strange is that the fds passed into the openat syscall as the first parameter refers to the file being read (not the directory it is in, which has a different fd), according to lsof. And the openat syscall always returns 0x1000 as a result (if strace is not lying), which is neither a credible fd, nor an errno I'd know of: [pid 29236] syscall_295(0x1b, 0x7fe46044a670, 0x1, 0x109e000, 0, 0, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00, 0x7fe46034ae00 unfinished ... [pid 29236] ... syscall_295 resumed ) = 0x1000 [pid 29235] syscall_295(0x1c, 0x7fe4659d8070, 0x1, 0x16df000, 0, 0, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800 unfinished ... [pid 29235] ... syscall_295 resumed ) = 0x1000 [pid 29234] syscall_295(0x1b, 0x7fe4659d8070, 0x1, 0x109f000, 0, 0, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800, 0x7fe4658d8800 unfinished ... [pid 29234] ... syscall_295 resumed ) = 0x1000 Alas, I could not get gdb to tell me exactly where those openat calls are made from (in the qemu-kvm source) - the functions that contain those calls are static and seem to become inlined. Does anyone have an idea what may have caused this? Do you still see good read performance when reading big plain files from a 9p mount. Regards, Lutz Vieweg
Re: [Qemu-devel] [PATCH 03/30] ppc: remove ppc440 bamboo board support
On 13.01.2012, at 15:24, Andreas Färber wrote: Am 13.01.2012 13:30, schrieb Alexander Graf: On 13.01.2012, at 12:45, Paolo Bonzini wrote: On 01/13/2012 12:04 PM, Andreas Färber wrote: This board never worked with TCG. It hasn't been updated since 0.13.0. I'm fairly sure hardware doesn't exist anymore that you can run the KVM support with. It does exist, I have one:-) Alex has already posted series to not only qdev'ify it but to also add TCG support so other people can test it. Review and testing would probably be appreciated.:) The work that you guys are putting in modernizing the PPC boards is really cool. Please, let's start working on the 1.1 changelog now so that it doesn't get lost! Good point :). I'm not sure how useful something like Qdev'ified board xxx really is in a changelog though. It's mostly invisible to users. This is inviting a flame war on whether users read Change Logs and whether a Change Log needs to be useful to them. ;) Users read changelogs. Packagers read changelogs. QEMU Developers read mailing lists. Libvirt developers might read changelogs. Qdev is a QEMU developer visible feature, so it doesn't belong into the changelog. Unless you want to argue that it makes stuff available through -device at which point it's management tool visible. Oh well. I probably just don't want to bloat it too much :). I concur with Paolo that TCG support for Bamboo is worth mentioning (user-visible feature) and so would a new, real PReP machine if we manage in time. Yes, both definitely should show up! The conversions could be summarized under a QOM heading. But since neither has been applied to master yet, we should wait with the Change Log update. But thanks for the reminder, good idea! If it's been posted on the ML, nobody complained on it and it's in the maintainer's queue, it's fine to update the changelog imho :). Alex Andreas http://wiki.qemu.org/ChangeLog/1.1 -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
Am 13.01.2012 15:18, schrieb Alexander Graf: On 13.01.2012, at 15:15, Andreas Färber wrote: Am 13.01.2012 13:14, schrieb Peter Maydell: On 11 January 2012 22:41, Peter Maydell peter.mayd...@linaro.org wrote: Does anybody object to my taking the AHCI patches along with this series via arm-devs.next ? (other than patch v4 which goes via target-arm.next) [I got an Acked-by: from Kevin over irc regarding these and will do this.] FWIW I don't object. Either the maintainership of AHCI doesn't fall under IDE or Kevin is busy - possibly both? It falls under IDE and Kevin acked them :) My RFC didn't get any review or testing yet, not from you either. ;( (But that is foremost waiting for Juan to comment on the VMState size issue the Samsung guys and me ran into. And it's in no way urgent for me currently or I would've ping'ed it already.) Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
On 13.01.2012, at 15:31, Andreas Färber wrote: Am 13.01.2012 15:18, schrieb Alexander Graf: On 13.01.2012, at 15:15, Andreas Färber wrote: Am 13.01.2012 13:14, schrieb Peter Maydell: On 11 January 2012 22:41, Peter Maydell peter.mayd...@linaro.org wrote: Does anybody object to my taking the AHCI patches along with this series via arm-devs.next ? (other than patch v4 which goes via target-arm.next) [I got an Acked-by: from Kevin over irc regarding these and will do this.] FWIW I don't object. Either the maintainership of AHCI doesn't fall under IDE or Kevin is busy - possibly both? It falls under IDE and Kevin acked them :) My RFC didn't get any review or testing yet, not from you either. ;( I'm sure he's still busy catching up on his email. He only got back this week :) (But that is foremost waiting for Juan to comment on the VMState size issue the Samsung guys and me ran into. And it's in no way urgent for me currently or I would've ping'ed it already.) Yup, that's the one big thing I would like to see addressed first too. Alex
[Qemu-devel] [PATCH v5 05/15] block: rate-limit streaming operations
This patch implements rate-limiting for image streaming. If we've exceeded the bandwidth quota for a 100 ms time slice we sleep the coroutine until the next slice begins. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- block/stream.c | 65 ++- 1 files changed, 59 insertions(+), 6 deletions(-) diff --git a/block/stream.c b/block/stream.c index 5255a61..93f0305 100644 --- a/block/stream.c +++ b/block/stream.c @@ -23,8 +23,39 @@ enum { STREAM_BUFFER_SIZE = 512 * 1024, /* in bytes */ }; +#define SLICE_TIME 1ULL /* ns */ + +typedef struct { +int64_t next_slice_time; +uint64_t slice_quota; +uint64_t dispatched; +} RateLimit; + +static int64_t ratelimit_calculate_delay(RateLimit *limit, uint64_t n) +{ +int64_t delay_ns = 0; +int64_t now = qemu_get_clock_ns(rt_clock); + +if (limit-next_slice_time now) { +limit-next_slice_time = now + SLICE_TIME; +limit-dispatched = 0; +} +if (limit-dispatched + n limit-slice_quota) { +delay_ns = limit-next_slice_time - now; +} else { +limit-dispatched += n; +} +return delay_ns; +} + +static void ratelimit_set_speed(RateLimit *limit, uint64_t speed) +{ +limit-slice_quota = speed / (10ULL / SLICE_TIME); +} + typedef struct StreamBlockJob { BlockJob common; +RateLimit limit; BlockDriverState *base; } StreamBlockJob; @@ -65,20 +96,24 @@ static void coroutine_fn stream_run(void *opaque) bdrv_enable_copy_on_read(bs); for (sector_num = 0; sector_num end; sector_num += n) { +retry: if (block_job_is_cancelled(s-common)) { break; } -/* TODO rate-limit */ -/* Note that even when no rate limit is applied we need to yield with - * no pending I/O here so that qemu_aio_flush() is able to return. - */ -co_sleep_ns(rt_clock, 0); - ret = bdrv_co_is_allocated(bs, sector_num, STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, n); trace_stream_one_iteration(s, sector_num, n, ret); if (ret == 0) { +if (s-common.speed) { +uint64_t delay_ns = ratelimit_calculate_delay(s-limit, n); +if (delay_ns 0) { +co_sleep_ns(rt_clock, delay_ns); + +/* Recheck cancellation and that sectors are unallocated */ +goto retry; +} +} ret = stream_populate(bs, sector_num, n, buf); } if (ret 0) { @@ -87,6 +122,11 @@ static void coroutine_fn stream_run(void *opaque) /* Publish progress */ s-common.offset += n * BDRV_SECTOR_SIZE; + +/* Note that even when no rate limit is applied we need to yield + * with no pending I/O here so that qemu_aio_flush() returns. + */ +co_sleep_ns(rt_clock, 0); } bdrv_disable_copy_on_read(bs); @@ -99,9 +139,22 @@ static void coroutine_fn stream_run(void *opaque) block_job_complete(s-common, ret); } +static int stream_set_speed(BlockJob *job, int64_t value) +{ +StreamBlockJob *s = container_of(job, StreamBlockJob, common); + +if (value 0) { +return -EINVAL; +} +job-speed = value; +ratelimit_set_speed(s-limit, value / BDRV_SECTOR_SIZE); +return 0; +} + static BlockJobType stream_job_type = { .instance_size = sizeof(StreamBlockJob), .job_type = stream, +.set_speed = stream_set_speed, }; int stream_start(BlockDriverState *bs, BlockDriverState *base, -- 1.7.7.3
[Qemu-devel] [PATCH v5 04/15] block: add image streaming block job
Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- Makefile.objs |1 + block/stream.c | 124 block_int.h|3 + trace-events |4 ++ 4 files changed, 132 insertions(+), 0 deletions(-) create mode 100644 block/stream.c diff --git a/Makefile.objs b/Makefile.objs index f4f52e0..949308d 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -35,6 +35,7 @@ block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-nested-y += qed-check.o block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o +block-nested-y += stream.o block-nested-$(CONFIG_WIN32) += raw-win32.o block-nested-$(CONFIG_POSIX) += raw-posix.o block-nested-$(CONFIG_LIBISCSI) += iscsi.o diff --git a/block/stream.c b/block/stream.c new file mode 100644 index 000..5255a61 --- /dev/null +++ b/block/stream.c @@ -0,0 +1,124 @@ +/* + * Image streaming + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi stefa...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include trace.h +#include block_int.h + +enum { +/* + * Size of data buffer for populating the image file. This should be large + * enough to process multiple clusters in a single call, so that populating + * contiguous regions of the image is efficient. + */ +STREAM_BUFFER_SIZE = 512 * 1024, /* in bytes */ +}; + +typedef struct StreamBlockJob { +BlockJob common; +BlockDriverState *base; +} StreamBlockJob; + +static int coroutine_fn stream_populate(BlockDriverState *bs, +int64_t sector_num, int nb_sectors, +void *buf) +{ +struct iovec iov = { +.iov_base = buf, +.iov_len = nb_sectors * BDRV_SECTOR_SIZE, +}; +QEMUIOVector qiov; + +qemu_iovec_init_external(qiov, iov, 1); + +/* Copy-on-read the unallocated clusters */ +return bdrv_co_readv(bs, sector_num, nb_sectors, qiov); +} + +static void coroutine_fn stream_run(void *opaque) +{ +StreamBlockJob *s = opaque; +BlockDriverState *bs = s-common.bs; +int64_t sector_num, end; +int ret = 0; +int n; +void *buf; + +s-common.len = bdrv_getlength(bs); +if (s-common.len 0) { +block_job_complete(s-common, s-common.len); +return; +} + +end = s-common.len BDRV_SECTOR_BITS; +buf = qemu_blockalign(bs, STREAM_BUFFER_SIZE); + +bdrv_enable_copy_on_read(bs); + +for (sector_num = 0; sector_num end; sector_num += n) { +if (block_job_is_cancelled(s-common)) { +break; +} + +/* TODO rate-limit */ +/* Note that even when no rate limit is applied we need to yield with + * no pending I/O here so that qemu_aio_flush() is able to return. + */ +co_sleep_ns(rt_clock, 0); + +ret = bdrv_co_is_allocated(bs, sector_num, + STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, n); +trace_stream_one_iteration(s, sector_num, n, ret); +if (ret == 0) { +ret = stream_populate(bs, sector_num, n, buf); +} +if (ret 0) { +break; +} + +/* Publish progress */ +s-common.offset += n * BDRV_SECTOR_SIZE; +} + +bdrv_disable_copy_on_read(bs); + +if (sector_num == end ret == 0) { +ret = bdrv_change_backing_file(bs, NULL, NULL); +} + +qemu_vfree(buf); +block_job_complete(s-common, ret); +} + +static BlockJobType stream_job_type = { +.instance_size = sizeof(StreamBlockJob), +.job_type = stream, +}; + +int stream_start(BlockDriverState *bs, BlockDriverState *base, + BlockDriverCompletionFunc *cb, void *opaque) +{ +StreamBlockJob *s; +Coroutine *co; + +s = block_job_create(stream_job_type, bs, cb, opaque); +if (!s) { +return -EBUSY; /* bs must already be in use */ +} + +s-base = base; + +co = qemu_coroutine_create(stream_run); +trace_stream_start(bs, base, s, co, opaque); +qemu_coroutine_enter(co, s); +return 0; +} diff --git a/block_int.h b/block_int.h index 316443e..c7c9178 100644 --- a/block_int.h +++ b/block_int.h @@ -332,4 +332,7 @@ int block_job_set_speed(BlockJob *job, int64_t value); void block_job_cancel(BlockJob *job); bool block_job_is_cancelled(BlockJob *job); +int stream_start(BlockDriverState *bs, BlockDriverState *base, + BlockDriverCompletionFunc *cb, void *opaque); + #endif /* BLOCK_INT_H */ diff --git a/trace-events b/trace-events index 360f039..c5368fa 100644 --- a/trace-events +++ b/trace-events @@ -70,6 +70,10 @@ bdrv_co_write_zeroes(void *bs, int64_t sector_num, int nb_sector) bs %p sector_ bdrv_co_io_em(void *bs,