[Qemu-devel] [PATCH v3 4/4] xilinx_zynq: machine model initial version
Xilinx zynq-7000 machine model. Also includes device model for the zynq-specific system level control register (SLCR) module. Signed-off-by: Peter A. G. Crosthwaite --- changes since v2: removed 2 compile warnings from zynq_arm_sysctl.c changes since v1: Added gem init function remowed WDT instantiation Added maintainers information removed dead sys_id and proc_id variables MAINTAINERS |5 + Makefile.target |1 + hw/xilinx_zynq.c | 178 + hw/zynq_arm_sysctl.c | 526 ++ 4 files changed, 710 insertions(+), 0 deletions(-) create mode 100644 hw/xilinx_zynq.c create mode 100644 hw/zynq_arm_sysctl.c diff --git a/MAINTAINERS b/MAINTAINERS index 173e893..9246bfa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -237,6 +237,11 @@ M: Peter Maydell S: Maintained F: hw/versatilepb.c +Xilinx Zynq +M: Peter Crosthwaite +S: Maintained +F: hw/xilinx_zynq.c + CRIS Machines - Axis Dev88 diff --git a/Makefile.target b/Makefile.target index 84b559c..40fd1b2 100644 --- a/Makefile.target +++ b/Makefile.target @@ -346,6 +346,7 @@ obj-arm-y += versatile_pci.o obj-arm-y += cadence_uart.o obj-arm-y += cadence_ttc.o obj-arm-y += cadence_gem.o +obj-arm-y += xilinx_zynq.o zynq_arm_sysctl.o obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o obj-arm-y += arm_l2x0.o obj-arm-y += arm_mptimer.o diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c new file mode 100644 index 000..36765fb --- /dev/null +++ b/hw/xilinx_zynq.c @@ -0,0 +1,178 @@ +/* + * Xilinx Zynq Baseboard System emulation. + * + * Copyright (c) 2010 Xilinx. + * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.croshtwa...@petalogix.com) + * Copyright (c) 2012 Petalogix Pty Ltd. + * Written by Haibing Ma + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA + * 02139, USA. + */ + +#include "sysbus.h" +#include "arm-misc.h" +#include "net.h" +#include "exec-memory.h" +#include "sysemu.h" +#include "boards.h" +#include "flash.h" +#include "blockdev.h" +#include "loader.h" + +#define FLASH_SIZE (64 * 1024 * 1024) +#define FLASH_SECTOR_SIZE (128 * 1024) + +#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */ + +static struct arm_boot_info zynq_binfo = {}; + +static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq) +{ +DeviceState *dev; +SysBusDevice *s; + +qemu_check_nic_model(nd, "cadence_gem"); +dev = qdev_create(NULL, "cadence_gem"); +qdev_set_nic_properties(dev, nd); +qdev_init_nofail(dev); +s = sysbus_from_qdev(dev); +sysbus_mmio_map(s, 0, base); +sysbus_connect_irq(s, 0, irq); +} + +static void zynq_init(ram_addr_t ram_size, const char *boot_device, +const char *kernel_filename, const char *kernel_cmdline, +const char *initrd_filename, const char *cpu_model) +{ +CPUState *env = NULL; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ext_ram = g_new(MemoryRegion, 1); +MemoryRegion *ocm_ram = g_new(MemoryRegion, 1); +DeviceState *dev; +SysBusDevice *busdev; +qemu_irq *irqp; +qemu_irq pic[64]; +NICInfo *nd; +int n; +qemu_irq cpu_irq[4]; + +if (!cpu_model) { +cpu_model = "cortex-a9"; +} + +for (n = 0; n < smp_cpus; n++) { +env = cpu_init(cpu_model); +if (!env) { +fprintf(stderr, "Unable to find CPU definition\n"); +exit(1); +} +irqp = arm_pic_init_cpu(env); +cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; +} + +/* max 2GB ram */ +if (ram_size > 0x8000) { +ram_size = 0x8000; +} + +/* DDR remapped to address zero. */ +memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size); +vmstate_register_ram_global(ext_ram); +memory_region_add_subregion(address_space_mem, 0, ext_ram); + +/* 256K of on-chip memory */ +memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10); +vmstate_register_ram_global(ocm_ram); +memory_region_add_subregion(address_space_mem, 0xFFFC, ocm_ram); + +DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); + +#ifndef ZYNQ_FLASH_INTEL +/* AMD */ +pflash_cfi02_register(0xe200, NULL, "zynq.pflash", FLASH_SIZE, + dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE, + FLASH_SIZE/FLASH_SECTOR_SIZE, 1, + 1, 0x0066, 0x0022, 0x, 0x, 0x0555, 0x2aa, + 0); +#else +/* INTEL is working well */ +pflash_cfi01_register(0xe2
[Qemu-devel] [PATCH v3 3/4] cadence_gem: initial version of device model
Device model for cadence gem ethernet controller. Signed-off-by: Peter A. G. Crosthwaite Signed-off-by: John Linn --- changes from v1: removed global init function marked vmsd as unmigratable cleaned up debug messages Makefile.target |1 + hw/cadence_gem.c | 1229 ++ 2 files changed, 1230 insertions(+), 0 deletions(-) create mode 100644 hw/cadence_gem.c diff --git a/Makefile.target b/Makefile.target index 1e8afe6..84b559c 100644 --- a/Makefile.target +++ b/Makefile.target @@ -345,6 +345,7 @@ obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o obj-arm-y += versatile_pci.o obj-arm-y += cadence_uart.o obj-arm-y += cadence_ttc.o +obj-arm-y += cadence_gem.o obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o obj-arm-y += arm_l2x0.o obj-arm-y += arm_mptimer.o diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c new file mode 100644 index 000..0dfa47d --- /dev/null +++ b/hw/cadence_gem.c @@ -0,0 +1,1229 @@ +/* + * QEMU Xilinx GEM emulation + * + * Copyright (c) 2011 Xilinx, Inc. + * + * 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 /* For crc32 */ +#include + +#include "sysbus.h" +#include "net.h" +#include "devices.h" +#include "sysemu.h" +#include "net/checksum.h" + +#ifdef CADENCE_GEM_ERR_DEBUG +#define qemu_debug(...) do { \ +fprintf(stderr, ": %s: ", __func__); \ +fprintf(stderr, ## __VA_ARGS__); \ +fflush(stderr); \ +} while (0); +#else +#define qemu_debug(...) +#endif + +#define GEM_NWCTRL 0x /* Network Control reg */ +#define GEM_NWCFG 0x0004 /* Network Config reg */ +#define GEM_NWSTATUS0x0008 /* Network Status reg */ +#define GEM_USERIO 0x000C /* User IO reg */ +#define GEM_DMACFG 0x0010 /* DMA Control reg */ +#define GEM_TXSTATUS0x0014 /* TX Status reg */ +#define GEM_RXQBASE 0x0018 /* RX Q Base address reg */ +#define GEM_TXQBASE 0x001C /* TX Q Base address reg */ +#define GEM_RXSTATUS0x0020 /* RX Status reg */ +#define GEM_ISR 0x0024 /* Interrupt Status reg */ +#define GEM_IER 0x0028 /* Interrupt Enable reg */ +#define GEM_IDR 0x002C /* Interrupt Disable reg */ +#define GEM_IMR 0x0030 /* Interrupt Mask reg */ +#define GEM_PHYMNTNC0x0034 /* Phy Maintaince reg */ +#define GEM_RXPAUSE 0x0038 /* RX Pause Time reg */ +#define GEM_TXPAUSE 0x003C /* TX Pause Time reg */ +#define GEM_TXPARTIALSF 0x0040 /* TX Partial Store and Forward */ +#define GEM_RXPARTIALSF 0x0044 /* RX Partial Store and Forward */ +#define GEM_HASHLO 0x0080 /* Hash Low address reg */ +#define GEM_HASHHI 0x0084 /* Hash High address reg */ +#define GEM_SPADDR1LO 0x0088 /* Specific addr 1 low reg */ +#define GEM_SPADDR1HI 0x008C /* Specific addr 1 high reg */ +#define GEM_SPADDR2LO 0x0090 /* Specific addr 2 low reg */ +#define GEM_SPADDR2HI 0x0094 /* Specific addr 2 high reg */ +#define GEM_SPADDR3LO 0x0098 /* Specific addr 3 low reg */ +#define GEM_SPADDR3HI 0x009C /* Specific addr 3 high reg */ +#define GEM_SPADDR4LO 0x00A0 /* Specific addr 4 low reg */ +#define GEM_SPADDR4HI 0x00A4 /* Specific addr 4 high reg */ +#define GEM_TIDMATCH1 0x00A8 /* Type ID1 Match reg */ +#define GEM_TIDMATCH2 0x00AC /* Type ID2 Match reg */ +#define GEM_TIDMATCH3 0x00B0 /* Type ID3 Match reg */ +#define GEM_TIDMATCH4 0x00B4 /* Type ID4 Match reg */ +#define GEM_WOLAN 0x00B8 /* Wake on LAN reg */ +#define GEM_IPGSTRETCH 0x00BC /* IPG Stretch reg */ +#define GEM_SVLAN 0x00C0 /* Stacked VLAN reg */ +#define GEM_MODID 0x00FC /* Module ID reg */ +#define GEM_OCTTXLO 0x0100 /* Octects transmitted Low reg */ +#define GEM_OCTTXHI 0x0104 /* Octects transmitted High reg */ +#define GEM_TXC
[Qemu-devel] [PATCH v3 2/4] cadence_ttc: initial version of device model
Implemented cadence Triple Timer Counter (TCC) Signed-off-by: Peter A. G. Crosthwaite Signed-off-by: John Linn --- changed from v2 changed ptimer to QEMUTimer (Fixed skew/drift issue in timer delays) changes from v1 refactored event driven code marked vmsd as unmigratable Makefile.target |1 + hw/cadence_ttc.c | 435 ++ 2 files changed, 436 insertions(+), 0 deletions(-) create mode 100644 hw/cadence_ttc.c diff --git a/Makefile.target b/Makefile.target index 411a4bf..1e8afe6 100644 --- a/Makefile.target +++ b/Makefile.target @@ -344,6 +344,7 @@ obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o obj-arm-y += versatile_pci.o obj-arm-y += cadence_uart.o +obj-arm-y += cadence_ttc.o obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o obj-arm-y += arm_l2x0.o obj-arm-y += arm_mptimer.o diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c new file mode 100644 index 000..1f0ca42 --- /dev/null +++ b/hw/cadence_ttc.c @@ -0,0 +1,435 @@ +/* + * Xilinx Zynq cadence TTC model + * + * Copyright (c) 2011 Xilinx Inc. + * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwa...@petalogix.com) + * Copyright (c) 2012 PetaLogix Pty Ltd. + * Written By Haibing Ma + *M. Habib + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA + * 02139, USA. + */ + +#include "sysbus.h" +#include "qemu-timer.h" + +#ifdef CADENCE_TTC_ERR_DEBUG +#define qemu_debug(...) do { \ +fprintf(stderr, ": %s: ", __func__); \ +fprintf(stderr, ## __VA_ARGS__); \ +fflush(stderr); \ +} while (0); +#else +#define qemu_debug(...) +#endif + +#define COUNTER_INTR_IV 0x0001 +#define COUNTER_INTR_M1 0x0002 +#define COUNTER_INTR_M2 0x0004 +#define COUNTER_INTR_M3 0x0008 +#define COUNTER_INTR_OV 0x0010 +#define COUNTER_INTR_EV 0x0020 + +#define COUNTER_CTRL_DIS0x0001 +#define COUNTER_CTRL_INT0x0002 +#define COUNTER_CTRL_DEC0x0004 +#define COUNTER_CTRL_MATCH 0x0008 +#define COUNTER_CTRL_RST0x0010 + +#define CLOCK_CTRL_PS_EN0x0001 +#define CLOCK_CTRL_PS_V 0x001e + +typedef struct { +QEMUTimer *timer; +int freq; + +uint32_t reg_clock; +uint32_t reg_count; +uint32_t reg_value; +uint16_t reg_interval; +uint16_t reg_match[3]; +uint32_t reg_intr; +uint32_t reg_intr_en; +uint32_t reg_event_ctrl; +uint32_t reg_event; + +uint64_t cpu_time; +unsigned int cpu_time_valid; + +qemu_irq irq; +} CadenceTimerState; + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +CadenceTimerState * timer[3]; +} cadence_ttc_state; + +static void cadence_timer_update(CadenceTimerState *s) +{ +qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en)); +} + +static CadenceTimerState *cadence_timer_from_addr(void *opaque, +target_phys_addr_t offset) +{ +unsigned int index; +cadence_ttc_state *s = (cadence_ttc_state *)opaque; + +index = (offset >> 2) % 3; + +return s->timer[index]; +} + +static uint64_t cadence_timer_get_ns(CadenceTimerState *s, uint64_t timer_steps) +{ +/* timer_steps has max value of 0x1. double check it + * (or overflow can happen below) */ +assert(timer_steps <= 1ULL << 32); + +uint64_t r = timer_steps * 10ULL; +if (s->reg_clock & CLOCK_CTRL_PS_EN) { +r >>= 16 - (((s->reg_clock & CLOCK_CTRL_PS_V) >> 1) + 1); +} else { +r >>= 16; +} +r /= (uint64_t)s->freq; +return r; +} + +static uint64_t cadence_timer_get_steps(CadenceTimerState *s, uint64_t ns) +{ +uint64_t to_divide = 10ULL; + +uint64_t r = ns; + /* for very large intervals (> 8s) do some division first to stop + * overflow (costs some prescision) */ +while (r >= 8ULL << 30 && to_divide > 1) { +r /= 1000; +to_divide /= 1000; +} +r <<= 16; +/* keep early-dividing as needed */ +while (r >= 8ULL << 30 && to_divide > 1) { +r /= 1000; +to_divide /= 1000; +} +r *= (uint64_t)s->freq; +if (s->reg_clock & CLOCK_CTRL_PS_EN) { +r /= 1 << (((s->reg_clock & CLOCK_CTRL_PS_V) >> 1) + 1); +} + +r /= to_divide; +return r; +} + +static inline int64_t is_between(int64_t x, int64_t a, int64_t b) +{ +if (a < b) { +return x > a && x <= b; +} +return x < a && x >= b; +} + +static void cadence_timer_run(CadenceTimerSt
[Qemu-devel] [PATCH v3 1/4] cadence_uart: initial version of device model
Implemented cadence UART serial controller Signed-off-by: Peter A. G. Crosthwaite Signed-off-by: John Linn --- changes from v1: converted register file to array added vmsd state save/load support removed read side effects from CISR register Makefile.target |1 + hw/cadence_uart.c | 561 + 2 files changed, 562 insertions(+), 0 deletions(-) create mode 100644 hw/cadence_uart.c diff --git a/Makefile.target b/Makefile.target index 29fde6e..411a4bf 100644 --- a/Makefile.target +++ b/Makefile.target @@ -343,6 +343,7 @@ endif obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o obj-arm-y += versatile_pci.o +obj-arm-y += cadence_uart.o obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o obj-arm-y += arm_l2x0.o obj-arm-y += arm_mptimer.o diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c new file mode 100644 index 000..1a57519 --- /dev/null +++ b/hw/cadence_uart.c @@ -0,0 +1,561 @@ +/* + * Device model for Cadence UART + * + * Copyright (c) 2010 Xilinx Inc. + * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwa...@petalogix.com) + * Copyright (c) 2012 PetaLogix Pty Ltd. + * Written by Haibing Ma + *M.Habib + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA + * 02139, USA. + */ + +#include "sysbus.h" +#include "qemu-char.h" +#include "qemu-timer.h" + +#ifdef CADENCE_UART_ERR_DEBUG +#define qemu_debug(...) do { \ +fprintf(stderr, ": %s: ", __func__); \ +fprintf(stderr, ## __VA_ARGS__); \ +fflush(stderr); \ +} while (0); +#else +#define qemu_debug(...) +#endif + +#define UART_INTR_RTRIG 0x0001 +#define UART_INTR_REMPTY0x0002 +#define UART_INTR_RFUL 0x0004 +#define UART_INTR_TEMPTY0x0008 +#define UART_INTR_TFUL 0x0010 +#define UART_INTR_ROVR 0x0020 +#define UART_INTR_FRAME 0x0040 +#define UART_INTR_PARE 0x0080 +#define UART_INTR_TIMEOUT 0x0100 +#define UART_INTR_DMSI 0x0200 +#define UART_INTR_TTRIG 0x0400 +#define UART_INTR_TNFUL 0x0800 +#define UART_INTR_TOVR 0x1000 + +#define UART_CSR_RTRIG 0x0001 +#define UART_CSR_REMPTY 0x0002 +#define UART_CSR_RFUL 0x0004 +#define UART_CSR_TEMPTY 0x0008 +#define UART_CSR_TFUL 0x0010 +#define UART_CSR_ROVR 0x0020 +#define UART_CSR_FRAME 0x0040 +#define UART_CSR_PARE 0x0080 +#define UART_CSR_TIMEOUT0x0100 +#define UART_CSR_DMSI 0x0200 +#define UART_CSR_RACTIVE0x0400 +#define UART_CSR_TACTIVE0x0800 +#define UART_CSR_FDELT 0x1000 +#define UART_CSR_TTRIG 0x2000 +#define UART_CSR_TNFUL 0x4000 + +#define UART_CR_STOPBRK 0x0100 +#define UART_CR_STARTBRK0x0080 +#define UART_CR_RST_TO 0x0040 +#define UART_CR_TX_DIS 0x0020 +#define UART_CR_TX_EN 0x0010 +#define UART_CR_RX_DIS 0x0008 +#define UART_CR_RX_EN 0x0004 +#define UART_CR_TXRST 0x0002 +#define UART_CR_RXRST 0x0001 + +#define UART_MR_CLKS0x0001 +#define UART_MR_CHRL0x0006 +#define UART_MR_PAR 0x0038 +#define UART_MR_NBSTOP 0x00C0 +#define UART_MR_CHMODE 0x0300 +#define UART_MR_UCLKEN 0x0400 +#define UART_MR_IRMODE 0x0800 + +#define UART_PARITY_ODD0x001 +#define UART_PARITY_EVEN 0x000 +#define UART_DATA_BITS_6 0x003 +#define UART_DATA_BITS_7 0x002 +#define UART_STOP_BITS_1 0x003 +#define UART_STOP_BITS_2 0x002 +#define RX_FIFO_SIZE 16 +#define TX_FIFO_SIZE 16 +#define UARK_INPUT_CLK 5000 + +#define NORMAL_MODE0 +#define ECHO_MODE 1 +#define LOCAL_LOOPBACK 2 +#define REMOTE_LOOPBACK3 + +#define R_CR (0x00/4) +#define R_MR (0x04/4) +#define R_IER (0x08/4) +#define R_IDR (0x0C/4) +#define R_IMR (0x10/4) +#define R_CISR (0x14/4) +#define R_BRGR (0x18/4) +#define R_RTOR (0x1C/4) +#define R_RTRIG(0x20/4) +#define R_MCR (0x24/4) +#define R_MSR (0x28/4) +#define R_CSR (0x2C/4) +#define R_TX_RX(0x30/4) +#define R_BDIV (0x34/4) +#define R_FDEL (0x38/4) +#define R_PMIN (0x3C/4) +#define R_PWID (0x40/4) +#define R_TTRIG(0x44/4) + +#define R_MAX (R_TTRIG + 1) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iome
[Qemu-devel] [PATCH v3 0/4] Zynq-7000 EPP platform model
This is a suite of Device models and a machine model for the Xilinx Zynq-7000 Extensible Processing Platform: http://www.xilinx.com/products/silicon-devices/epp/zynq-7000/index.htm This is an ARM based platform featuring embedded SoC peripherals. This patch series includes a minimal set of device models and a a machine model capable of emulating zynq platforms booting linux. This first 3 patches in this series are device models for IP provided by cadence for the Zynq platform. The final patch is the initial revision of the zynq machine model. Most of this work was originally authored by Xilinx, as indicated by (c) notices in added files. Tree is available from: git://developer.petalogix.com/private/peterc/qemu.git --- changed from v2: fixed timer prescision issue (2/4) fixed compile warnings in zynq_arm_sysctl (4/4) changes from v1: formatting and style fixes updated for QOM removed former patch 3 (cadence WDT device model) - not required removed former patch 5 (dtb argument) - this is currently under discussion in other patch series' removed former patch 6 (initrd parameterisation) - not required for minimal boot Peter A. G. Crosthwaite (4): cadence_uart: initial version of device model cadence_ttc: initial version of device model cadence_gem: initial version of device model xilinx_zynq: machine model initial version MAINTAINERS |5 + Makefile.target |4 + hw/cadence_gem.c | 1229 ++ hw/cadence_ttc.c | 435 ++ hw/cadence_uart.c| 561 +++ hw/xilinx_zynq.c | 178 hw/zynq_arm_sysctl.c | 526 + 7 files changed, 2938 insertions(+), 0 deletions(-) create mode 100644 hw/cadence_gem.c create mode 100644 hw/cadence_ttc.c create mode 100644 hw/cadence_uart.c create mode 100644 hw/xilinx_zynq.c create mode 100644 hw/zynq_arm_sysctl.c -- 1.7.3.2
Re: [Qemu-devel] [PATCH 1/3] Add support for 128-bit arithmeticRe: [PATCH 1/3] Add support for 128-bit arithmetic
Am 10.02.2012 10:51, schrieb Jay Foad: > On 30 Oct 2011, Avi Kivity wrote: >> The memory API supports 64-bit buses (e.g. PCI). A size on such a bus cannot >> be represented with a 64-bit data type, if both 0 and the entire address >> space size are to be represented. Futhermore, any address arithemetic may >> overflow and return unexpected results. >> >> Introduce a 128-bit signed integer type for use in such cases. Addition, >> subtraction, and comparison are the only operations supported. >> >> Signed-off-by: Avi Kivity >> --- >> int128.h | 116 >> ++ >> 1 files changed, 116 insertions(+), 0 deletions(-) >> create mode 100644 int128.h >> >> diff --git a/int128.h b/int128.h >> new file mode 100644 >> index 000..b3864b6 >> --- /dev/null >> +++ b/int128.h >> @@ -0,0 +1,116 @@ >> +#ifndef INT128_H >> +#define INT128_H >> + >> +typedef struct Int128 Int128; >> + >> +struct Int128 { >> +uint64_t lo; >> +int64_t hi; >> +}; > >> +static inline Int128 int128_add(Int128 a, Int128 b) >> +{ >> +Int128 r = { a.lo + b.lo, a.hi + b.hi }; >> +r.hi += (r.lo < a.lo) || (r.lo < b.lo); >> +return r; >> +} > > This is a bit redundant. You only need either: > >r.hi += r.lo < a.lo; > > or: > >r.hi += r.lo < b.lo; > > because the way that two's complement addition works means that r.lo > will always be less than both a.lo and b.lo, or > greater-than-or-equal-to both of them. > >> +static inline bool int128_ge(Int128 a, Int128 b) >> +{ >> +return int128_nonneg(int128_sub(a, b)); >> +} > > This is wrong if you get signed overflow in int128_sub(a, b). > >> Regardless, the need for careful coding means subtle bugs, > > Indeed :-) Are these just theoretical issues or does anything in particular break for you? These functions were introduced to tackle int64_t overflow issues in the Memory API, not as an arbitrary API AFAIU. If nothing's broken in practice it would be best if you could just send a patch with your proposed fix rather than describing it in words. :) 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] How to follow a child process created in the guest OS?
On Sat, 11 Feb 2012, Andreas F?rber wrote: > Am 10.02.2012 11:26, schrieb ???: > > On Fri, Feb 10, 2012 at 08:14:41AM +, Stefan Hajnoczi wrote: > >> On Thu, Feb 09, 2012 at 06:33:16PM +0800, ??? wrote: > >>> I am running a tiny OS on QEMU and debugging it with gdbstub. The tiny OS > >>> will > >>> fork process 1, 2, ... and so on. I want to follow the child process, > >>> [...] > >>> > >>> Is there a way to do what I'm trying to do? Thanks! > > > - Tiny OS code - > > void main(void) /* This really IS void, no error here. */ > > { > > /* initialize enviroment */ > > > > sti(); > > move_to_user_mode(); > > if (!fork()) {/* we count on this going ok */ > > init(); // task 1 > > } > > > > for(;;) pause(); // task 0 > > } > > > > > > I am running this tiny OS on QEMU then using GDB to connect it. > > I want to follow task 1 after the forking, [...] > > Since this seems to be your code, if this were PowerPC I'd simply try to > place via inline assembler a trap instruction first thing inside the Being hardcore are we? __builtin_trap () is there for a reason. > init() function. That can easily be caught in gdbstub. > > Depending on what you really want to do, you could always try some > printf-style output to serial. ;) > > Andreas > > -- mailto:av1...@comtv.ru
Re: [Qemu-devel] Memory: how to determine the max memory size of one VM?
> Am 11.02.2012 00:25, schrieb Paul Brook: > >> ii) Some tracing of mine indicates QEMU has a highly dynamic memory > >> usage during runtime, be it due to network layer, block layer or > >> whatever exactly. > > > > We do? Significant compared to the size of guest ram? That sounds like a > > bug. > > Attached is a gnuplot from a simpletrace trace file while installing a > SLES 11 SP2 Release Candidate over slirp to virtio with -m 8G on an 8 > GiB host (post-1.0 master). > > It's not fully scientifically correct (it doesn't take into account > memory allocations not traced by QEMU itself, like pthreads) but it > suggests that after the initial surge to ~8.7 GB we have a fluctuation > of ~0.2 GB for 8 GiB guest RAM. It's larger than I'd expect at least. > > Since the user was close to the limit, this lead to an abort. In their > case it was a pthread_create() that failed, and we used tap + virtio. Hmm, yes, we're clearly allocating some very large buffers somewhere. Paul
Re: [Qemu-devel] How to follow a child process created in the guest OS?
Am 10.02.2012 11:26, schrieb 陳韋任: > On Fri, Feb 10, 2012 at 08:14:41AM +, Stefan Hajnoczi wrote: >> On Thu, Feb 09, 2012 at 06:33:16PM +0800, 陳韋任 wrote: >>> I am running a tiny OS on QEMU and debugging it with gdbstub. The tiny OS >>> will >>> fork process 1, 2, ... and so on. I want to follow the child process, [...] >>> >>> Is there a way to do what I'm trying to do? Thanks! > - Tiny OS code - > void main(void) /* This really IS void, no error here. */ > { > /* initialize enviroment */ > > sti(); > move_to_user_mode(); > if (!fork()) {/* we count on this going ok */ > init(); // task 1 > } > > for(;;) pause(); // task 0 > } > > > I am running this tiny OS on QEMU then using GDB to connect it. > I want to follow task 1 after the forking, [...] Since this seems to be your code, if this were PowerPC I'd simply try to place via inline assembler a trap instruction first thing inside the init() function. That can easily be caught in gdbstub. Depending on what you really want to do, you could always try some printf-style output to serial. ;) 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] Memory: how to determine the max memory size of one VM?
Am 11.02.2012 00:25, schrieb Paul Brook: >> ii) Some tracing of mine indicates QEMU has a highly dynamic memory >> usage during runtime, be it due to network layer, block layer or >> whatever exactly. > > We do? Significant compared to the size of guest ram? That sounds like a bug. Attached is a gnuplot from a simpletrace trace file while installing a SLES 11 SP2 Release Candidate over slirp to virtio with -m 8G on an 8 GiB host (post-1.0 master). It's not fully scientifically correct (it doesn't take into account memory allocations not traced by QEMU itself, like pthreads) but it suggests that after the initial surge to ~8.7 GB we have a fluctuation of ~0.2 GB for 8 GiB guest RAM. It's larger than I'd expect at least. Since the user was close to the limit, this lead to an abort. In their case it was a pthread_create() that failed, and we used tap + virtio. Didn't investigate the exact origin of the fluctuations (yet), but the combination of the choice to have virtually all allocations abort (which is okay at startup) and of doing allocations during guest runtime turns out Bad(tm) in practice. 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] How to follow a child process created in the guest OS?
> I am running this tiny OS on QEMU then using GDB to connect it. > > I want to follow task 1 after the forking, but it seems that GDB > stick with task 0 and cannot follow task 1 even I do `set follow-fork-mode > child`. You have exactly one CPU. That's what the qemu GDB stub exposes. Multiple processes are an illusion created by your operating system. It is not something qemu knows or cares about. In most cases if you want to do debugging within that OS created illusion (aka a userspace process) then you probably don't want to be using a hardware debug probe (i.e. the qemu gdb stub) at all. Instead you want to be using the debug facilities provided by your operating system. On linux this would be ptrace, probably via gdbserver. Paul
Re: [Qemu-devel] [PATCH v3 6/6] qemu_calculate_timeout: increase minimum timeout to 1h
> +#ifdef CONFIG_SLIRP > +static inline void slirp_update_timeout(uint32_t *timeout) > +{ > +*timeout = MIN(1000, *timeout); > +} > +#else > +static inline void slirp_update_timeout(uint32_t *timeout) { } > +#endif Shouldn't we be testing whether slirp is actually in use? I doubt many people go to the effort of rebuilding without SLIRP support. Paul
Re: [Qemu-devel] Memory: how to determine the max memory size of one VM?
> There's two slightly different scenarios to consider here: > > i) User specifies command line options that cannot possibly work. > => Ideally, yeah, we should just provide an understandable error message > and exit with error code. > > ii) Some tracing of mine indicates QEMU has a highly dynamic memory > usage during runtime, be it due to network layer, block layer or > whatever exactly. We do? Significant compared to the size of guest ram? That sounds like a bug. I know I've nacked patches before (particularly SCSI ones) because they allocarted memory proportional to the size of the guest block device request. Paul
Re: [Qemu-devel] [PATCH] Merge mips64 and mipsn32
> > Make MIPS N32 be a variant of mips64, rather than a new architecture in > > its own right. This matches how sparc/ppc work, and makes TARGET_MIPS64 > > the right thing to check for a 64-bit mips core. > > > > As side-effect of this is that linux-user/mipsn32 gets merged into > > linux-user/mips64. I consider this to be a feature as anything > > differences other than the syscall numbers are probably bugs. >... > Note: Richard Henderson and me had been looking into code sharing among > the MIPS ABIs for signal handling in response to a half-done Octeon > mips64 patchset. > > There's an unfinished RFC of mine from December or so, feel free to pick > that up or to come up with a better idea! Yeah, I found those and have a couple of other patches I need to reconcile and push out. I haven't looked at the signal handling bits. Paul
Re: [Qemu-devel] [PATCH] fstatat size mismatch
A "linux-user: " prefix for the subject would be nice, but let's wait for other comments first. Am 09.02.2012 20:05, schrieb Paul Brook: > host_to_target_stat64 is used for both stat64 and newfstatat syscalls. > In the latter case we don't actually have a struct stat64. > The current TARGET_ABI_BITS test is wrong for some 64-bit ILP32 targets > (in particular MIPS N32). Check for TARGET_NR_newfstatat instead. > > This will all break horribly if both newfstatat and stat64 are defined, > so also add a check for that. > > Signed-off-by: Paul Brook > --- CC'ing Riku. Andreas > linux-user/syscall.c | 12 +++- > 1 files changed, 11 insertions(+), 1 deletions(-) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index ee32089..6e0999b 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -4474,6 +4474,16 @@ static inline abi_long > host_to_target_timespec(abi_ulong target_addr, > return 0; > } > > +/* The newfstatat syscall uses regular struct stat. However it never > + occurs on targets with a struct stat64. This allows us to share > + host_to_target_stat64 between newfstatat and fstatat64. */ > + > +#if defined(TARGET_NR_newfstatat) && (defined(TARGET_NR_fstatat64) \ > +|| defined(TARGET_NR_stat64) || defined(TARGET_NR_fstat64) \ > +|| defined(TARGET_NR_lstat64)) > +#error mismatched stat syscalls. > +#endif > + > #if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat) > static inline abi_long host_to_target_stat64(void *cpu_env, > abi_ulong target_addr, > @@ -4506,7 +4516,7 @@ static inline abi_long host_to_target_stat64(void > *cpu_env, > } else > #endif > { > -#if TARGET_ABI_BITS == 64 && !defined(TARGET_ALPHA) > +#if defined(TARGET_NR_newfstatat) > struct target_stat *target_st; > #else > struct target_stat64 *target_st; -- 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] Merge mips64 and mipsn32
Am 10.02.2012 12:23, schrieb Paul Brook: > Make MIPS N32 be a variant of mips64, rather than a new architecture in > its own right. This matches how sparc/ppc work, and makes TARGET_MIPS64 > the right thing to check for a 64-bit mips core. > > As side-effect of this is that linux-user/mipsn32 gets merged into > linux-user/mips64. I consider this to be a feature as anything differences > other than the syscall numbers are probably bugs. > > Signed-off-by: Paul Brook > --- > configure |3 +- > linux-user/mips64/syscall.h| 14 +- > linux-user/mips64/syscall_nr.h | 312 > +--- > linux-user/mips64/syscall_nr32.h | 311 +++ > linux-user/mips64/syscall_nr64.h | 306 +++ > linux-user/mipsn32/syscall.h | 224 -- > linux-user/mipsn32/syscall_nr.h| 311 --- > linux-user/mipsn32/target_signal.h | 29 > linux-user/mipsn32/termbits.h | 245 > linux-user/syscall_defs.h | 79 +- > 10 files changed, 636 insertions(+), 1198 deletions(-) > create mode 100644 linux-user/mips64/syscall_nr32.h > create mode 100644 linux-user/mips64/syscall_nr64.h > delete mode 100644 linux-user/mipsn32/syscall.h > delete mode 100644 linux-user/mipsn32/syscall_nr.h > delete mode 100644 linux-user/mipsn32/target_signal.h > delete mode 100644 linux-user/mipsn32/termbits.h Note: Richard Henderson and me had been looking into code sharing among the MIPS ABIs for signal handling in response to a half-done Octeon mips64 patchset. There's an unfinished RFC of mine from December or so, feel free to pick that up or to come up with a better idea! 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 v2] qom: Unify type registration
Am 09.02.2012 17:49, schrieb Peter Maydell: > On 9 February 2012 14:20, Andreas Färber wrote: >> Replace device_init() with generalized type_init(). >> >> While at it, unify naming convention: type_init([$prefix_]register_types) >> Also, type_init() is a function, so add preceding blank line where >> necessary and don't put a semicolon after the closing brace. > > Ugh, touching the whole tree again? On Anthony's request. And this is v2 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
[Qemu-devel] [PATCH] configure: Remove OpenBSD workaround for curses probe
Remove the OpenBSD workaround for the curses probe. This has not been necessary for 5 releases now. Signed-off-by: Brad Smith diff --git a/configure b/configure index 763db24..c9729f8 100755 --- a/configure +++ b/configure @@ -1900,9 +1900,6 @@ if test "$curses" != "no" ; then curses_found=no cat > $TMPC << EOF #include -#ifdef __OpenBSD__ -#define resize_term resizeterm -#endif int main(void) { const char *s = curses_version(); resize_term(0, 0); -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
[Qemu-devel] [Bug 928204] Re: build failure gentoo
Sounds like your compiler may be to blame. Can you try on a different system? Or maybe try rebuilding your compiler without any *CFLAGS set? -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/928204 Title: build failure gentoo Status in QEMU: New Bug description: gcc 4.5.3, gentoo linux ./configure --prefix=/usr --sysconfdir=/etc --disable-strip --disable-werror --disable-kvm --disable-libiscsi --enable-nptl --enable-uuid --enable-linux-user --extra-ldflags=-Wl,-z,execheap --enable-linux-aio --enable-bluez --disable-brlapi --disable-curl --disable-fdt --disable-pie --enable-vnc-jpeg --enable-curses --disable-smartcard-nss --enable-opengl --enable-vnc-png --disable-rbd --disable-vnc-sasl --enable-sdl --disable-spice --enable-vnc-tls --disable-vnc-thread --disable-vde --enable-vhost-net --disable-xen --disable-attr --disable-xfsctl --disable-darwin-user --disable-bsd-user --audio-card-list=ac97 es1370 sb16 cs4231a adlib gus hda --audio-drv-list=sdl alsa oss --target-list= i386-softmmu x86_64-softmmu alpha-softmmu arm-softmmu cris-softmmu m68k-softmmu microblaze-softmmu microblazeel-softmmu mips-softmmu mipsel-softmmu ppc-softmmu ppc64-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu sparc64-softmmu s390x-softmmu lm32-softmmu mips64-softmmu mips64el-softmmu ppcemb-softmmu xtensa-softmmu xtensaeb-softmmu i386-linux-user x86_64-linux-user alpha-linux-user arm-linux-user cris-linux-user m68k-linux-user microblaze-linux-user microblazeel-linux-user mips-linux-user mipsel-linux-user ppc-linux-user ppc64-linux-user sh4-linux-user sh4eb-linux-user sparc-linux-user sparc64-linux-user s390x-linux-user armeb-linux-user ppc64abi32-linux-user sparc32plus-linux-user unicore32-linux-user --cc=x86_64-pc-linux-gnu-gcc --host-cc=x86_64-pc-linux-gnu-gcc Install prefix/usr BIOS directory/usr/share/qemu binary directory /usr/bin library directory /usr/lib include directory /usr/include config directory /etc Manual directory /usr/share/man ELF interp prefix /usr/gnemul/qemu-%M Source path /var/tmp/portage/app-emulation/qemu-/work/qemu- C compilerx86_64-pc-linux-gnu-gcc Host C compiler x86_64-pc-linux-gnu-gcc CFLAGS-O2 -g -O2 -pipe QEMU_CFLAGS -m64 -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fstack-protector-all -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -I/usr/include/libpng15 LDFLAGS -Wl,--warn-common -m64 -g -Wl,-z,execheap -Wl,-O1 -Wl,--as-needed make make install install pythonpython smbd /usr/sbin/smbd host CPU x86_64 host big endian no target listi386-softmmu x86_64-softmmu alpha-softmmu arm-softmmu cris-softmmu m68k-softmmu microblaze-softmmu microblazeel-softmmu mips-softmmu mipsel-softmmu ppc-softmmu ppc64-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu sparc64-softmmu s390x-softmmu lm32-softmmu mips64-softmmu mips64el-softmmu ppcemb-softmmu xtensa-softmmu xtensaeb-softmmu i386-linux-user x86_64-linux-user alpha-linux-user arm-linux-user cris-linux-user m68k-linux-user microblaze-linux-user microblazeel-linux-user mips-linux-user mipsel-linux-user ppc-linux-user ppc64-linux-user sh4-linux-user sh4eb-linux-user sparc-linux-user sparc64-linux-user s390x-linux-user armeb-linux-user ppc64abi32-linux-user sparc32plus-linux-user unicore32-linux-user tcg debug enabled no Mon debug enabled no gprof enabled no sparse enabledno strip binariesno profiler no static build no -Werror enabled no SDL support yes curses supportyes curl support no mingw32 support no Audio drivers sdl alsa oss Extra audio cards ac97 es1370 sb16 cs4231a adlib gus hda Block whitelist Mixer emulation no VNC support yes VNC TLS support yes VNC SASL support no VNC JPEG support yes VNC PNG support yes VNC threadno xen support no brlapi supportno bluez supportyes Documentation yes NPTL support yes GUEST_BASEyes PIE no vde support no Linux AIO support yes ATTR/XATTR support no Install blobs yes KVM support no TCG interpreter no fdt support no preadv supportyes fdatasync yes madvise yes posix_madvise yes uuid support yes libcap-ng support no vhost-net support yes Trace backend nop Trace output file trace- spice support no rbd support no xfsctl supportno nss used no us
Re: [Qemu-devel] [RFC 0/5]: QMP: Introduce GUEST_MEDIUM_EJECT & BLOCK_MEDIUM_CHANGED
On 02/10/2012 08:39 PM, Paolo Bonzini wrote: 1. added commands blockdev-tray-open, blockdev-tray-close, blockdev-medium-insert, blockdev-medium-remove I think this slightly overengineering. eject and change work well enough, we do not need blockdev-medium-insert and blockdev-medium-remove (yet). Of course there can be a new API, just nothing user-visible. 2. added the events: BLOCK_TRAY_OPEN, BLOCK_TRAY_CLOSE, BLOCK_MEDIUM_INSERTED BLOCK_MEDIUM_REMOVED, which would be emitted when the relating command is issued (maybe the events could just be BLOCK_TRAY_CHANGED & BLOCK_MEDIUM_CHANGED) Or even just one event with two boolean arguments. Looks slightly less clean, but it has an advantage: a guest that sends "eject" can wait for an event and will know whether the eject command was really executed (tray = open, medium = none) or just an eject request was obeyed by the guest (tray = open, medium = present). Now, maybe the guest eject could also emit BLOCK_TRAY_OPEN & BLOCK_TRAY_CLOSE. Then I think this is a complete solution. Yes. Hmm... I don't know... The more I think about it, the more I like Luiz's original proposal of only signaling guest-initiated ejects. I won't hold up any other patch that works, but I cannot think of something that is as easily usable by management in a non-racy way. Paolo
[Qemu-devel] [PATCH 2/6] monitor: Introduce qemu_get_fd()
Get the file-descriptor from 'cur_mon', will be used by the QAPI converted migration command. Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- monitor.c |5 + monitor.h |1 + 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index aadbdcb..11639b1 100644 --- a/monitor.c +++ b/monitor.c @@ -2250,6 +2250,11 @@ static void do_loadvm(Monitor *mon, const QDict *qdict) } } +int qemu_get_fd(const char *fdname) +{ +return monitor_get_fd(cur_mon, fdname); +} + int monitor_get_fd(Monitor *mon, const char *fdname) { mon_fd_t *monfd; diff --git a/monitor.h b/monitor.h index b72ea07..58109af 100644 --- a/monitor.h +++ b/monitor.h @@ -56,6 +56,7 @@ int monitor_read_block_device_key(Monitor *mon, const char *device, BlockDriverCompletionFunc *completion_cb, void *opaque); +int qemu_get_fd(const char *fdname); int monitor_get_fd(Monitor *mon, const char *fdname); void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) -- 1.7.9.111.gf3fb0.dirty
[Qemu-devel] [PATCH 4/6] Error: Introduce error_copy()
Signed-off-by: Luiz Capitulino --- error.c | 12 error.h |5 + 2 files changed, 17 insertions(+), 0 deletions(-) diff --git a/error.c b/error.c index 990050f..d85e136 100644 --- a/error.c +++ b/error.c @@ -43,6 +43,18 @@ void error_set(Error **errp, const char *fmt, ...) *errp = err; } +Error *error_copy(const Error *err) +{ +Error *err_new; + +err_new = g_malloc0(sizeof(*err)); +err_new->obj = qdict_copy(err->obj); +err_new->msg = g_strdup(err->msg); +err_new->fmt = err->fmt; + +return err_new; +} + bool error_is_set(Error **errp) { return (errp && *errp); diff --git a/error.h b/error.h index 6361f40..45ff6c1 100644 --- a/error.h +++ b/error.h @@ -35,6 +35,11 @@ void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3); bool error_is_set(Error **err); /** + * Returns an exact copy of the error passed as an argument. + */ +Error *error_copy(const Error *err); + +/** * Get a human readable representation of an error object. */ const char *error_get_pretty(Error *err); -- 1.7.9.111.gf3fb0.dirty
Re: [Qemu-devel] [RFC 0/5]: QMP: Introduce GUEST_MEDIUM_EJECT & BLOCK_MEDIUM_CHANGED
On 02/10/2012 06:55 PM, Kevin Wolf wrote: Am 10.02.2012 18:04, schrieb Luiz Capitulino: This reminds me about an earlier try where I did the following, iirc: 1. added commands blockdev-tray-open, blockdev-tray-close, blockdev-medium-insert, blockdev-medium-remove I think this slightly overengineering. eject and change work well enough, we do not need blockdev-medium-insert and blockdev-medium-remove (yet). Of course there can be a new API, just nothing user-visible. 2. added the events: BLOCK_TRAY_OPEN, BLOCK_TRAY_CLOSE, BLOCK_MEDIUM_INSERTED BLOCK_MEDIUM_REMOVED, which would be emitted when the relating command is issued (maybe the events could just be BLOCK_TRAY_CHANGED & BLOCK_MEDIUM_CHANGED) Or even just one event with two boolean arguments. Looks slightly less clean, but it has an advantage: a guest that sends "eject" can wait for an event and will know whether the eject command was really executed (tray = open, medium = none) or just an eject request was obeyed by the guest (tray = open, medium = present). Now, maybe the guest eject could also emit BLOCK_TRAY_OPEN & BLOCK_TRAY_CLOSE. Then I think this is a complete solution. Yes. Looks good to me in general. I'm not sure how you're imagining to implement this, I would prefer not to emit events from the device code, but only from block.c. ... and yes. :) Another interesting point is what to do with host CD-ROM passthrough. I think the TRAY_OPEN/CLOSE part is doable (do Paolo's patches actually do that, so that we just need to add an event?). It is in the part that I haven't posted yet. We would have to fake MEDIUM_REMOVED/INSERTED immediately before a TRAY_CLOSE if the medium has changed. Not sure about this, the "medium" hasn't changed in the sense that the backend is still the same. With passthrough, eject could become a synonym of tray-open. It is very unintuitive that the device is completely disconnected by the backend. And with passthrough, as soon as the guest ejects my CD I know that I have to remove the medium before the guest reboots. In other words we can expect some kind of collaboration from the user. LOCK/UNLOCK (which you forgot in your list) is only initiated by the guest or monitor (eject -f), so there's nothing special with passthrough. Well, there are a couple of places where we unlock without calling bdrv_lock_medium, those should be fixed so that in the passthrough case we force-unlock the host CD too. Paolo
[Qemu-devel] [PATCH 6/6] qapi: Convert migrate
The migrate command is one of those commands where HMP and QMP completely mix up together. This made the conversion to the QAPI (which separates the command into QMP and HMP parts) a bit difficult. The first important change to be noticed is that this commit completes the removal of the Monitor object from migration code, started by the previous commit. Another important and tricky change is about supporting the non-detached mode. That's, if the user doesn't pass '-d' the migrate command will lock the monitor and will only release it when migration is finished. To support that in the new HMP command (hmp_migrate()), it was necessary to create a timer which runs every second and checks if the migration is still active. If it's, the timer callback will re-schedule itself to run one second in the future. If the migration has already finished, the monitor lock is relased and the user can use it normally. All these changes should be transparent to the user. Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- hmp-commands.hx |3 +- hmp.c| 51 + hmp.h|1 + migration-fd.c |2 +- migration.c | 66 ++ migration.h |3 -- qapi-schema.json | 21 + qmp-commands.hx |9 +-- savevm.c | 13 +- sysemu.h |2 +- 10 files changed, 100 insertions(+), 71 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 573b823..10d3f1b 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -792,8 +792,7 @@ ETEXI " full copy of disk\n\t\t\t -i for migration without " "shared storage with incremental copy of disk " "(base image shared between src and destination)", -.user_print = monitor_user_noop, - .mhandler.cmd_new = do_migrate, +.mhandler.cmd = hmp_migrate, }, diff --git a/hmp.c b/hmp.c index 8ff8c94..70bd574 100644 --- a/hmp.c +++ b/hmp.c @@ -14,6 +14,7 @@ */ #include "hmp.h" +#include "qemu-timer.h" #include "qmp-commands.h" static void hmp_handle_error(Monitor *mon, Error **errp) @@ -851,3 +852,53 @@ void hmp_block_job_cancel(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &error); } + +typedef struct MigrationStatus +{ +QEMUTimer *timer; +Monitor *mon; +} MigrationStatus; + +static void hmp_migrate_status_cb(void *opaque) +{ +MigrationStatus *status = opaque; +MigrationInfo *info; + +info = qmp_query_migrate(NULL); +if (!info->has_status || strcmp(info->status, "active") == 0) { +qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock) + 1000); +goto out; +} + +monitor_resume(status->mon); +qemu_del_timer(status->timer); +g_free(status); + +out: +qapi_free_MigrationInfo(info); +} + +void hmp_migrate(Monitor *mon, const QDict *qdict) +{ +int detach = qdict_get_try_bool(qdict, "detach", 0); +int blk = qdict_get_try_bool(qdict, "blk", 0); +int inc = qdict_get_try_bool(qdict, "inc", 0); +const char *uri = qdict_get_str(qdict, "uri"); +Error *err = NULL; + +qmp_migrate(uri, !!blk, blk, !!inc, inc, false, false, &err); +if (err) { +monitor_printf(mon, "migrate: %s\n", error_get_pretty(err)); +error_free(err); +return; +} + +if (!detach) { +MigrationStatus *status = g_malloc0(sizeof(*status)); +status->timer = qemu_new_timer_ms(rt_clock, hmp_migrate_status_cb, + status); +status->mon = mon; +monitor_suspend(mon); +qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock)); +} +} diff --git a/hmp.h b/hmp.h index 18eecbd..989a613 100644 --- a/hmp.h +++ b/hmp.h @@ -58,5 +58,6 @@ void hmp_block_set_io_throttle(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); +void hmp_migrate(Monitor *mon, const QDict *qdict); #endif diff --git a/migration-fd.c b/migration-fd.c index 5a068c6..99f192d 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -75,7 +75,7 @@ static int fd_close(MigrationState *s) int fd_start_outgoing_migration(MigrationState *s, const char *fdname) { -s->fd = monitor_get_fd(s->mon, fdname); +s->fd = qemu_get_fd(fdname); if (s->fd == -1) { DPRINTF("fd_migration: invalid file descriptor identifier\n"); goto err_after_get_fd; diff --git a/migration.c b/migration.c index 5c5c94c..6f148f9 100644 --- a/migration.c +++ b/migration.c @@ -158,16 +158,6 @@ MigrationInfo *qmp_query_migrate(Error **errp) /* shared migration helpers */ -static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon) -{ -if (monitor_suspend(mon) == 0) { -DPRINTF("suspending
[Qemu-devel] [PATCH 5/6] Purge migration of (almost) everything to do with monitors
The Monitor object is passed back and forth within the migration/savevm code so that it can print errors and progress to the user. However, that approach assumes a HMP monitor, being completely invalid in QMP. This commit drops almost every single usage of the Monitor object, all monitor_printf() calls have been converted into DPRINTF() ones. There are a few remaining Monitor objects, those are going to be dropped by the next commit. Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- arch_init.c |2 +- block-migration.c | 58 ++-- migration.c |8 +++--- migration.h |2 +- savevm.c | 29 - sysemu.h |9 +++ vmstate.h |3 +- 7 files changed, 50 insertions(+), 61 deletions(-) diff --git a/arch_init.c b/arch_init.c index 699bdd1..2988964 100644 --- a/arch_init.c +++ b/arch_init.c @@ -259,7 +259,7 @@ static void sort_ram_list(void) g_free(blocks); } -int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) +int ram_save_live(QEMUFile *f, int stage, void *opaque) { ram_addr_t addr; uint64_t bytes_transferred_last; diff --git a/block-migration.c b/block-migration.c index 4467468..fd2 100644 --- a/block-migration.c +++ b/block-migration.c @@ -18,7 +18,6 @@ #include "hw/hw.h" #include "qemu-queue.h" #include "qemu-timer.h" -#include "monitor.h" #include "block-migration.h" #include "migration.h" #include "blockdev.h" @@ -204,8 +203,7 @@ static void blk_mig_read_cb(void *opaque, int ret) assert(block_mig_state.submitted >= 0); } -static int mig_save_device_bulk(Monitor *mon, QEMUFile *f, -BlkMigDevState *bmds) +static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds) { int64_t total_sectors = bmds->total_sectors; int64_t cur_sector = bmds->cur_sector; @@ -272,7 +270,6 @@ static void set_dirty_tracking(int enable) static void init_blk_migration_it(void *opaque, BlockDriverState *bs) { -Monitor *mon = opaque; BlkMigDevState *bmds; int64_t sectors; @@ -295,19 +292,17 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs) block_mig_state.total_sector_sum += sectors; if (bmds->shared_base) { -monitor_printf(mon, "Start migration for %s with shared base " -"image\n", - bs->device_name); +DPRINTF("Start migration for %s with shared base image\n", +bs->device_name); } else { -monitor_printf(mon, "Start full migration for %s\n", - bs->device_name); +DPRINTF("Start full migration for %s\n", bs->device_name); } QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry); } } -static void init_blk_migration(Monitor *mon, QEMUFile *f) +static void init_blk_migration(QEMUFile *f) { block_mig_state.submitted = 0; block_mig_state.read_done = 0; @@ -318,10 +313,10 @@ static void init_blk_migration(Monitor *mon, QEMUFile *f) block_mig_state.total_time = 0; block_mig_state.reads = 0; -bdrv_iterate(init_blk_migration_it, mon); +bdrv_iterate(init_blk_migration_it, NULL); } -static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f) +static int blk_mig_save_bulked_block(QEMUFile *f) { int64_t completed_sector_sum = 0; BlkMigDevState *bmds; @@ -330,7 +325,7 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f) QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) { if (bmds->bulk_completed == 0) { -if (mig_save_device_bulk(mon, f, bmds) == 1) { +if (mig_save_device_bulk(f, bmds) == 1) { /* completed bulk section for this device */ bmds->bulk_completed = 1; } @@ -352,8 +347,7 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f) block_mig_state.prev_progress = progress; qemu_put_be64(f, (progress << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS); -monitor_printf(mon, "Completed %d %%\r", progress); -monitor_flush(mon); +DPRINTF("Completed %d %%\r", progress); } return ret; @@ -368,8 +362,8 @@ static void blk_mig_reset_dirty_cursor(void) } } -static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, - BlkMigDevState *bmds, int is_async) +static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds, + int is_async) { BlkMigBlock *blk; int64_t total_sectors = bmds->total_sectors; @@ -428,20 +422,20 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, return (bmds->cur_dirty >= bmds->total_sectors); error: -monitor_printf(mon, "Error reading sector %" PRId64 "\n", sector); +DPRI
[Qemu-devel] [PATCH 3/6] QDict: Introduce qdict_copy()
Signed-off-by: Luiz Capitulino --- check-qdict.c | 29 + qdict.c | 18 ++ qdict.h |1 + 3 files changed, 48 insertions(+), 0 deletions(-) diff --git a/check-qdict.c b/check-qdict.c index fc0d276..12c73ab 100644 --- a/check-qdict.c +++ b/check-qdict.c @@ -227,6 +227,34 @@ static void qdict_iterapi_test(void) QDECREF(tests_dict); } +static void qdict_copy_test(void) +{ +QDict *tests_dict = qdict_new(); +const QDictEntry *ent; +QDict *new; +int i; + +for (i = 0; i < 1024; i++) { +char key[32]; + +snprintf(key, sizeof(key), "key%d", i); +qdict_put(tests_dict, key, qint_from_int(i)); +} + +new = qdict_copy(tests_dict); + +g_assert(qdict_size(new) == qdict_size(tests_dict)); +for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){ +const char *key = qdict_entry_key(ent); + +g_assert(qdict_haskey(new, key) == 1); +g_assert(qdict_get_int(new, key) == qdict_get_int(tests_dict, key)); +} + +QDECREF(new); +QDECREF(tests_dict); +} + /* * Errors test-cases */ @@ -365,6 +393,7 @@ int main(int argc, char **argv) g_test_add_func("/public/del", qdict_del_test); g_test_add_func("/public/to_qdict", qobject_to_qdict_test); g_test_add_func("/public/iterapi", qdict_iterapi_test); +g_test_add_func("/public/copy", qdict_copy_test); g_test_add_func("/errors/put_exists", qdict_put_exists_test); g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test); diff --git a/qdict.c b/qdict.c index 4bf308b..dc9141f 100644 --- a/qdict.c +++ b/qdict.c @@ -401,6 +401,24 @@ const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry) } /** + * qdict_copy(): Build a new dictionary from an existing one. + */ +QDict *qdict_copy(const QDict *from) +{ +const QDictEntry *ent; +QDict *new; + +new = qdict_new(); + +for (ent = qdict_first(from); ent; ent = qdict_next(from, ent)) { +qdict_put_obj(new, qdict_entry_key(ent), qdict_entry_value(ent)); +qobject_incref(qdict_entry_value(ent)); +} + +return new; +} + +/** * qentry_destroy(): Free all the memory allocated by a QDictEntry */ static void qentry_destroy(QDictEntry *e) diff --git a/qdict.h b/qdict.h index 929d8d2..9976a18 100644 --- a/qdict.h +++ b/qdict.h @@ -36,6 +36,7 @@ typedef struct QDict { QDict *qdict_new(void); const char *qdict_entry_key(const QDictEntry *entry); QObject *qdict_entry_value(const QDictEntry *entry); +QDict *qdict_copy(const QDict *from); size_t qdict_size(const QDict *qdict); void qdict_put_obj(QDict *qdict, const char *key, QObject *value); void qdict_del(QDict *qdict, const char *key); -- 1.7.9.111.gf3fb0.dirty
[Qemu-devel] [PATCH 1/6] QError: Introduce new errors for the migration command
The new errors are QERR_MIGRATION_ACTIVE and QERR_MIGRATION_NOT_SUPPORTED, which are going to be used by the QAPI converted migration command. Signed-off-by: Luiz Capitulino --- qerror.c |8 qerror.h |6 ++ 2 files changed, 14 insertions(+), 0 deletions(-) diff --git a/qerror.c b/qerror.c index 8e6efaf..ce9aa05 100644 --- a/qerror.c +++ b/qerror.c @@ -193,6 +193,14 @@ static const QErrorStringTable qerror_table[] = { .desc = "Using KVM without %(capability), %(feature) unavailable", }, { +.error_fmt = QERR_MIGRATION_ACTIVE, +.desc = "There's a migration process in progress", +}, +{ +.error_fmt = QERR_MIGRATION_NOT_SUPPORTED, +.desc = "State blocked by non-migratable device '%(device)'", +}, +{ .error_fmt = QERR_MIGRATION_EXPECTED, .desc = "An incoming migration is expected before this command can be executed", }, diff --git a/qerror.h b/qerror.h index e8718bf..557d7a0 100644 --- a/qerror.h +++ b/qerror.h @@ -165,6 +165,12 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_KVM_MISSING_CAP \ "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }" +#define QERR_MIGRATION_ACTIVE \ +"{ 'class': 'MigrationActive', 'data': {} }" + +#define QERR_MIGRATION_NOT_SUPPORTED \ +"{ 'class': 'MigrationNotSupported', 'data': {'device': %s} }" + #define QERR_MIGRATION_EXPECTED \ "{ 'class': 'MigrationExpected', 'data': {} }" -- 1.7.9.111.gf3fb0.dirty
[Qemu-devel] [PATCH 0/6] qapi: Convert migrate
This is a rebase of Anthony's conversion, from his glib branch; and this is also the beginning of the conversion of complex commands to the qapi. There are two important changes that should be observed: 1. patch 5/6 purges the 'mon' object from migration code. One of the consequences is that we lose the ability to print progress status to the HMP user (esp. in block migration) 2. The HMP hmp_migrate() command is a bit tricky when in non-detached mode: we lock the monitor and poll for the migration status from a timer handler. This obviously assumes that migration will end at some point Besides, this is missing testing with libvirt. I plan to do it shortly, but wanted to get some review in parallel. arch_init.c |2 +- block-migration.c | 58 ++--- check-qdict.c | 29 error.c | 12 error.h |5 +++ hmp-commands.hx |3 +- hmp.c | 51 hmp.h |1 + migration-fd.c|2 +- migration.c | 74 +++-- migration.h |5 +--- monitor.c |5 +++ monitor.h |1 + qapi-schema.json | 21 +++ qdict.c | 18 + qdict.h |1 + qerror.c |8 + qerror.h |6 qmp-commands.hx |9 +- savevm.c | 42 ++--- sysemu.h | 11 +++ vmstate.h |3 +- 22 files changed, 235 insertions(+), 132 deletions(-)
[Qemu-devel] [PATCH v2 1/8] kvm: Set cpu_single_env only once
As we have thread-local cpu_single_env now and KVM uses exactly one thread per VCPU, we can drop the cpu_single_env updates from the loop and initialize this variable only once during setup. Signed-off-by: Jan Kiszka --- cpus.c|1 + kvm-all.c |5 - 2 files changed, 1 insertions(+), 5 deletions(-) diff --git a/cpus.c b/cpus.c index f45a438..d0c8340 100644 --- a/cpus.c +++ b/cpus.c @@ -714,6 +714,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) qemu_mutex_lock(&qemu_global_mutex); qemu_thread_get_self(env->thread); env->thread_id = qemu_get_thread_id(); +cpu_single_env = env; r = kvm_init_vcpu(env); if (r < 0) { diff --git a/kvm-all.c b/kvm-all.c index c4babda..e2cbc03 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1118,8 +1118,6 @@ int kvm_cpu_exec(CPUState *env) return EXCP_HLT; } -cpu_single_env = env; - do { if (env->kvm_vcpu_dirty) { kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE); @@ -1136,13 +1134,11 @@ int kvm_cpu_exec(CPUState *env) */ qemu_cpu_kick_self(); } -cpu_single_env = NULL; qemu_mutex_unlock_iothread(); run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0); qemu_mutex_lock_iothread(); -cpu_single_env = env; kvm_arch_post_run(env, run); kvm_flush_coalesced_mmio_buffer(); @@ -1206,7 +1202,6 @@ int kvm_cpu_exec(CPUState *env) } env->exit_request = 0; -cpu_single_env = NULL; return ret; } -- 1.7.3.4
[Qemu-devel] [PATCH v2 2/8] Allow to use pause_all_vcpus from VCPU context
In order to perform critical manipulations on the VM state in the context of a VCPU, specifically code patching, stopping and resuming of all VCPUs may be necessary. resume_all_vcpus is already compatible, now enable pause_all_vcpus for this use case by stopping the calling context before starting to wait for the whole gang. CC: Paolo Bonzini Signed-off-by: Jan Kiszka --- cpus.c | 12 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/cpus.c b/cpus.c index d0c8340..5adfc6b 100644 --- a/cpus.c +++ b/cpus.c @@ -870,6 +870,18 @@ void pause_all_vcpus(void) penv = (CPUState *)penv->next_cpu; } +if (!qemu_thread_is_self(&io_thread)) { +cpu_stop_current(); +if (!kvm_enabled()) { +while (penv) { +penv->stop = 0; +penv->stopped = 1; +penv = (CPUState *)penv->next_cpu; +} +return; +} +} + while (!all_vcpus_paused()) { qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex); penv = first_cpu; -- 1.7.3.4
[Qemu-devel] [PATCH v2 8/8] kvmvapic: Use optionrom helpers
Use OPTION_ROM_START/END from the common header file, add comment to init code. Signed-off-by: Jan Kiszka --- pc-bios/optionrom/kvmvapic.S | 18 -- 1 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pc-bios/optionrom/kvmvapic.S b/pc-bios/optionrom/kvmvapic.S index 856c1e5..aa17a40 100644 --- a/pc-bios/optionrom/kvmvapic.S +++ b/pc-bios/optionrom/kvmvapic.S @@ -9,12 +9,10 @@ # option) any later version. See the COPYING file in the top-level directory. # - .text 0 - .code16 -.global _start -_start: - .short 0xaa55 - .byte (_end - _start) / 512 +#include "optionrom.h" + +OPTION_ROM_START + # clear vapic area: firmware load using rep insb may cause # stale tpr/isr/irr data to corrupt the vapic area. push %es @@ -26,8 +24,11 @@ _start: cld rep stosw pop %es + + # announce presence to the hypervisor mov $vapic_base, %ax out %ax, $0x7e + lret .code32 @@ -331,7 +332,4 @@ up_set_tpr_poll_irq: vapic: . = . + vapic_size -.byte 0 # reserve space for signature -.align 512, 0 - -_end: +OPTION_ROM_END -- 1.7.3.4
[Qemu-devel] [PATCH v2 3/8] target-i386: Add infrastructure for reporting TPR MMIO accesses
This will allow the APIC core to file a TPR access report. Depending on the accelerator and kernel irqchip mode, it will either be delivered right away or queued for later reporting. In TCG mode, we can restart the triggering instruction and can therefore forward the event directly. KVM does not allows us to restart, so we postpone the delivery of events recording in the user space APIC until the current instruction is completed. Note that KVM without in-kernel irqchip will report the address after the instruction that triggered a write access. In contrast, read accesses will return the precise information. Signed-off-by: Jan Kiszka --- cpu-all.h|3 ++- hw/apic.h|2 ++ hw/apic_common.c |4 target-i386/cpu.h|9 + target-i386/helper.c | 19 +++ target-i386/kvm.c| 24 ++-- 6 files changed, 58 insertions(+), 3 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index e2c3c49..80e6d42 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -375,8 +375,9 @@ DECLARE_TLS(CPUState *,cpu_single_env); #define CPU_INTERRUPT_TGT_INT_0 0x0100 #define CPU_INTERRUPT_TGT_INT_1 0x0400 #define CPU_INTERRUPT_TGT_INT_2 0x0800 +#define CPU_INTERRUPT_TGT_INT_3 0x2000 -/* First unused bit: 0x2000. */ +/* First unused bit: 0x4000. */ /* The set of all bits that should be masked when single-stepping. */ #define CPU_INTERRUPT_SSTEP_MASK \ diff --git a/hw/apic.h b/hw/apic.h index a62d83b..45598bd 100644 --- a/hw/apic.h +++ b/hw/apic.h @@ -18,6 +18,8 @@ void cpu_set_apic_tpr(DeviceState *s, uint8_t val); uint8_t cpu_get_apic_tpr(DeviceState *s); void apic_init_reset(DeviceState *s); void apic_sipi(DeviceState *s); +void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, + int access); /* pc.c */ int cpu_is_bsp(CPUState *env); diff --git a/hw/apic_common.c b/hw/apic_common.c index 8373d79..588531b 100644 --- a/hw/apic_common.c +++ b/hw/apic_common.c @@ -68,6 +68,10 @@ uint8_t cpu_get_apic_tpr(DeviceState *d) return s ? s->tpr >> 4 : 0; } +void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, int access) +{ +} + void apic_report_irq_delivered(int delivered) { apic_irq_delivered += delivered; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 37dde79..92e9c87 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -482,6 +482,7 @@ #define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0 #define CPU_INTERRUPT_INIT CPU_INTERRUPT_TGT_INT_1 #define CPU_INTERRUPT_SIPI CPU_INTERRUPT_TGT_INT_2 +#define CPU_INTERRUPT_TPR CPU_INTERRUPT_TGT_INT_3 enum { @@ -772,6 +773,9 @@ typedef struct CPUX86State { XMMReg ymmh_regs[CPU_NB_REGS]; uint64_t xcr0; + +target_ulong tpr_access_ip; +int tpr_access_type; } CPUX86State; CPUX86State *cpu_x86_init(const char *cpu_model); @@ -1064,4 +1068,9 @@ void svm_check_intercept(CPUState *env1, uint32_t type); uint32_t cpu_cc_compute_all(CPUState *env1, int op); +#define TPR_ACCESS_READ 0 +#define TPR_ACCESS_WRITE1 + +void cpu_report_tpr_access(CPUState *env, int access); + #endif /* CPU_I386_H */ diff --git a/target-i386/helper.c b/target-i386/helper.c index 2586aff..eca20cd 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1189,6 +1189,25 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank, } } } + +void cpu_report_tpr_access(CPUState *env, int access) +{ +TranslationBlock *tb; + +if (kvm_enabled()) { +cpu_synchronize_state(env); + +env->tpr_access_ip = env->eip; +env->tpr_access_type = access; + +cpu_interrupt(env, CPU_INTERRUPT_TPR); +} else { +tb = tb_find_pc(env->mem_io_pc); +cpu_restore_state(tb, env, env->mem_io_pc); + +apic_handle_tpr_access_report(env->apic_state, env->eip, access); +} +} #endif /* !CONFIG_USER_ONLY */ static void mce_init(CPUX86State *cenv) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 981192d..fa77f9d 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1635,8 +1635,10 @@ void kvm_arch_pre_run(CPUState *env, struct kvm_run *run) } if (!kvm_irqchip_in_kernel()) { -/* Force the VCPU out of its inner loop to process the INIT request */ -if (env->interrupt_request & CPU_INTERRUPT_INIT) { +/* Force the VCPU out of its inner loop to process any INIT requests + * or pending TPR access reports. */ +if (env->interrupt_request & +(CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) { env->exit_request = 1; } @@ -1730,6 +1732,11 @@ int kvm_arch_process_async_events(CPUState *env) kvm_cpu_synchronize_state(env); do_cpu_sipi(env); } +if (env->interrupt_request & CPU_INTERRUPT_TPR) { +env->interrupt_request &= ~CPU_INTERRUPT_TPR; +apic_handle_tpr_access_report(env->apic_state, env->tpr_acces
[Qemu-devel] [PATCH v2 5/8] kvmvapic: Introduce TPR access optimization for Windows guests
This enables acceleration for MMIO-based TPR registers accesses of 32-bit Windows guest systems. It is mostly useful with KVM enabled, either on older Intel CPUs (without flexpriority feature, can also be manually disabled for testing) or any current AMD processor. The approach introduced here is derived from the original version of qemu-kvm. It was refactored, documented, and extended by support for user space APIC emulation, both with and without KVM acceleration. The VMState format was kept compatible, so was the ABI to the option ROM that implements the guest-side para-virtualized driver service. This enables seamless migration from qemu-kvm to upstream or, one day, between KVM and TCG mode. The basic concept goes like this: - VAPIC PV interface consisting of I/O port 0x7e and (for KVM in-kernel irqchip) a vmcall hypercall is registered - VAPIC option ROM is loaded into guest - option ROM activates TPR MMIO access reporting via port 0x7e - TPR accesses are trapped and patched in the guest to call into option ROM instead, VAPIC support is enabled - option ROM TPR helpers track state in memory and invoke hypercall to poll for pending IRQs if required Signed-off-by: Jan Kiszka --- Makefile.target|3 +- hw/apic.c | 126 - hw/apic_common.c | 64 +- hw/apic_internal.h | 27 ++ hw/kvm/apic.c | 32 +++ hw/kvmvapic.c | 774 6 files changed, 1012 insertions(+), 14 deletions(-) create mode 100644 hw/kvmvapic.c diff --git a/Makefile.target b/Makefile.target index 68481a3..ec7eff8 100644 --- a/Makefile.target +++ b/Makefile.target @@ -230,7 +230,8 @@ obj-y += device-hotplug.o # Hardware support obj-i386-y += mc146818rtc.o pc.o -obj-i386-y += sga.o apic_common.o apic.o ioapic_common.o ioapic.o piix_pci.o +obj-i386-y += apic_common.o apic.o kvmvapic.o +obj-i386-y += sga.o ioapic_common.o ioapic.o piix_pci.o obj-i386-y += vmport.o obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o obj-i386-y += debugcon.o multiboot.o diff --git a/hw/apic.c b/hw/apic.c index 086c544..2ebf3ca 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -35,6 +35,10 @@ #define MSI_ADDR_DEST_ID_SHIFT 12 #defineMSI_ADDR_DEST_ID_MASK 0x000 +#define SYNC_FROM_VAPIC 0x1 +#define SYNC_TO_VAPIC 0x2 +#define SYNC_ISR_IRR_TO_VAPIC 0x4 + static APICCommonState *local_apics[MAX_APICS + 1]; static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode); @@ -78,6 +82,70 @@ static inline int get_bit(uint32_t *tab, int index) return !!(tab[i] & mask); } +/* return -1 if no bit is set */ +static int get_highest_priority_int(uint32_t *tab) +{ +int i; +for (i = 7; i >= 0; i--) { +if (tab[i] != 0) { +return i * 32 + fls_bit(tab[i]); +} +} +return -1; +} + +static void apic_sync_vapic(APICCommonState *s, int sync_type) +{ +VAPICState vapic_state; +size_t length; +off_t start; +int vector; + +if (!s->vapic_paddr) { +return; +} +if (sync_type & SYNC_FROM_VAPIC) { +cpu_physical_memory_rw(s->vapic_paddr, (void *)&vapic_state, + sizeof(vapic_state), 0); +s->tpr = vapic_state.tpr; +} +if (sync_type & (SYNC_TO_VAPIC | SYNC_ISR_IRR_TO_VAPIC)) { +start = offsetof(VAPICState, isr); +length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr); + +if (sync_type & SYNC_TO_VAPIC) { +assert(qemu_cpu_is_self(s->cpu_env)); + +vapic_state.tpr = s->tpr; +vapic_state.enabled = 1; +start = 0; +length = sizeof(VAPICState); +} + +vector = get_highest_priority_int(s->isr); +if (vector < 0) { +vector = 0; +} +vapic_state.isr = vector & 0xf0; + +vapic_state.zero = 0; + +vector = get_highest_priority_int(s->irr); +if (vector < 0) { +vector = 0; +} +vapic_state.irr = vector & 0xff; + +cpu_physical_memory_write_rom(s->vapic_paddr + start, + ((void *)&vapic_state) + start, length); +} +} + +static void apic_vapic_base_update(APICCommonState *s) +{ +apic_sync_vapic(s, SYNC_TO_VAPIC); +} + static void apic_local_deliver(APICCommonState *s, int vector) { uint32_t lvt = s->lvt[vector]; @@ -239,20 +307,17 @@ static void apic_set_base(APICCommonState *s, uint64_t val) static void apic_set_tpr(APICCommonState *s, uint8_t val) { -s->tpr = (val & 0x0f) << 4; -apic_update_irq(s); +/* Updates from cr8 are ignored while the VAPIC is active */ +if (!s->vapic_paddr) { +s->tpr = val << 4; +apic_update_irq(s); +} } -/* return -1 if no bit is set */ -static int get_highest_priority_int(uint32_t *tab) +static uint8_t apic_get_tpr(APICCommonState *s) { -int i; -
[Qemu-devel] [PATCH v2 4/8] kvmvapic: Add option ROM
This imports and builds the original VAPIC option ROM of qemu-kvm. Its interaction with QEMU is described in the commit that introduces the corresponding device model. Signed-off-by: Jan Kiszka --- .gitignore |1 + Makefile |2 +- pc-bios/optionrom/Makefile |2 +- pc-bios/optionrom/kvmvapic.S | 341 ++ 4 files changed, 344 insertions(+), 2 deletions(-) create mode 100644 pc-bios/optionrom/kvmvapic.S diff --git a/.gitignore b/.gitignore index f5aab2c..d3b78c3 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ pc-bios/vgabios-pq/status pc-bios/optionrom/linuxboot.bin pc-bios/optionrom/multiboot.bin pc-bios/optionrom/multiboot.raw +pc-bios/optionrom/kvmvapic.bin .stgit-* cscope.* tags diff --git a/Makefile b/Makefile index 47acf3d..c2ef135 100644 --- a/Makefile +++ b/Makefile @@ -255,7 +255,7 @@ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \ pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \ bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ mpc8544ds.dtb \ -multiboot.bin linuxboot.bin \ +multiboot.bin linuxboot.bin kvmvapic.bin \ s390-zipl.rom \ spapr-rtas.bin slof.bin \ palcode-clipper diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index 2caf7e6..f6b4027 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -14,7 +14,7 @@ CFLAGS += -I$(SRC_PATH) CFLAGS += $(call cc-option, $(CFLAGS), -fno-stack-protector) QEMU_CFLAGS = $(CFLAGS) -build-all: multiboot.bin linuxboot.bin +build-all: multiboot.bin linuxboot.bin kvmvapic.bin # suppress auto-removal of intermediate files .SECONDARY: diff --git a/pc-bios/optionrom/kvmvapic.S b/pc-bios/optionrom/kvmvapic.S new file mode 100644 index 000..e1d8f18 --- /dev/null +++ b/pc-bios/optionrom/kvmvapic.S @@ -0,0 +1,341 @@ +# +# Local APIC acceleration for Windows XP and related guests +# +# Copyright 2011 Red Hat, Inc. and/or its affiliates +# +# Author: Avi Kivity +# +# This work is licensed under the terms of the GNU GPL, version 2, or (at your +# option) any later version. See the COPYING file in the top-level directory. +# + + .text 0 + .code16 +.global _start +_start: + .short 0xaa55 + .byte (_end - _start) / 512 + # clear vapic area: firmware load using rep insb may cause + # stale tpr/isr/irr data to corrupt the vapic area. + push %es + push %cs + pop %es + xor %ax, %ax + mov $vapic_size/2, %cx + lea vapic, %di + cld + rep stosw + pop %es + mov $vapic_base, %ax + out %ax, $0x7e + lret + + .code32 +vapic_size = 2*4096 + +.macro fixup delta=-4 +777: + .text 1 + .long 777b + \delta - vapic_base + .text 0 +.endm + +.macro reenable_vtpr + out %al, $0x7e +.endm + +.text 1 + fixup_start = . +.text 0 + +.align 16 + +vapic_base: + .ascii "kvm aPiC" + + /* relocation data */ + .long vapic_base; fixup + .long fixup_start ; fixup + .long fixup_end ; fixup + + .long vapic ; fixup + .long vapic_size +vcpu_shift: + .long 0 +real_tpr: + .long 0 + .long up_set_tpr; fixup + .long up_set_tpr_eax; fixup + .long up_get_tpr_eax; fixup + .long up_get_tpr_ecx; fixup + .long up_get_tpr_edx; fixup + .long up_get_tpr_ebx; fixup + .long 0 /* esp. won't work. */ + .long up_get_tpr_ebp; fixup + .long up_get_tpr_esi; fixup + .long up_get_tpr_edi; fixup + .long up_get_tpr_stack ; fixup + .long mp_set_tpr; fixup + .long mp_set_tpr_eax; fixup + .long mp_get_tpr_eax; fixup + .long mp_get_tpr_ecx; fixup + .long mp_get_tpr_edx; fixup + .long mp_get_tpr_ebx; fixup + .long 0 /* esp. won't work. */ + .long mp_get_tpr_ebp; fixup + .long mp_get_tpr_esi; fixup + .long mp_get_tpr_edi; fixup + .long mp_get_tpr_stack ; fixup + +.macro kvm_hypercall + .byte 0x0f, 0x01, 0xc1 +.endm + +kvm_hypercall_vapic_poll_irq = 1 + +pcr_cpu = 0x51 + +.align 64 + +mp_get_tpr_eax: + pushf + cli + reenable_vtpr + push %ecx + + fs/movzbl pcr_cpu, %eax + + mov vcpu_shift, %ecx; fixup + shl %cl, %eax + testb $1, vapic+4(%eax) ; fixup delta=-5 + jz mp_get_tpr_bad + movzbl vapic(%eax), %eax ; fixup + +mp_get_tpr_out: + pop %ecx + popf + ret + +mp_get_tpr_bad: + mov real_tpr, %eax ; fixup + mov (%eax), %eax + jmp mp_get_tpr_out + +mp_get_tpr_ebx: + mov %eax, %ebx + call mp_get_tpr_eax + xchg %eax, %ebx + ret + +mp_get_tpr_ecx: + mov %eax, %ecx + call mp_get_tpr_eax + xchg %eax, %ecx + ret + +mp_get_tpr_edx: + mov %eax, %edx + call mp_get_tpr_eax +
[Qemu-devel] [PATCH v2 6/8] kvmvapic: Simplify mp/up_set_tpr
The CH registers is only written, never read. So we can remove these operations and, in case of up_set_tpr, also the ECX push/pop. Signed-off-by: Jan Kiszka --- pc-bios/optionrom/kvmvapic.S |6 +- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/pc-bios/optionrom/kvmvapic.S b/pc-bios/optionrom/kvmvapic.S index e1d8f18..856c1e5 100644 --- a/pc-bios/optionrom/kvmvapic.S +++ b/pc-bios/optionrom/kvmvapic.S @@ -202,7 +202,6 @@ mp_isr_is_bigger: mov %bh, %bl mp_tpr_is_bigger: /* %bl = ppr */ - mov %bl, %ch /* ch = ppr */ rol $8, %ebx /* now: %bl = irr, %bh = ppr */ cmp %bh, %bl @@ -276,7 +275,6 @@ up_set_tpr_eax: up_set_tpr: pushf push %eax - push %ecx push %ebx reenable_vtpr @@ -284,7 +282,7 @@ up_set_tpr_failed: mov vapic, %eax ; fixup mov %eax, %ebx - mov 20(%esp), %bl + mov 16(%esp), %bl /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */ @@ -298,7 +296,6 @@ up_isr_is_bigger: mov %bh, %bl up_tpr_is_bigger: /* %bl = ppr */ - mov %bl, %ch /* ch = ppr */ rol $8, %ebx /* now: %bl = irr, %bh = ppr */ cmp %bh, %bl @@ -306,7 +303,6 @@ up_tpr_is_bigger: up_set_tpr_out: pop %ebx - pop %ecx pop %eax popf ret $4 -- 1.7.3.4
Re: [Qemu-devel] [PATCH] oslib: make error handling more reasonable
On 02/10/2012 07:41 AM, Daniel P. Berrange wrote: >> @@ -80,7 +80,7 @@ void *qemu_oom_check(void *ptr) >> { >> if (ptr == NULL) { >> fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); >> -abort(); >> +exit(EXIT_FAILURE); > > exit() will call any atexit()/on_exit() handlers, as well as trying > to flush I/O streams. Any of these actions may require further > memory allocations, which will likely fail, or worse cause this > code to re-enter itself if an atexit() handler calls qemu_malloc > > The only option other than abort(), is to use _Exit() which > doesn't try to run cleanup handlers. Correct, but in that case, then you need to fflush(stderr) prior to _Exit(), or else use write() rather than fprintf(), since otherwise your attempt at a nice oom error message is lost. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
[Qemu-devel] [PATCH v2 7/8] optionsrom: Reserve space for checksum
Always add a byte before the final 512-bytes alignment to reserve the space for the ROM checksum. Signed-off-by: Jan Kiszka --- pc-bios/optionrom/optionrom.h |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h index aa783de..3daf7da 100644 --- a/pc-bios/optionrom/optionrom.h +++ b/pc-bios/optionrom/optionrom.h @@ -124,7 +124,8 @@ movw%ax, %ds; #define OPTION_ROM_END \ -.align 512, 0; \ + .byte 0; \ + .align 512, 0; \ _end: #define BOOT_ROM_END \ -- 1.7.3.4
[Qemu-devel] [PATCH v2 0/8] uq/master: TPR access optimization for Windows guests
Here is v2 of the TPR access optimization. Changes: - plug race between patching and running VCPUs accessing the same TPR instruction by stopping VCPUs during patch process - realized forward/backward check in evaluate_tpr_instruction via a table but kept patch_instruction as is (too much variations for a table-driven approach) - dropped smp_cpus == 1 special case from get_kpcr_number - fixed comment why R/W ROM alias has to be page-aligned The series is also available at git://git.kiszka.org/qemu-kvm.git queues/kvm-tpr Please review/apply. CC: Paolo Bonzini Jan Kiszka (8): kvm: Set cpu_single_env only once Allow to use pause_all_vcpus from VCPU context target-i386: Add infrastructure for reporting TPR MMIO accesses kvmvapic: Add option ROM kvmvapic: Introduce TPR access optimization for Windows guests kvmvapic: Simplify mp/up_set_tpr optionsrom: Reserve space for checksum kvmvapic: Use optionrom helpers .gitignore|1 + Makefile |2 +- Makefile.target |3 +- cpu-all.h |3 +- cpus.c| 13 + hw/apic.c | 126 ++- hw/apic.h |2 + hw/apic_common.c | 68 - hw/apic_internal.h| 27 ++ hw/kvm/apic.c | 32 ++ hw/kvmvapic.c | 774 + kvm-all.c |5 - pc-bios/optionrom/Makefile|2 +- pc-bios/optionrom/kvmvapic.S | 335 ++ pc-bios/optionrom/optionrom.h |3 +- target-i386/cpu.h |9 + target-i386/helper.c | 19 + target-i386/kvm.c | 24 ++- 18 files changed, 1423 insertions(+), 25 deletions(-) create mode 100644 hw/kvmvapic.c create mode 100644 pc-bios/optionrom/kvmvapic.S -- 1.7.3.4
Re: [Qemu-devel] [PATCH 1/1] char: Add a QemuChrHandlers struct to initialise chardev handlers
On 02/10/2012 12:08 PM, Kevin Wolf wrote: Am 10.02.2012 18:22, schrieb Anthony Liguori: On 02/10/2012 11:09 AM, Amit Shah wrote: On (Fri) 10 Feb 2012 [07:28:19], Anthony Liguori wrote: On 02/10/2012 07:19 AM, Amit Shah wrote: Instead of passing each handler in the qemu_add_handlers() function, create a struct of handlers that can be passed to the function instead. Signed-off-by: Amit Shah Why? It's a good cleanup. It's not a win in terms of code size. If you plan on introducing additional handlers, perhaps you should include this in that series where it's more appropriately justified. As a change on it's own, it doesn't seem to make a lot of sense. Makes the code much easier to look at. Can't really compare on code size, since there's zero change in the resulting binary, but the code just becomes more readable and manageable. It's not more readable IMHO. You've taken function call arguments from the place they naturally belong (in the function call) and placed them somewhere else. More importantly, this isn't a pattern we use in QEMU anywhere. The obvious next step is to replace CharDriverState.chr_can_read/read/event with a CharDriverState.ops that refers to a CharDriverHandler struct, and suddenly you have a pattern that is used a lot in QEMU (and that indeed increases readability in my opinion). I actually think that you need to change chr_can_read/read/event to take CharDriverHandler as the first argument instead of CharDriverState, then drop the handle_opaque and refactor callers appropriately. But then at this stage, we should drop NULL handlers as a disconnect mechanism and switch to a qemu_chr_fe_connect(), qemu_chr_fe_disconnect(). And that indicates that we should call it CharFrontEnd instead of CharDriverHandler. So in such a series, I don't think this patch would even survive. Regards, Anthony Liguori Kevin
Re: [Qemu-devel] [PATCH 1/1] char: Add a QemuChrHandlers struct to initialise chardev handlers
Am 10.02.2012 18:22, schrieb Anthony Liguori: > On 02/10/2012 11:09 AM, Amit Shah wrote: >> On (Fri) 10 Feb 2012 [07:28:19], Anthony Liguori wrote: >>> On 02/10/2012 07:19 AM, Amit Shah wrote: Instead of passing each handler in the qemu_add_handlers() function, create a struct of handlers that can be passed to the function instead. Signed-off-by: Amit Shah >>> >>> Why? >> >> It's a good cleanup. >> >>> It's not a win in terms of code size. If you plan on introducing >>> additional handlers, perhaps you should include this in that series >>> where it's more appropriately justified. >>> >>> As a change on it's own, it doesn't seem to make a lot of sense. >> >> Makes the code much easier to look at. Can't really compare on code >> size, since there's zero change in the resulting binary, but the code >> just becomes more readable and manageable. > > It's not more readable IMHO. You've taken function call arguments from the > place they naturally belong (in the function call) and placed them somewhere > else. > > More importantly, this isn't a pattern we use in QEMU anywhere. The obvious next step is to replace CharDriverState.chr_can_read/read/event with a CharDriverState.ops that refers to a CharDriverHandler struct, and suddenly you have a pattern that is used a lot in QEMU (and that indeed increases readability in my opinion). Kevin
Re: [Qemu-devel] [RFC 0/5]: QMP: Introduce GUEST_MEDIUM_EJECT & BLOCK_MEDIUM_CHANGED
Am 10.02.2012 18:04, schrieb Luiz Capitulino: > This reminds me about an earlier try where I did the following, iirc: > > 1. added commands blockdev-tray-open, blockdev-tray-close, > blockdev-medium-insert, > blockdev-medium-remove > 2. added the events: BLOCK_TRAY_OPEN, BLOCK_TRAY_CLOSE, BLOCK_MEDIUM_INSERTED > BLOCK_MEDIUM_REMOVED, which would be emitted when the relating command is > issued > (maybe the events could just be BLOCK_TRAY_CHANGED & BLOCK_MEDIUM_CHANGED) > 3. re-wrote eject and change in terms of the new commands, note that you get > the > events for free > > Now, maybe the guest eject could also emit BLOCK_TRAY_OPEN & > BLOCK_TRAY_CLOSE. Then > I think this is a complete solution. > > Do you guys agree? Looks good to me in general. I'm not sure how you're imagining to implement this, I would prefer not to emit events from the device code, but only from block.c. Another interesting point is what to do with host CD-ROM passthrough. I think the TRAY_OPEN/CLOSE part is doable (do Paolo's patches actually do that, so that we just need to add an event?). We would have to fake MEDIUM_REMOVED/INSERTED immediately before a TRAY_CLOSE if the medium has changed. LOCK/UNLOCK (which you forgot in your list) is only initiated by the guest or monitor (eject -f), so there's nothing special with passthrough. Kevin
Re: [Qemu-devel] [PATCH] checkpatch: Don't WARN about missing spaces in audio files
On 02/09/2012 10:02 PM, malc wrote: On Fri, 10 Feb 2012, Evgeny Voevodin wrote: On 02/09/2012 06:59 PM, Andreas F?rber wrote: Disable warnings for spaces before opening parenthesis in hw/{ac97,adlib,cs4231a,es1370,gus,sb16}.c. Why audio files are such a special thing? Because they are consistently formatted the way they are. I personally hate the QEMU Coding Style I dislike inconsistency more than any particular style. So I'm with malc here. I'd be opposed to introducing a new file that deviated from Coding Style but for the ones that already do, I see no reason to convert them all at once or make the code deviate from the style it's already using. Isn't it be better to revert a patch that introduced checkpatch.pl errors? No. Regards, Anthony Liguori
Re: [Qemu-devel] [PATCH v2] Add SPICE support to add_client monitor command
On Fri, 10 Feb 2012 12:30:21 +0100 Gerd Hoffmann wrote: > On 02/07/12 15:38, Daniel P. Berrange wrote: > > From: "Daniel P. Berrange" > > > > This is a followup to > > > > http://patchwork.ozlabs.org/patch/121004/ > > > > With the acceptance of some new APIs to libspice-server.so it > > is possible to add support for SPICE to the 'add_client' > > monitor command, bringing parity with VNC. Since SPICE can > > use TLS or plain connections, the command also gains a new > > 'tls' parameter to specify whether TLS should be attempted > > on the injected client sockets. > > > > This new feature is only enabled if building against a > > libspice-server >= 0.10.1 > > > > * qmp-commands.hx: Add 'tls' parameter & missing doc for > > 'skipauth' parameter > > * monitor.c: Wire up SPICE for 'add_client' command > > * ui/qemu-spice.h, ui/spice-core.c: Add qemu_spice_display_add_client > > API to wire up from monitor > > Spice bits are sane, the monitor bits look good to me too. > > Luiz? Can you have a look at the monitor bits? If you ack I'll go > queue it up for the next spice update. Or you can just grab it and > merge via qmp tree. Reviewed. Will need a respin. Will ack v3 and you merge it through the spice queue.
Re: [Qemu-devel] [PATCH v2] Add SPICE support to add_client monitor command
On Tue, 7 Feb 2012 14:38:40 + "Daniel P. Berrange" wrote: > From: "Daniel P. Berrange" > > This is a followup to > > http://patchwork.ozlabs.org/patch/121004/ > > With the acceptance of some new APIs to libspice-server.so it > is possible to add support for SPICE to the 'add_client' > monitor command, bringing parity with VNC. Since SPICE can > use TLS or plain connections, the command also gains a new > 'tls' parameter to specify whether TLS should be attempted > on the injected client sockets. > > This new feature is only enabled if building against a > libspice-server >= 0.10.1 > > * qmp-commands.hx: Add 'tls' parameter & missing doc for > 'skipauth' parameter > * monitor.c: Wire up SPICE for 'add_client' command > * ui/qemu-spice.h, ui/spice-core.c: Add qemu_spice_display_add_client > API to wire up from monitor > > [1] > http://cgit.freedesktop.org/spice/spice/commit/server/spice.h?id=d55b68b6b44f2499278fa860fb47ff22f5011faa > > http://cgit.freedesktop.org/spice/spice/commit/server/spice.h?id=bd07dde530d9504e1cfe7ed5837fc00c26f36716 > > Signed-off-by: Daniel P. Berrange > --- > monitor.c |9 +++-- > qmp-commands.hx |6 -- > ui/qemu-spice.h |1 + > ui/spice-core.c | 13 + > 4 files changed, 25 insertions(+), 4 deletions(-) > > diff --git a/monitor.c b/monitor.c > index aadbdcb..0d4daad 100644 > --- a/monitor.c > +++ b/monitor.c > @@ -823,13 +823,18 @@ static int add_graphics_client(Monitor *mon, const > QDict *qdict, QObject **ret_d > CharDriverState *s; > > if (strcmp(protocol, "spice") == 0) { > +int fd = monitor_get_fd(mon, fdname); > +int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); > +int tls = qdict_get_try_bool(qdict, "tls", 0); > if (!using_spice) { > /* correct one? spice isn't a device ,,, */ > qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice"); > return -1; > } > - qerror_report(QERR_ADD_CLIENT_FAILED); > - return -1; > +if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) { > +close(fd); > +} > +return 0; > #ifdef CONFIG_VNC > } else if (strcmp(protocol, "vnc") == 0) { > int fd = monitor_get_fd(mon, fdname); > diff --git a/qmp-commands.hx b/qmp-commands.hx > index b5e2ab8..82625c8 100644 > --- a/qmp-commands.hx > +++ b/qmp-commands.hx > @@ -910,8 +910,8 @@ EQMP > > { > .name = "add_client", > -.args_type = "protocol:s,fdname:s,skipauth:b?", > -.params = "protocol fdname skipauth", > +.args_type = "protocol:s,fdname:s,skipauth:b?,tls:b?", > +.params = "protocol fdname skipauth tls", > .help = "add a graphics client", > .user_print = monitor_user_noop, > .mhandler.cmd_new = add_graphics_client, > @@ -927,6 +927,8 @@ Arguments: > > - "protocol": protocol name (json-string) > - "fdname": file descriptor name (json-string) > +- "skipauth": whether to skip authentication (json-bool) > +- "tls": whether to perform TLS (json-bool) Please, mark them as optionals "(json-bool, optional)" > > Example: > > diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h > index c35b29c..8932771 100644 > --- a/ui/qemu-spice.h > +++ b/ui/qemu-spice.h > @@ -33,6 +33,7 @@ void qemu_spice_init(void); > void qemu_spice_input_init(void); > void qemu_spice_audio_init(void); > void qemu_spice_display_init(DisplayState *ds); > +int qemu_spice_display_add_client(int csock, int skipauth, int tls); You also have to add this to the #else /* CONFIG_SPICE */ clause otherwise it breaks the build when not building spice support. > int qemu_spice_add_interface(SpiceBaseInstance *sin); > int qemu_spice_set_passwd(const char *passwd, >bool fail_if_connected, bool > disconnect_if_connected); > diff --git a/ui/spice-core.c b/ui/spice-core.c > index 5639c6f..d98863e 100644 > --- a/ui/spice-core.c > +++ b/ui/spice-core.c > @@ -747,6 +747,19 @@ int qemu_spice_set_pw_expire(time_t expires) > return qemu_spice_set_ticket(false, false); > } > > +int qemu_spice_display_add_client(int csock, int skipauth, int tls) > +{ > +#if SPICE_SERVER_VERSION >= 0x000a01 > +if (tls) { > +return spice_server_add_ssl_client(spice_server, csock, skipauth); > +} else { > +return spice_server_add_client(spice_server, csock, skipauth); > +} > +#else > +return -1; > +#endif > +} > + > static void spice_register_config(void) > { > qemu_add_opts(&qemu_spice_opts);
[Qemu-devel] [PATCH 1/4] Use getaddrinfo for migration
This allows us to use ipv4/ipv6 for migration addresses. Once there, it also uses /etc/services names (it came free). Signed-off-by: Juan Quintela Signed-off-by: Amos Kong --- migration-tcp.c | 60 --- net.c | 108 +++ qemu_socket.h |3 ++ 3 files changed, 127 insertions(+), 44 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index 35a5781..644bb8f 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -81,43 +81,27 @@ static void tcp_wait_for_connect(void *opaque) int tcp_start_outgoing_migration(MigrationState *s, const char *host_port) { -struct sockaddr_in addr; int ret; - -ret = parse_host_port(&addr, host_port); -if (ret < 0) { -return ret; -} +int fd; s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; -s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0); -if (s->fd == -1) { -DPRINTF("Unable to open socket"); -return -socket_error(); -} - -socket_set_nonblock(s->fd); - -do { -ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); -if (ret == -1) { -ret = -socket_error(); -} -if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) { -qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); -return 0; -} -} while (ret == -EINTR); - -if (ret < 0) { +ret = tcp_client_start(host_port, &fd); +s->fd = fd; +if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) { +DPRINTF("connect in progress"); +qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); +} else if (ret < 0) { DPRINTF("connect failed\n"); -migrate_fd_error(s); +if (ret != -EINVAL) { +migrate_fd_error(s); +} return ret; +} else { +migrate_fd_connect(s); } -migrate_fd_connect(s); return 0; } @@ -157,28 +141,16 @@ out2: int tcp_start_incoming_migration(const char *host_port) { -struct sockaddr_in addr; -int val; +int ret; int s; DPRINTF("Attempting to start an incoming migration\n"); -if (parse_host_port(&addr, host_port) < 0) { -fprintf(stderr, "invalid host/port combination: %s\n", host_port); -return -EINVAL; -} - -s = qemu_socket(PF_INET, SOCK_STREAM, 0); -if (s == -1) { -return -socket_error(); +ret = tcp_server_start(host_port, &s); +if (ret < 0) { +return ret; } -val = 1; -setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); - -if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) { -goto err; -} if (listen(s, 1) == -1) { goto err; } diff --git a/net.c b/net.c index c34474f..f63014c 100644 --- a/net.c +++ b/net.c @@ -99,6 +99,114 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) return 0; } +static int tcp_server_bind(int fd, struct addrinfo *rp) +{ +int ret; +int val = 1; + +/* allow fast reuse */ +setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); + +ret = bind(fd, rp->ai_addr, rp->ai_addrlen); + +if (ret == -1) { +ret = -socket_error(); +} +return ret; + +} + +static int tcp_client_connect(int fd, struct addrinfo *rp) +{ +int ret; + +do { +ret = connect(fd, rp->ai_addr, rp->ai_addrlen); +if (ret == -1) { +ret = -socket_error(); +} +} while (ret == -EINTR); + +return ret; +} + + +static int tcp_start_common(const char *str, int *fd, bool server) +{ +char hostname[512]; +const char *service; +const char *name; +struct addrinfo hints; +struct addrinfo *result, *rp; +int s; +int sfd; +int ret = -EINVAL; + +*fd = -1; +service = str; +if (get_str_sep(hostname, sizeof(hostname), &service, ':') < 0) { +return -EINVAL; +} +if (server && strlen(hostname) == 0) { +name = NULL; +} else { +name = hostname; +} + +/* Obtain address(es) matching host/port */ + +memset(&hints, 0, sizeof(struct addrinfo)); +hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ +hints.ai_socktype = SOCK_STREAM; /* Datagram socket */ + +if (server) { +hints.ai_flags = AI_PASSIVE; +} + +s = getaddrinfo(name, service, &hints, &result); +if (s != 0) { +fprintf(stderr, "qemu: getaddrinfo: %s\n", gai_strerror(s)); +return -EINVAL; +} + +/* getaddrinfo() returns a list of address structures. + Try each address until we successfully bind/connect). + If socket(2) (or bind/connect(2)) fails, we (close the socket + and) try the next address. */ + +for (rp = result; rp != NULL; rp = rp->ai_next) { +sfd = qemu_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); +
Re: [Qemu-devel] [PATCH 1/1] char: Add a QemuChrHandlers struct to initialise chardev handlers
On 02/10/2012 11:09 AM, Amit Shah wrote: On (Fri) 10 Feb 2012 [07:28:19], Anthony Liguori wrote: On 02/10/2012 07:19 AM, Amit Shah wrote: Instead of passing each handler in the qemu_add_handlers() function, create a struct of handlers that can be passed to the function instead. Signed-off-by: Amit Shah Why? It's a good cleanup. It's not a win in terms of code size. If you plan on introducing additional handlers, perhaps you should include this in that series where it's more appropriately justified. As a change on it's own, it doesn't seem to make a lot of sense. Makes the code much easier to look at. Can't really compare on code size, since there's zero change in the resulting binary, but the code just becomes more readable and manageable. It's not more readable IMHO. You've taken function call arguments from the place they naturally belong (in the function call) and placed them somewhere else. More importantly, this isn't a pattern we use in QEMU anywhere. Regards, Anthony Liguori Amit
Re: [Qemu-devel] [RFC 0/5]: QMP: Introduce GUEST_MEDIUM_EJECT & BLOCK_MEDIUM_CHANGED
On Fri, 10 Feb 2012 10:27:21 +0100 Markus Armbruster wrote: > Luiz Capitulino writes: > > > On Thu, 09 Feb 2012 16:01:21 +0100 > > Markus Armbruster wrote: > > > >> Luiz Capitulino writes: > >> > >> > I've tried to implement a BLOCK_MEDIUM_EJECT event that, as we > >> > discussed[1], > >> > would be emitted by guest-initiated ejects and by the QMP/HMP eject and > >> > change > >> > commands. > >> > > >> > However, that turned to be a bit problematic, because the eject and > >> > change > >> > commands don't exactly handle tray movements: they actually insert/purge > >> > a > >> > medium from from the drive. > >> > >> The monitor commands are complex, because they do several things, and > >> the exact things they do depends on circumstances. In my experience, > >> it's best to think in basic operations until you understand the problem, > >> then bring in the complex commands. If you bring them in any earlier, > >> you'll get lost in detail and confused. > [...] > >> Now let's compare your proposal to my ideas. Your BLOCK_MEDIUM_CHANGED > >> appears to track my medium <-> empty. You emit it from the block > >> layer's bdrv_dev_change_media_cb(). Called to notify device models > >> whenever the block layer changes media. The "whenever it changes media" > >> part makes it a convenient choke point. > >> > >> Your GUEST_MEDIUM_EJECTED does *not* track my open <-> closed. I think > >> it's more complex than a straight open <-> closed event. Evidence: your > >> event documentation in qmp-events.txt needs an extra note to clarify > >> when exactly the event is emitted. > > > > The purpose of the note is not to clarify, but to emphasize that the event > > is about guest initiated ejects. Also, I disagree it's more complex, > > actually > > I think it's quite simple vs. emitting the eject event from the eject and > > change commands, as this can be messy because of their complicated > > semantics. > > What's complex about an event that fires when the tray moves? Isn't > that's as simple as it gets? The complexity is purely in the two > monitor commands. Adding events doesn't increase that complexity, it > merely makes it easier to observe. In principle this is completely right, but in practice I see a few problems because the change and eject commands require the event to be emitted as special cases (as those commands don't always move the tray). But note that I'm not saying this is undoable, just saying that I don't like as much as I like emitting the event only when the guest moves the tray. > I feel strongly that we shouldn't design events around monitor > commands[*]. Especially not complex, messy monitor commands that'll > have to be broken up for QMP eventually. Events should be about > noteworthy state transitions. Well, if we break eject/change into multiple commands and each command does a single state transition, then we end up doing what you're saying, except that no explicit state machine code exists (like the RunState code). > Fundamental state machines such as the one modelling tray behavior don't > change much. But triggers for their state transitions are less stable. > I expect an event that just reports a state transition to age more > gracefully than one that is also tied to triggers, such as "the guest > did it". > > >> This is just my analysis of the problem. If folks think your proposal > >> serves their needs, and Kevin is happy with it, I won't object. > > > > No feedback so far. > > > [*] I'm oversimplifying. Events are *usually* about noteworthy state > transitions. But we sometimes use the event mechanism for asynchronous > replies to synchronous monitor commands, like in your "QMP: add > balloon-get-memory-stats command" series. That's fine. >
[Qemu-devel] [PATCH 2/4] net/socket: allow ipv6 for net_socket_listen_init and socket_connect_init
Remove use of parse_host_port. More SO_SOCKADDR changes. Signed-off-by: Juan Quintela Signed-off-by: Amos Kong --- net/socket.c | 60 +++--- 1 files changed, 11 insertions(+), 49 deletions(-) diff --git a/net/socket.c b/net/socket.c index d4c2002..439a69c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -403,29 +403,13 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str) { NetSocketListenState *s; -int fd, val, ret; -struct sockaddr_in saddr; - -if (parse_host_port(&saddr, host_str) < 0) -return -1; +int fd, ret; s = g_malloc0(sizeof(NetSocketListenState)); -fd = qemu_socket(PF_INET, SOCK_STREAM, 0); -if (fd < 0) { -perror("socket"); -g_free(s); -return -1; -} -socket_set_nonblock(fd); - -/* allow fast reuse */ -val = 1; -setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); - -ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); +ret = tcp_server_start(host_str, &fd); if (ret < 0) { -perror("bind"); +fprintf(stderr, "tcp_server_start: %s\n", strerror(ret)); g_free(s); closesocket(fd); return -1; @@ -451,41 +435,19 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str) { NetSocketState *s; -int fd, connected, ret, err; +int fd, connected, ret; struct sockaddr_in saddr; -if (parse_host_port(&saddr, host_str) < 0) -return -1; - -fd = qemu_socket(PF_INET, SOCK_STREAM, 0); -if (fd < 0) { -perror("socket"); +ret = tcp_client_start(host_str, &fd); +if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) { +connected = 0; +} else if (ret < 0) { +closesocket(fd); return -1; +} else { +connected = 1; } -socket_set_nonblock(fd); -connected = 0; -for(;;) { -ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); -if (ret < 0) { -err = socket_error(); -if (err == EINTR || err == EWOULDBLOCK) { -} else if (err == EINPROGRESS) { -break; -#ifdef _WIN32 -} else if (err == WSAEALREADY || err == WSAEINVAL) { -break; -#endif -} else { -perror("connect"); -closesocket(fd); -return -1; -} -} else { -connected = 1; -break; -} -} s = net_socket_fd_init(vlan, model, name, fd, connected); if (!s) return -1;
[Qemu-devel] [PATCH 0/4] support to migrate with IPv6 address
Those four patches make migration of IPv6 address work. Use getaddrinfo() to socket addresses infomation. --- Amos Kong (4): Use getaddrinfo for migration net/socket: allow ipv6 for net_socket_listen_init and socket_connect_init net: split hostname and service by last colon net: support to include ipv6 address by brackets migration-tcp.c | 60 net.c | 116 +++ net/socket.c| 60 +--- qemu_socket.h |3 + 4 files changed, 145 insertions(+), 94 deletions(-) -- Amos Kong
Re: [Qemu-devel] [PATCH 6/6] qmp: add balloon-get-memory-stats & event
On Thu, 9 Feb 2012 13:26:40 -0600 Adam Litke wrote: > On Wed, Feb 08, 2012 at 06:30:40PM -0200, Luiz Capitulino wrote: > > This commit adds a QMP API for the guest provided memory statistics > > (long disabled by commit 07b0403dfc2b2ac179ae5b48105096cc2d03375a). > > > > The approach taken by the original commit > > (625a5befc2e3200b396594f002218d235e375da5) was to extend the > > query-balloon command. It introduced a severe bug though: query-balloon > > would hang if the guest didn't respond. > > > > The approach taken by this commit is asynchronous and thus avoids > > any QMP hangs. > > > > First, a client has to issue the balloon-get-memory-stats command. > > That command gets the process started by only sending a request to > > the guest, it doesn't block. When the memory stats are made available > > by the guest, they are returned to the client as an QMP event. > > > > Signed-off-by: Luiz Capitulino > > --- > > QMP/qmp-events.txt | 36 > > balloon.c | 30 +++- > > balloon.h |4 ++- > > hw/virtio-balloon.c | 76 > > ++- > > monitor.c |2 + > > monitor.h |1 + > > qapi-schema.json| 21 ++ > > qmp-commands.hx |5 +++ > > 8 files changed, 147 insertions(+), 28 deletions(-) > > > > diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt > > index 06cb404..b34b289 100644 > > --- a/QMP/qmp-events.txt > > +++ b/QMP/qmp-events.txt > > @@ -1,6 +1,42 @@ > > QEMU Monitor Protocol Events > > > > > > +BALLOON_MEMORY_STATS > > + > > + > > +Emitted when memory statistics information is made available by the guest. > > + > > +Data: > > + > > +- "memory-swapped-in": number of pages swapped in within the guest > > + (json-int, optional) > > +- "memory-swapped-out": number of pages swapped out within the guest > > + (json-int, optional) > > These are in units of pages where memory-total and memory-free are in bytes. > Maybe it makes sense to name these "memory-pages-swapped-in/out" to avoid > confusion. Yes it makes them longer, but I can imagine all of the questions > in > the future when users don't expect the units to be in pages. Seems like a good idea. > > > +- "major-page-faults": number of major page faults within the guest > > + (json-int, optional) > > +- "minor-page-faults": number of minor page faults within the guest > > + (json-int, optional) > > +- "memory-free": amount of memory (in bytes) free in the guest > > + (json-int, optional) > > +- "memory-total": amount of memory (in bytes) visible to the guest > > + (json-int, optional) > > + > > +Example: > > + > > +{ "event": "BALLOON_MEMORY_STATS", > > +"data": { "memory-free": 847941632, > > + "major-page-faults": 225, > > + "memory-swapped-in": 0, > > + "minor-page-faults": 222317, > > + "memory-total": 1045516288, > > + "memory-swapped-out": 0 }, > > +"timestamp": { "seconds": 1265044230, "microseconds": 450486 } } > > + > > +Notes: o The balloon-get-memory-stats command must be issued first, to tell > > + the guest to make the memory statistics available. > > + o The event may not contain all data members when emitted > > + > > + > > BLOCK_IO_ERROR > > -- > > > > diff --git a/balloon.c b/balloon.c > > index d340ae3..1c1a3c1 100644 > > --- a/balloon.c > > +++ b/balloon.c > > @@ -33,12 +33,15 @@ > > > > static QEMUBalloonEvent *balloon_event_fn; > > static QEMUBalloonInfo *balloon_info_fn; > > +static QEMUBalloonStats *balloon_stats_fn; > > static void *balloon_opaque; > > > > int qemu_add_balloon_handler(QEMUBalloonEvent *event_func, > > - QEMUBalloonInfo *info_func, void *opaque) > > + QEMUBalloonInfo *info_func, > > + QEMUBalloonStats *stats_func, void *opaque) > > { > > -if (balloon_event_fn || balloon_info_fn || balloon_opaque) { > > +if (balloon_event_fn || balloon_info_fn || balloon_stats_fn || > > +balloon_opaque) { > > /* We're already registered one balloon handler. How many can > > * a guest really have? > > */ > > @@ -47,6 +50,7 @@ int qemu_add_balloon_handler(QEMUBalloonEvent *event_func, > > } > > balloon_event_fn = event_func; > > balloon_info_fn = info_func; > > +balloon_stats_fn = stats_func; > > balloon_opaque = opaque; > > return 0; > > } > > @@ -58,6 +62,7 @@ void qemu_remove_balloon_handler(void *opaque) > > } > > balloon_event_fn = NULL; > > balloon_info_fn = NULL; > > +balloon_stats_fn = NULL; > > balloon_opaque = NULL; > > } > > > > @@ -80,6 +85,15 @@ static int qemu_balloon_info(BalloonInfo *info) > > return 1; > > } > > > > +static int qemu_balloon_stats(void
Re: [Qemu-devel] [PATCH 1/1] char: Add a QemuChrHandlers struct to initialise chardev handlers
On (Fri) 10 Feb 2012 [07:28:19], Anthony Liguori wrote: > On 02/10/2012 07:19 AM, Amit Shah wrote: > >Instead of passing each handler in the qemu_add_handlers() function, > >create a struct of handlers that can be passed to the function instead. > > > >Signed-off-by: Amit Shah > > Why? It's a good cleanup. > It's not a win in terms of code size. If you plan on introducing > additional handlers, perhaps you should include this in that series > where it's more appropriately justified. > > As a change on it's own, it doesn't seem to make a lot of sense. Makes the code much easier to look at. Can't really compare on code size, since there's zero change in the resulting binary, but the code just becomes more readable and manageable. Amit
Re: [Qemu-devel] [RFC 0/5]: QMP: Introduce GUEST_MEDIUM_EJECT & BLOCK_MEDIUM_CHANGED
On Fri, 10 Feb 2012 10:36:06 +0100 Markus Armbruster wrote: > Paolo Bonzini writes: > > > On 02/09/2012 04:01 PM, Markus Armbruster wrote: > >> Your GUEST_MEDIUM_EJECTED does*not* track my open<-> closed. I think > >> it's more complex than a straight open<-> closed event. Evidence: your > >> event documentation in qmp-events.txt needs an extra note to clarify > >> when exactly the event is emitted. > > > > I think I agree at this point that always generating an event for open > > <-> closed would make sense. > > > > However, we need to write a proper state machine rather than keeping > > it implicit. Events would be generated in the state machine rather > > than magically in bdrv_eject/bdrv_close. We could also take the > > occasion to move all this out of block.c which is becoming huge. So > > we would have: > > > > guest eject, tray locked: > > nothing > > > > guest eject, tray unlocked: > > BLOCK_MEDIUM_EJECT > > empty/full not affected > > > > guest eject, tray open: > > BLOCK_MEDIUM_EJECT > > empty/full not affected I think we should only emit the event when the tray actually moves, that's what mngt is interested in. > > eject, tray locked: > > eject request sent to guest > > guest responds to eject request as above > > > > eject, tray unlocked and full: > > BLOCK_MEDIUM_EJECT > > BLOCK_MEDIUM_CHANGED I don't think BLOCK_MEDIUM_EJECT should be emitted if the tray is already open. > > eject, tray unlocked and empty: > > BLOCK_MEDIUM_EJECT And closed... > > eject, tray open and full: > > BLOCK_MEDIUM_CHANGED > > > > eject, tray open and empty: > > no event Yes. > > > > change, tray locked: > > eject request sent to guest > > guest responds to eject request as above > > > > change, tray unlocked and full: > > BLOCK_MEDIUM_EJECT (to open) > > BLOCK_MEDIUM_CHANGED (perhaps twice? full -> empty -> full) > > BLOCK_MEDIUM_EJECT (to close) > > > > change, tray unlocked and empty: > > BLOCK_MEDIUM_EJECT (to open) > > BLOCK_MEDIUM_CHANGED > > BLOCK_MEDIUM_EJECT (to close) > > > > change, tray open and full: > > BLOCK_MEDIUM_CHANGED (perhaps twice?) > > BLOCK_MEDIUM_EJECT (to close) > > > > change, tray open and empty: > > BLOCK_MEDIUM_CHANGED > > BLOCK_MEDIUM_EJECT (to close) > > > > Luiz, can you try making a proof of concept of this state machine? > > > > Events then would hopefully come natural. > > Making the tray state machine explicit may make sense. But we also need > to preserve the sane guest / host split: tray movement and locking is > guest matter, handling media in an open tray is host matter. > > Moreover, let's not think "eject" and "change". These are complex > actions that should be built from basic parts. The verbs I want used > are open, close, lock, unlock, insert, remove. > > Eject becomes something like open (if not already open) + remove (if > open and not empty). > > Change becomes something like open (if not already open) + remove (if > open and not empty) + insert (if empty) + close (if open). This reminds me about an earlier try where I did the following, iirc: 1. added commands blockdev-tray-open, blockdev-tray-close, blockdev-medium-insert, blockdev-medium-remove 2. added the events: BLOCK_TRAY_OPEN, BLOCK_TRAY_CLOSE, BLOCK_MEDIUM_INSERTED BLOCK_MEDIUM_REMOVED, which would be emitted when the relating command is issued (maybe the events could just be BLOCK_TRAY_CHANGED & BLOCK_MEDIUM_CHANGED) 3. re-wrote eject and change in terms of the new commands, note that you get the events for free Now, maybe the guest eject could also emit BLOCK_TRAY_OPEN & BLOCK_TRAY_CLOSE. Then I think this is a complete solution. Do you guys agree?
Re: [Qemu-devel] [PATCH v3 6/6] qemu_calculate_timeout: increase minimum timeout to 1h
On Fri, 10 Feb 2012, Jan Kiszka wrote: > On 2012-02-10 12:18, Paolo Bonzini wrote: > > On 02/10/2012 12:19 PM, Stefano Stabellini wrote: > >> I think you are right and the right thing to do would be blocking > >> indefinitely. > >> However if slirp doesn't support it, we could have a timeout of 1000 if > >> CONFIG_SLIRP, otherwise block indefinitely. > > > > You could add a similar hack to qemu_bh_update_timeout for > > slirp_update_timeout. > > Real solutions would be preferred, but I know that the code is hairy. In > any case, please no CONFIG_SLIRP code forks. I tried to follow your suggestions, what do you guys think about the approach of the patch below? --- main_loop_wait: block indefinitely - remove qemu_calculate_timeout; - explicitly size timeout to uint32_t; - introduce slirp_update_timeout; - pass NULL as timeout argument to select in case timeout is the maximum value; Signed-off-by: Stefano Stabellini diff --git a/async.c b/async.c index 332d511..ecdaf15 100644 --- a/async.c +++ b/async.c @@ -120,7 +120,7 @@ void qemu_bh_delete(QEMUBH *bh) bh->deleted = 1; } -void qemu_bh_update_timeout(int *timeout) +void qemu_bh_update_timeout(uint32_t *timeout) { QEMUBH *bh; diff --git a/main-loop.c b/main-loop.c index 692381c..4a105e9 100644 --- a/main-loop.c +++ b/main-loop.c @@ -366,7 +366,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) } } -static void os_host_main_loop_wait(int *timeout) +static void os_host_main_loop_wait(uint32_t *timeout) { int ret, ret2, i; PollingEntry *pe; @@ -410,7 +410,7 @@ static void os_host_main_loop_wait(int *timeout) *timeout = 0; } #else -static inline void os_host_main_loop_wait(int *timeout) +static inline void os_host_main_loop_wait(uint32_t *timeout) { } #endif @@ -419,21 +419,17 @@ int main_loop_wait(int nonblocking) { fd_set rfds, wfds, xfds; int ret, nfds; -struct timeval tv; -int timeout; +struct timeval tv, *tvarg = NULL; +uint32_t timeout = UINT32_MAX; if (nonblocking) { timeout = 0; } else { -timeout = qemu_calculate_timeout(); qemu_bh_update_timeout(&timeout); } os_host_main_loop_wait(&timeout); -tv.tv_sec = timeout / 1000; -tv.tv_usec = (timeout % 1000) * 1000; - /* poll any events */ /* XXX: separate device handlers from system ones */ nfds = -1; @@ -442,16 +438,23 @@ int main_loop_wait(int nonblocking) FD_ZERO(&xfds); #ifdef CONFIG_SLIRP +slirp_update_timeout(&timeout); slirp_select_fill(&nfds, &rfds, &wfds, &xfds); #endif qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds); glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv); +if (timeout < UINT32_MAX) { +tvarg = &tv; +tv.tv_sec = timeout / 1000; +tv.tv_usec = (timeout % 1000) * 1000; +} + if (timeout > 0) { qemu_mutex_unlock_iothread(); } -ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); +ret = select(nfds + 1, &rfds, &wfds, &xfds, tvarg); if (timeout > 0) { qemu_mutex_lock_iothread(); diff --git a/main-loop.h b/main-loop.h index f971013..22c0dc9 100644 --- a/main-loop.h +++ b/main-loop.h @@ -352,6 +352,6 @@ void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc void qemu_bh_schedule_idle(QEMUBH *bh); int qemu_bh_poll(void); -void qemu_bh_update_timeout(int *timeout); +void qemu_bh_update_timeout(uint32_t *timeout); #endif diff --git a/qemu-timer.c b/qemu-timer.c index de20852..3e1ce08 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -821,8 +821,3 @@ fail: return err; } -int qemu_calculate_timeout(void) -{ -return 1000; -} - diff --git a/qemu-timer.h b/qemu-timer.h index de17f3b..f1386d5 100644 --- a/qemu-timer.h +++ b/qemu-timer.h @@ -62,7 +62,6 @@ uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts); void qemu_run_all_timers(void); int qemu_alarm_pending(void); void configure_alarms(char const *opt); -int qemu_calculate_timeout(void); void init_clocks(void); int init_timer_alarm(void); diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 890fd86..6af7534 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -42,4 +42,13 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port); +#ifdef CONFIG_SLIRP +static inline void slirp_update_timeout(uint32_t *timeout) +{ +*timeout = MIN(1000, *timeout); +} +#else +static inline void slirp_update_timeout(uint32_t *timeout) { } +#endif + #endif
[Qemu-devel] virtio-blk performance regression and qemu-kvm
Hi, Recently I observed performance regression regarding virtio-blk, especially different IO bandwidths between qemu-kvm 0.14.1 and 1.0. So I want to share the benchmark results, and ask you what the reason would be. 1. Test condition - On host, ramdisk-backed block device (/dev/ram0) - qemu-kvm is configured with virtio-blk driver for /dev/ram0, which is detected as /dev/vdb inside the guest VM. - Host System: Ubuntu 11.10 / Kernel 3.2 - Guest System: Debian 6.0 / Kernel 3.0.6 - Host I/O scheduler : deadline - testing tool : fio 2. Raw performance on the host If we test I/O with fio on /dev/ram0 on the host, - Sequential read (on the host) # fio -name iops -rw=read -size=1G -iodepth 1 \ -filename /dev/ram0 -ioengine libaio -direct=1 -bs=4096 - Sequential write (on the host) # fio -name iops -rw=write -size=1G -iodepth 1 \ -filename /dev/ram0 -ioengine libaio -direct=1 -bs=4096 Result: read 1691,6 MByte/s write 898,9 MByte/s No wonder, it's extremely fast. 3. Comparison with different qemu-kvm versions Now I'm running benchmarks with both qemu-kvm 0.14.1 and 1.0. - Sequential read (Running inside guest) # fio -name iops -rw=read -size=1G -iodepth 1 \ -filename /dev/vdb -ioengine libaio -direct=1 -bs=4096 - Sequential write (Running inside guest) # fio -name iops -rw=write -size=1G -iodepth 1 \ -filename /dev/vdb -ioengine libaio -direct=1 -bs=4096 For each one, I tested 3 times to get the average. Result: seqread with qemu-kvm 0.14.1 67,0 MByte/s seqread with qemu-kvm 1.0 30,9 MByte/s seqwrite with qemu-kvm 0.14.1 65,8 MByte/s seqwrite with qemu-kvm 1.0 30,5 MByte/s So the newest stable version of qemu-kvm shows only the half of bandwidth compared to the older version 0.14.1. The question is, why is it so slower? How can we improve the performance, except for downgrading to 0.14.1? I know there have been already several discussions on this issue, for example, benchmark and trace on virtio-blk latency [1], or in-kernel accelerator "vhost-blk" [2]. I'm going to continue testing with those ones, too. But does anyone have a better idea or know about recent updates? Regards, Dongsu [1] http://www.linux-kvm.org/page/Virtio/Block/Latency [2] http://thread.gmane.org/gmane.comp.emulators.kvm.devel/76893
Re: [Qemu-devel] How to follow a child process created in the guest OS?
On Fri, Feb 10, 2012 at 08:14:41AM +, Stefan Hajnoczi wrote: > On Thu, Feb 09, 2012 at 06:33:16PM +0800, 陳韋任 wrote: > > The question is not so related to QEMU itself, but I want to give it a > > try. > > I am running a tiny OS on QEMU and debugging it with gdbstub. The tiny OS > > will > > fork process 1, 2, ... and so on. I want to follow the child process, but > > the > > GDB command `set follow-fork-mode child` doesn't work. This seems to be a > > bug > > or missing feature in GDB remote protocol. [1] > > > > Is there a way to do what I'm trying to do? Thanks! > > I'm confused. If you are running a system emulator with a guest OS > inside then GDB's process-level features are not available. The QEMU > gdbstub gives you access at the system-level. If you want to debug > guest processes, run gdb inside the guest. Hope the code snip below can clarify what I am trying to do. - Tiny OS code - void main(void) /* This really IS void, no error here. */ { /* initialize enviroment */ sti(); move_to_user_mode(); if (!fork()) {/* we count on this going ok */ init(); // task 1 } for(;;) pause(); // task 0 } I am running this tiny OS on QEMU then using GDB to connect it. I want to follow task 1 after the forking, but it seems that GDB stick with task 0 and cannot follow task 1 even I do `set follow-fork-mode child`. Thanks! 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 4/4] net: support to include ipv6 address by brackets
That method of representing an IPv6 address with a port is discouraged because of its ambiguity. Referencing to RFC5952, the recommended format is: [2312::8274]:5200 test status: Successed listen side: qemu-kvm -incoming tcp:[2312::8274]:5200 client side: qemu-kvm ... (qemu) migrate -d tcp:[2312::8274]:5200 Signed-off-by: Amos Kong --- net.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/net.c b/net.c index 9e1ef9e..cccdb6b 100644 --- a/net.c +++ b/net.c @@ -88,6 +88,12 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) if (!p1) return -1; len = p1 - p; +/* remove brackets which includes hostname */ +if (*p == '[' && *(p1-1) == ']') { +p += 1; +len -= 2; +} + p1++; if (buf_size > 0) { if (len > buf_size - 1)
[Qemu-devel] [PATCH 3/4] net: split hostname and service by last colon
IPv6 address contains colons, parse will be wrong. [2312::8274]:5200 Signed-off-by: Amos Kong --- net.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net.c b/net.c index f63014c..9e1ef9e 100644 --- a/net.c +++ b/net.c @@ -84,7 +84,7 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) const char *p, *p1; int len; p = *pp; -p1 = strchr(p, sep); +p1 = strrchr(p, sep); if (!p1) return -1; len = p1 - p;
Re: [Qemu-devel] Memory: how to determine the max memory size of one VM?
Am 10.02.2012 11:36, schrieb Stefan Hajnoczi: > On Fri, Feb 10, 2012 at 10:35 AM, Stefan Hajnoczi wrote: >> On Fri, Feb 10, 2012 at 9:47 AM, Zhi Yong Wu wrote: >>> Today i tried to create one VM with the option "-m 4000", and found it >>> failed with the following errors: >>> >>> Failed to allocate 4194304000 B: Cannot allocate memory >>> Aborted (core dumped) >> >> Did you run on a 32-bit host? > > BTW we shouldn't abort(3). There's two slightly different scenarios to consider here: i) User specifies command line options that cannot possibly work. => Ideally, yeah, we should just provide an understandable error message and exit with error code. ii) Some tracing of mine indicates QEMU has a highly dynamic memory usage during runtime, be it due to network layer, block layer or whatever exactly. Any memory allocation of those may fail due to soft or hard limits, including pthread_create. => We should not abort because the previously running guest is gone and it's data may be incomplete or corrupted. Not to mention that libvirt shows an odd error message. Problem is that there is no distinction at this point, so if we remove the abort(3) for use case i) we loose it for debugging ii) as well. What would be cool is finding some way to avoid dynamic allocations after guest startup (i.e., preallocated memory pools) and dealing with running out of space there in a non-fatal way. 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] Memory: how to determine the max memory size of one VM?
Am 10.02.2012 12:23, schrieb Zhi Yong Wu: > On Fri, Feb 10, 2012 at 7:10 PM, Stefan Hajnoczi wrote: >> On Fri, Feb 10, 2012 at 11:00 AM, Zhi Yong Wu wrote: >>> On Fri, Feb 10, 2012 at 6:35 PM, Stefan Hajnoczi wrote: On Fri, Feb 10, 2012 at 9:47 AM, Zhi Yong Wu wrote: > Today i tried to create one VM with the option "-m 4000", and found it > failed with the following errors: > > Failed to allocate 4194304000 B: Cannot allocate memory > Aborted (core dumped) Did you run on a 32-bit host? >>> No, it is one x86_64 host. >> >> That is weird. Have you tried strace(1) to find out which system call >> is failing and why? > It seems that it failed to call mmap(). ENOMEM /etc/sysconfig/ulimit on SUSE has a default SOFTVIRTUALLIMIT value of "80", i.e. 80% of the available physical + swap memory can be allocated by one process. For our SLES use cases we applied a simple patch to raise this limit via RLIMIT_AS (so that, e.g., a 24 GB RAM host can create VMs > -m 20G). ulimit -Sv can change this value, too. For upstream QEMU we felt setting proper limits is the responsibility of a management tool. 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] oslib: make error handling more reasonable
Am 10.02.2012 16:13, schrieb Zhi Yong Wu: On Fri, Feb 10, 2012 at 10:41 PM, Daniel P. Berrange wrote: On Fri, Feb 10, 2012 at 10:34:13PM +0800, Zhi Yong Wu wrote: From: Zhi Yong Wu Signed-off-by: Zhi Yong Wu --- oslib-posix.c |4 ++-- oslib-win32.c |4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/oslib-posix.c b/oslib-posix.c index b6a3c7f..f978d56 100644 --- a/oslib-posix.c +++ b/oslib-posix.c @@ -80,7 +80,7 @@ void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); -abort(); +exit(EXIT_FAILURE); exit() will call any atexit()/on_exit() handlers, as well as trying to flush I/O streams. Any of these actions may require further memory allocations, which will likely fail, or worse cause this code to re-enter itself if an atexit() handler calls qemu_malloc Nice, very reasonable. The only option other than abort(), is to use _Exit() which doesn't try to run cleanup handlers. I will try to send out v2 Could you please explain why calling exit, _Exit or _exit is more reasonable than calling abort? abort can create core dumps or start a debugger which is useful for me and maybe other developers, too.
Re: [Qemu-devel] [PATCH 3/5] raw-posix: keep complete control of door locking if possible
On 02/10/2012 03:56 PM, Markus Armbruster wrote: Paolo Bonzini writes: On 02/10/2012 01:49 PM, Markus Armbruster wrote: With manage_door off: * cdrom_lock_medium() does nothing. Thus, guest OS operating the virtual door lock does not affect the physical door. * cdrom_eject() does nothing. Thus, guest OS moving the virtual tray does not affect the physical tray. That's because manage_door off means "we couldn't get O_EXCL to work". udev will affect the physical tray and we cannot really compete with it. Understood. I'm just describing behavior to make sure I understand your patch, not criticizing it. Sure, just expanding on the rationale. For virtio-scsi+scsi-block, we definitely want O_EXCL to remove the device from udev and the in-kernel poller. That's because GESN reports events only once, and we do not want the host and guest to race on receiving events. But in order to open with O_EXCL we need to unmount (GNOME3 doesn't have an unmount menu item anymore, which is why I did it myself in patch 5/5). Program A unmounting a filesystem that some unknown program B mounted for its own unknown reasons doesn't feel right to me. Even when program B sucks as badly as Gnome appears to do. Especially when program A does it automatically, silently, and without a way to switch it off. Well, first it's a CD-ROM, so it won't cause data loss. CD burning programs use O_EXCL so QEMU will not stomp on anyone's feet while the CD is being written to. Second, it's the user who asked to use the CD-ROM in a guest. It makes sense to imply he does not want to use it in the host. Third, if there are open files or such, the unmounting will fail. And in fact in most cases you won't notice the auto unmounting. Say you're installing a guest (most common case of IDE CD passthrough). The installation program will usually eject the disc before rebooting. If you put it back in after you stop the VM and QEMU has exited, ta-dah, the disc will be remounted. You've made a good case for why we really, really want managed_door on. With managed_door off, both software and humans basically run around confused. Kind of. In most cases you don't care at all about the tray (for example when installing a VM from a "real" disk). You care about the tray if the guest starts using it, for example Anaconda's infamous auto-eject after testing media. Right now sometimes it's hard to convince the guest that you actually put the CD back. But if the tray is not managed, you'll never get an auto-eject and you don't have to convince anyone about anything. Why do we even offer managed_door off then? And isn't the automatic, *silent* fallback to the rotten user experience of managed_door off a recipe for support calls? Regarding silence you have a point. On the other hand, when starting via libvirt everything will be silent. :( This is another point in favor of automatic unmounting, which will usually just work. It may make sense to fail completely if the unmounting fails, but then we need to do more effort to grab the disk (e.g. try /bin/umount if udisks fails). Paolo
[Qemu-devel] [PATCH v2] oslib: make error handling more reasonable
From: Zhi Yong Wu Signed-off-by: Zhi Yong Wu --- oslib-posix.c |4 ++-- oslib-win32.c |2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/oslib-posix.c b/oslib-posix.c index b6a3c7f..3b7cd9d 100644 --- a/oslib-posix.c +++ b/oslib-posix.c @@ -80,7 +80,7 @@ void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); -abort(); +_Exit(EXIT_FAILURE); } return ptr; } @@ -94,7 +94,7 @@ void *qemu_memalign(size_t alignment, size_t size) if (ret != 0) { fprintf(stderr, "Failed to allocate %zu B: %s\n", size, strerror(ret)); -abort(); +_Exit(EXIT_FAILURE); } #elif defined(CONFIG_BSD) ptr = qemu_oom_check(valloc(size)); diff --git a/oslib-win32.c b/oslib-win32.c index ce3021e..67b82d3 100644 --- a/oslib-win32.c +++ b/oslib-win32.c @@ -35,7 +35,7 @@ void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError()); -abort(); +_Exit(EXIT_FAILURE); } return ptr; } -- 1.7.6
Re: [Qemu-devel] [PATCH] oslib: make error handling more reasonable
On Fri, Feb 10, 2012 at 10:41 PM, Daniel P. Berrange wrote: > On Fri, Feb 10, 2012 at 10:34:13PM +0800, Zhi Yong Wu wrote: >> From: Zhi Yong Wu >> >> Signed-off-by: Zhi Yong Wu >> --- >> oslib-posix.c | 4 ++-- >> oslib-win32.c | 4 ++-- >> 2 files changed, 4 insertions(+), 4 deletions(-) >> >> diff --git a/oslib-posix.c b/oslib-posix.c >> index b6a3c7f..f978d56 100644 >> --- a/oslib-posix.c >> +++ b/oslib-posix.c >> @@ -80,7 +80,7 @@ void *qemu_oom_check(void *ptr) >> { >> if (ptr == NULL) { >> fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); >> - abort(); >> + exit(EXIT_FAILURE); > > exit() will call any atexit()/on_exit() handlers, as well as trying > to flush I/O streams. Any of these actions may require further > memory allocations, which will likely fail, or worse cause this > code to re-enter itself if an atexit() handler calls qemu_malloc Nice, very reasonable. > > The only option other than abort(), is to use _Exit() which > doesn't try to run cleanup handlers. I will try to send out v2 > > 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 :| -- Regards, Zhi Yong Wu
Re: [Qemu-devel] [PATCH 3/5] raw-posix: keep complete control of door locking if possible
Paolo Bonzini writes: > On 02/10/2012 01:49 PM, Markus Armbruster wrote: >> With manage_door off: >> >> * cdrom_lock_medium() does nothing. Thus, guest OS operating the >> virtual door lock does not affect the physical door. >> >> * cdrom_eject() does nothing. Thus, guest OS moving the virtual tray >> does not affect the physical tray. > > That's because manage_door off means "we couldn't get O_EXCL to > work". udev will affect the physical tray and we cannot really compete > with it. Understood. I'm just describing behavior to make sure I understand your patch, not criticizing it. >> Compare to before this patch: >> >> * cdrom_lock_medium() fails silently. Thus, guest OS operating the >> virtual door may or may not affect the physical door. It usually does >> unless the CD-ROM is mounted in the host. >> >> * cdrom_eject() perror()s when it fails. Thus, guest OS moving the >> virtual tray may or may not affect the physocal tray. It usually does >> unless the CD-ROM is mounted in the host, or udev got its paws on it >> (I think). >> >> With manage_door on: >> >> * cdrom_lock_medium() works exactly as before, except the common failure >> mode "CD-ROM is mounted in the host" can't happen. >> >> * cdrom_eject() works exactly as before, except the common failure mode >> "CD-ROM is mounted in the host" can't happen. >> >> Is this correct? >> >> If yes, is it what we want? > > For virtio-scsi+scsi-block, we definitely want O_EXCL to remove the > device from udev and the in-kernel poller. That's because GESN > reports events only once, and we do not want the host and guest to > race on receiving events. But in order to open with O_EXCL we need to > unmount (GNOME3 doesn't have an unmount menu item anymore, which is > why I did it myself in patch 5/5). Program A unmounting a filesystem that some unknown program B mounted for its own unknown reasons doesn't feel right to me. Even when program B sucks as badly as Gnome appears to do. Especially when program A does it automatically, silently, and without a way to switch it off. > For IDE we do not need O_EXCL in principle. However, using the > emulated passthrough CD-ROM gets confusing without O_EXCL (to the user > and to the guest, always; and sometimes, to the host udev as well). > Basically, the guest tries to lock the disk, but udev runs as root so > it can unlock it under its feet as soon as you press the button. With > O_EXCL and some extra patches (waiting for Luiz's eject event > discussion), everything kinda works; still confusing to the user, but > not to the host or VM. > > I have some prototype patches to improve the situation on IDE somehow > (still a far cry from scsi-block), but I'm waiting for Luiz's eject > event patches to reach a conclusion first. > > There is also the case of emulated passthrough SCSI CD-ROM, but I > don't care much about it. > >> Shouldn't the user be able to ask for one >> of "grab the CD-ROM exclusively, else fail", "grab it if you can", >> "don't grab it even if you could"? > > Perhaps IDE could be made to work cooperatively, but right now it > doesn't. But scsi-block should fail if it cannot manage the door > because it bypasses all the CD-ROM machinery and issues SCSI commands > directly. You've made a good case for why we really, really want managed_door on. With managed_door off, both software and humans basically run around confused. Why do we even offer managed_door off then? And isn't the automatic, *silent* fallback to the rotten user experience of managed_door off a recipe for support calls? [...]
[Qemu-devel] [PATCH v3 6/6] trace: [stderr] Port to generic event information and new control interface
Signed-off-by: Lluís Vilanova --- scripts/tracetool.py | 26 -- trace/stderr.c | 35 +++ 2 files changed, 15 insertions(+), 46 deletions(-) diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 98a8ca8..a3135b8 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -348,10 +348,10 @@ def simple_c(events): @for_backend("stderr", "h", "Stderr built-in backend") def stderr_h(events): -print '''#include -#include "trace/stderr.h" - -extern TraceEvent trace_list[];''' +print """\ +#include +#include "trace/control.h" +""" for num, event in enumerate(events): argnames = ", ".join(event.args.names()) @@ -360,31 +360,21 @@ extern TraceEvent trace_list[];''' print ''' static inline void trace_%(name)s(%(args)s) { -if (trace_list[%(event_num)s].state != 0) { +bool _state = trace_event_get_state(%(event_id)s); +if (_state) { fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s); } }''' % { 'name': event.name, 'args': event.args, -'event_num': num, +'event_id': "TRACE_" + event.name.upper(), 'fmt': event.fmt.rstrip('\n'), 'argnames': argnames } -print -print '#define NR_TRACE_EVENTS %d' % len(events) @for_backend("stderr", "c") def stderr_c(events): -print '''#include "trace.h" - -TraceEvent trace_list[] = { -''' -for event in events: -print '{.tp_name = "%(name)s", .state=0},' % { -'name': event.name -} -print -print '};' +pass ## diff --git a/trace/stderr.c b/trace/stderr.c index 0810d6f..3d5f313 100644 --- a/trace/stderr.c +++ b/trace/stderr.c @@ -4,40 +4,19 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf) { -unsigned int i; +TraceEventID i; -for (i = 0; i < NR_TRACE_EVENTS; i++) { +for (i = 0; i < trace_event_count(); i++) { +TraceEvent *ev = trace_event_id(i); stream_printf(stream, "%s [Event ID %u] : state %u\n", - trace_list[i].tp_name, i, trace_list[i].state); + trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev)); } } -bool trace_event_set_state(const char *name, bool state) +void trace_event_set_state_dynamic(TraceEvent *ev, bool state) { -unsigned int i; -unsigned int len; -bool wildcard = false; -bool matched = false; - -len = strlen(name); -if (len > 0 && name[len - 1] == '*') { -wildcard = true; -len -= 1; -} -for (i = 0; i < NR_TRACE_EVENTS; i++) { -if (wildcard) { -if (!strncmp(trace_list[i].tp_name, name, len)) { -trace_list[i].state = state; -matched = true; -} -continue; -} -if (!strcmp(trace_list[i].tp_name, name)) { -trace_list[i].state = state; -return true; -} -} -return matched; +assert(ev != NULL); +ev->dstate = state; } bool trace_backend_init(const char *events, const char *file)
Re: [Qemu-devel] [PATCH] oslib: make error handling more reasonable
On Fri, Feb 10, 2012 at 10:34:13PM +0800, Zhi Yong Wu wrote: > From: Zhi Yong Wu > > Signed-off-by: Zhi Yong Wu > --- > oslib-posix.c |4 ++-- > oslib-win32.c |4 ++-- > 2 files changed, 4 insertions(+), 4 deletions(-) > > diff --git a/oslib-posix.c b/oslib-posix.c > index b6a3c7f..f978d56 100644 > --- a/oslib-posix.c > +++ b/oslib-posix.c > @@ -80,7 +80,7 @@ void *qemu_oom_check(void *ptr) > { > if (ptr == NULL) { > fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); > -abort(); > +exit(EXIT_FAILURE); exit() will call any atexit()/on_exit() handlers, as well as trying to flush I/O streams. Any of these actions may require further memory allocations, which will likely fail, or worse cause this code to re-enter itself if an atexit() handler calls qemu_malloc The only option other than abort(), is to use _Exit() which doesn't try to run cleanup handlers. 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 :|
Re: [Qemu-devel] Memory: how to determine the max memory size of one VM?
On Fri, Feb 10, 2012 at 10:08 PM, Stefan Hajnoczi wrote: > On Fri, Feb 10, 2012 at 11:53 AM, Zhi Yong Wu wrote: >> By the way, need we still to do one clean failure exit? > > I find the abort(3) usage odd but it's not critical to change it. > Since we printed an error message I would have expected > exit(EXIT_FAILURE), not abort(3) which is usually used for strange > cases that you want to debug if hit. OK. i will send out one patch since it is on hand. thanks > > Stefan -- Regards, Zhi Yong Wu
Re: [Qemu-devel] Configure time selection of VGA and Ethernet
On 02/09/2012 06:54 PM, carlo.bra...@libero.it wrote: Hello, in your opinion, is it possible to add some #ifdef and two options to configure script for activating/deactivating the compilation of supported video and ethernet interfaces, in a similar manner it had been done with audio cards and "--audio-card-list" option? This is already supported. You need to put a configuration file in *-softmmu/config-devices.mak (after configuring) with the list of devices. However, the usability (especially the interaction with Makefiles and "git pull") is pretty bad. It is simplest to modify default-configs/*.mak and build QEMU normally. Paolo
[Qemu-devel] [PATCH] oslib: make error handling more reasonable
From: Zhi Yong Wu Signed-off-by: Zhi Yong Wu --- oslib-posix.c |4 ++-- oslib-win32.c |4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/oslib-posix.c b/oslib-posix.c index b6a3c7f..f978d56 100644 --- a/oslib-posix.c +++ b/oslib-posix.c @@ -80,7 +80,7 @@ void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); -abort(); +exit(EXIT_FAILURE); } return ptr; } @@ -94,7 +94,7 @@ void *qemu_memalign(size_t alignment, size_t size) if (ret != 0) { fprintf(stderr, "Failed to allocate %zu B: %s\n", size, strerror(ret)); -abort(); +exit(EXIT_FAILURE); } #elif defined(CONFIG_BSD) ptr = qemu_oom_check(valloc(size)); diff --git a/oslib-win32.c b/oslib-win32.c index ce3021e..af2ff93 100644 --- a/oslib-win32.c +++ b/oslib-win32.c @@ -35,7 +35,7 @@ void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError()); -abort(); +exit(EXIT_FAILURE); } return ptr; } @@ -45,7 +45,7 @@ void *qemu_memalign(size_t alignment, size_t size) void *ptr; if (!size) { -abort(); +exit(EXIT_FAILURE); } ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); trace_qemu_memalign(alignment, size, ptr); -- 1.7.6
[Qemu-devel] [PATCH v3 3/6] trace: [monitor] Use new event control interface
Signed-off-by: Lluís Vilanova --- monitor.c | 15 --- 1 files changed, 12 insertions(+), 3 deletions(-) diff --git a/monitor.c b/monitor.c index 5e099bd..010f659 100644 --- a/monitor.c +++ b/monitor.c @@ -617,10 +617,19 @@ static void do_trace_event_set_state(Monitor *mon, const QDict *qdict) { const char *tp_name = qdict_get_str(qdict, "name"); bool new_state = qdict_get_bool(qdict, "option"); -int ret = trace_event_set_state(tp_name, new_state); -if (!ret) { -monitor_printf(mon, "unknown event name \"%s\"\n", tp_name); +if (trace_event_is_pattern(tp_name)) { +TraceEvent *ev = NULL; +while ((ev = trace_event_pattern(tp_name, ev)) != NULL) { +trace_event_set_state_dynamic(ev, new_state); +} +} else { +TraceEvent *ev = trace_event_name(tp_name); +if (ev == NULL) { +monitor_printf(mon, "unknown event name \"%s\"\n", tp_name); +} else { +trace_event_set_state_dynamic(ev, new_state); +} } }
[Qemu-devel] [PATCH v3 5/6] trace: [simple] Port to generic event information and new control interface
Signed-off-by: Lluís Vilanova --- scripts/tracetool.py | 29 ++--- trace/simple.c | 33 ++--- trace/simple.h |6 +- trace/stderr.h | 11 --- 4 files changed, 17 insertions(+), 62 deletions(-) delete mode 100644 trace/stderr.h diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 724b595..98a8ca8 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -265,28 +265,18 @@ def simple_h(events): 'name': event.name, 'args': event.args } -print -print '#define NR_TRACE_EVENTS %d' % len(events) -print 'extern TraceEvent trace_list[NR_TRACE_EVENTS];' @for_backend("simple", "c") def simple_c(events): rec_off = 0 -print '#include "trace.h"' -print '#include "trace/simple.h"' -print -print 'TraceEvent trace_list[] = {' -print -for event in events: -print '{.tp_name = "%(name)s", .state=0},' % { -'name': event.name -} -print -print '};' -print +print """\ +#include "trace.h" +#include "trace/control.h" +#include "trace/simple.h" +""" -for num, event in enumerate(events): -sizes = [] +for event in events: +sizes = ["0"] for type_, name in event.args: if type_is_string(type_): sizes.append("4 + strlen(%s)" % name) @@ -301,7 +291,8 @@ def simple_c(events): uint64_t pvar64 __attribute__ ((unused)); uint32_t slen __attribute__ ((unused)); -if (!trace_list[%(event_id)s].state) { +bool _state = trace_event_get_state(%(event_id)s); +if (!_state) { return; } @@ -310,7 +301,7 @@ def simple_c(events): ''' % { 'name': event.name, 'args': event.args, -'event_id': num, +'event_id': "TRACE_" + event.name.upper(), 'sizestr' : sizestr, } diff --git a/trace/simple.c b/trace/simple.c index f5aa3bd..3c99923 100644 --- a/trace/simple.c +++ b/trace/simple.c @@ -263,38 +263,17 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf) { unsigned int i; -for (i = 0; i < NR_TRACE_EVENTS; i++) { +for (i = 0; i < trace_event_count(); i++) { +TraceEvent *ev = trace_event_id(i); stream_printf(stream, "%s [Event ID %u] : state %u\n", - trace_list[i].tp_name, i, trace_list[i].state); + trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev)); } } -bool trace_event_set_state(const char *name, bool state) +void trace_event_set_state_dynamic(TraceEvent *ev, bool state) { -unsigned int i; -unsigned int len; -bool wildcard = false; -bool matched = false; - -len = strlen(name); -if (len > 0 && name[len - 1] == '*') { -wildcard = true; -len -= 1; -} -for (i = 0; i < NR_TRACE_EVENTS; i++) { -if (wildcard) { -if (!strncmp(trace_list[i].tp_name, name, len)) { -trace_list[i].state = state; -matched = true; -} -continue; -} -if (!strcmp(trace_list[i].tp_name, name)) { -trace_list[i].state = state; -return true; -} -} -return matched; +assert(ev != NULL); +ev->dstate = state; } /* Helper function to create a thread with signals blocked. Use glib's diff --git a/trace/simple.h b/trace/simple.h index 671cbeb..6850ac5 100644 --- a/trace/simple.h +++ b/trace/simple.h @@ -15,12 +15,8 @@ #include #include -typedef uint64_t TraceEventID; +#include "trace-events.h" -typedef struct { -const char *tp_name; -bool state; -} TraceEvent; void st_print_trace(FILE *stream, fprintf_function stream_printf); void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf); diff --git a/trace/stderr.h b/trace/stderr.h deleted file mode 100644 index d575b61..000 --- a/trace/stderr.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef TRACE_STDERR_H -#define TRACE_STDERR_H - -typedef uint64_t TraceEventID; - -typedef struct { -const char *tp_name; -bool state; -} TraceEvent; - -#endif /* ! TRACE_STDERR_H */
[Qemu-devel] [PATCH v3 4/6] trace: [default] Use new event control interface
Signed-off-by: Lluís Vilanova --- trace/default.c |3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/trace/default.c b/trace/default.c index c9b27a2..12db18d 100644 --- a/trace/default.c +++ b/trace/default.c @@ -18,11 +18,10 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf) "operation not supported with the current backend\n"); } -bool trace_event_set_state(const char *name, bool state) +void trace_event_set_state_dynamic(TraceEvent *ev, bool state) { fprintf(stderr, "warning: " "cannot set the state of a trace event with the current backend\n"); -return false; } bool trace_backend_init(const char *events, const char *file)
[Qemu-devel] [PATCH v3 2/6] trace: Provide a detailed event control interface
This interface decouples event obtention from interaction. Event can be obtained through three different methods: * identifier * name * simple wildcard pattern Signed-off-by: Lluís Vilanova --- docs/tracing.txt | 41 + trace/control-internal.h | 60 +++ trace/control.c | 92 ++--- trace/control.h | 148 ++ 4 files changed, 296 insertions(+), 45 deletions(-) create mode 100644 trace/control-internal.h diff --git a/docs/tracing.txt b/docs/tracing.txt index a92716f..17690f1 100644 --- a/docs/tracing.txt +++ b/docs/tracing.txt @@ -100,44 +100,32 @@ respectively. This ensures portability between 32- and 64-bit platforms. == Generic interface and monitor commands == -You can programmatically query and control the dynamic state of trace events -through a backend-agnostic interface: +You can programmatically query and control the state of trace events through a +backend-agnostic interface provided by the file "trace/control.h". -* trace_print_events +Note that some of the backends do not provide an implementation for some parts +of this interface, in which case QEMU will just print a warning (please refer to +header "trace/control.h" to see which routines are backend-dependant). -* trace_event_set_state - Enables or disables trace events at runtime inside QEMU. - The function returns "true" if the state of the event has been successfully - changed, or "false" otherwise: - -#include "trace/control.h" - -trace_event_set_state("virtio_irq", true); /* enable */ -[...] -trace_event_set_state("virtio_irq", false); /* disable */ - -Note that some of the backends do not provide an implementation for this -interface, in which case QEMU will just print a warning. - -This functionality is also provided through monitor commands: +The state of events can also be queried and modified through monitor commands: * info trace-events View available trace events and their state. State 1 means enabled, state 0 means disabled. * trace-event NAME on|off - Enable/disable a given trace event or a group of events having common prefix - through wildcard. + Enable/disable a given trace event or a group of events (using wildcards). The "-trace events=" command line argument can be used to enable the events listed in from the very beginning of the program. This file must contain one event name per line. -A basic wildcard matching is supported in both the monitor command "trace --event" and the events list file. That means you can enable/disable the events -having a common prefix in a batch. For example, virtio-blk trace events could -be enabled using: - trace-event virtio_blk_* on +Wildcard matching is supported in both the monitor command "trace -event" and +the events list file. That means you can enable/disable the events having a +common prefix in a batch. For example, virtio-blk trace events could be enabled +using the following monitor command: + +trace-event virtio_blk_* on == Trace backends == @@ -268,3 +256,6 @@ guard such computations and avoid its compilation when the event is disabled: } return ptr; } + +You can check both if the event has been disabled and is dynamically enabled at +the same time using the 'trace_event_get_state' routine. diff --git a/trace/control-internal.h b/trace/control-internal.h new file mode 100644 index 000..81db761 --- /dev/null +++ b/trace/control-internal.h @@ -0,0 +1,60 @@ +/* + * Interface for configuring and controlling the state of tracing events. + * + * Copyright (C) 2011, 2012 Lluís Vilanova + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + + +extern TraceEvent trace_events[]; + + +static inline TraceEvent *trace_event_id(TraceEventID id) +{ +assert(id < trace_event_count()); +return &trace_events[id]; +} + +static inline TraceEventID trace_event_count(void) +{ +return TRACE_EVENT_COUNT; +} + +static inline bool trace_event_is_pattern(const char *str) +{ +assert(str != NULL); + +while (*str != '\0') { +if (*str == '*') { +return true; +} +str++; +} +return false; +} + +static inline TraceEventID trace_event_get_id(TraceEvent *ev) +{ +assert(ev != NULL); +return ev->id; +} + +static inline const char * trace_event_get_name(TraceEvent *ev) +{ +assert(ev != NULL); +return ev->name; +} + +static inline bool trace_event_get_state_static(TraceEvent *ev) +{ +assert(ev != NULL); +return ev->sstate; +} + +static inline bool trace_event_get_state_dynamic(TraceEvent *ev) +{ +assert(ev != NULL); +return ev->dstate; +} diff --git a/trace/control.c b/trace/control.c index 4c5527d..7fbe854 100644 --- a/trace/control.c +++ b/trace/control.c @@ -1,15 +1,84 @@ /* * Interface for configuring and c
[Qemu-devel] [PATCH v3 1/6] trace: Provide a generic tracing event descriptor
Uses tracetool to generate a backend-independent tracing event description. Signed-off-by: Lluís Vilanova --- Makefile |5 +++ Makefile.objs | 15 +++- scripts/tracetool.py | 94 trace/event-internal.h | 28 ++ 4 files changed, 134 insertions(+), 8 deletions(-) create mode 100644 trace/event-internal.h diff --git a/Makefile b/Makefile index a9f3c7e..13e603c 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,14 @@ BUILD_DIR=$(CURDIR) GENERATED_HEADERS = config-host.h trace.h qemu-options.def + +GENERATED_HEADERS += trace-events.h +GENERATED_SOURCES += trace-events.c + ifeq ($(TRACE_BACKEND),dtrace) GENERATED_HEADERS += trace-dtrace.h endif + GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c trace.c diff --git a/Makefile.objs b/Makefile.objs index e6644c6..31abd21 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -348,6 +348,19 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o ## # trace +trace-events.h: trace-events.h-timestamp +trace-events.h-timestamp: $(SRC_PATH)/trace-events $(TRACETOOL) + $(call tracetool-gen,events-h,events) + $(call tracetool-ci) + +trace-events.c: trace-events.c-timestamp +trace-events.c-timestamp: $(SRC_PATH)/trace-events $(TRACETOOL) + $(call tracetool-gen,events-c,events) + $(call tracetool-ci) + +trace-obj-y += trace-events.o + + ifeq ($(TRACE_BACKEND),dtrace) TRACE_H_EXTRA_DEPS=trace-dtrace.h endif @@ -389,7 +402,7 @@ trace/simple.o: trace/simple.c $(GENERATED_HEADERS) trace-obj-$(CONFIG_TRACE_DTRACE) += trace-dtrace.o ifneq ($(TRACE_BACKEND),dtrace) -trace-obj-y = trace.o +trace-obj-y += trace.o endif trace-nested-$(CONFIG_TRACE_DEFAULT) += default.o diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 7053a74..724b595 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -118,6 +118,73 @@ def get_backend_descr(backend): # formats ## +# format: events-h + +@for_format("events-h", BEGIN, "Generate .h for event description") +def process(events): +print """\ +/* This file is autogenerated by tracetool, do not edit. */ + +#ifndef TRACE_EVENTS_H +#define TRACE_EVENTS_H + +#include +""" + +# event identifiers +print """ +typedef enum {\ +""" +for event in events: +print "TRACE_%s," % event.name.upper() +print """\ +TRACE_EVENT_COUNT +} TraceEventID; +""" + +# static state +for e in events: +if 'disable' in e.properties: +enabled = 0 +else: +enabled = 1 +print "#define TRACE_%s_ENABLED %d" % (e.name.upper(), enabled) + +print """\ +#include "trace/event-internal.h" + +#endif /* TRACE_EVENTS_H */\ +""" + + +## +# format: events-c + +@for_format("events-c", BEGIN, "Generate .h for event description") +def process(events): +print """\ +/* This file is autogenerated by tracetool, do not edit. */ + +#include "trace.h" +#include "trace-events.h" +#include "trace/control.h" + + +TraceEvent trace_events[TRACE_EVENT_COUNT] = {\ +""" +for e in events: +print """\ +{ .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },\ +""" % { "id": "TRACE_" + e.name.upper(), +"name": e.name, +"sstate": "TRACE_%s_ENABLED" % e.name.upper(), +} +print """\ +}; +""" + + +## # format: h @for_format("h", BEGIN, "Generate .h file") @@ -131,13 +198,6 @@ def trace_h_begin(events): @for_format("h", END) def trace_h_end(events): -for e in events: -if 'disable' in e.properties: -enabled = 0 -else: -enabled = 1 -print "#define TRACE_%s_ENABLED %d" % (e.name.upper(), enabled) -print print '#endif /* TRACE_H */' @@ -154,6 +214,26 @@ def trace_c_begin(events): # backends ## +# backend: events + +@for_backend("events", "events-h", "Generic event description") +def process(events): +pass + +@for_backend("nop", "events-h") +def process(events): +pass + +@for_backend("events", "events-c") +def process(events): +pass + +@for_backend("nop", "events-c") +def process(events): +pass + + +## # backend: nop @for_backend("nop", "h", "Tracing disabled") diff --git a/trace/event-internal.h b/trace/event-internal.h new file mode 100644 index 000..d62e82f --- /dev/null +++ b/trace/event-internal.h @@ -0,0 +1,28 @@ +/* + * Interface for configuring and controlling the state of tracing events. + * + * Copyright (C) 2012 Lluís Vilanova + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING f
[Qemu-devel] [PATCH v3 0/6] trace: Generic event state description
NOTE: Applies on top of the tracetool-handling trivial changes. Provides a generic event state description and a more detailed event control and query interface. Signed-off-by: Lluís Vilanova --- Changes in v3: * Add some assertions. * Remove debugging printf's. * Improve documentation. * Make 'trace_event_get_state_static' use run-time information, and leave TRACE_*_ENABLED for compile-time checks. Changes in v2: * Minor compilation fixes. Lluís Vilanova (6): trace: Provide a generic tracing event descriptor trace: Provide a detailed event control interface trace: [monitor] Use new event control interface trace: [default] Use new event control interface trace: [simple] Port to generic event information and new control interface trace: [stderr] Port to generic event information and new control interface Makefile |5 ++ Makefile.objs| 15 - docs/tracing.txt | 41 + monitor.c| 15 - scripts/tracetool.py | 149 -- trace/control-internal.h | 60 +++ trace/control.c | 92 ++-- trace/control.h | 148 ++ trace/default.c |3 - trace/event-internal.h | 28 + trace/simple.c | 33 ++ trace/simple.h |6 -- trace/stderr.c | 35 ++- trace/stderr.h | 11 --- 14 files changed, 475 insertions(+), 166 deletions(-) create mode 100644 trace/control-internal.h create mode 100644 trace/event-internal.h delete mode 100644 trace/stderr.h To: qemu-devel@nongnu.org Cc: Stefan Hajnoczi Cc: Blue Swirl
Re: [Qemu-devel] [PATCH 5/5] raw-posix: unmount CD-ROM filesystem via udisks
On 02/10/2012 01:51 PM, Markus Armbruster wrote: > We need to use O_EXCL in order to suppress event generation in the > kernel. However, O_EXCL by definition fails when the CD-ROM drive > is mounted. Automatically unmount it when it is passed through to > the guest. I'm not sure automatic unmount is worth the trouble, and I'm even less sure making the auto-unmount mandatory is a smart move. Getting O_EXCL access is worth the trouble. Everything else is just means to an end. :) Paolo
Re: [Qemu-devel] [PATCH v2 00/15] SCSI s/g + SCSI migration + virtio-scsi
On 02/10/2012 03:01 PM, Stefan Hajnoczi wrote: The virtio-scsi portions look good. Thanks, I'll rebase and resubmit! Paolo
Re: [Qemu-devel] Memory: how to determine the max memory size of one VM?
On Fri, Feb 10, 2012 at 11:53 AM, Zhi Yong Wu wrote: > By the way, need we still to do one clean failure exit? I find the abort(3) usage odd but it's not critical to change it. Since we printed an error message I would have expected exit(EXIT_FAILURE), not abort(3) which is usually used for strange cases that you want to debug if hit. Stefan
Re: [Qemu-devel] [PATCH v2 00/15] SCSI s/g + SCSI migration + virtio-scsi
On Mon, Jan 16, 2012 at 4:30 PM, Paolo Bonzini wrote: > Here is v2 (three counting the RFC) of the virtio-scsi driver. > Unlike previous versions, it includes migration support. > > The only change in the spec has been s/UNDERRUN/OVERRUN/g. > > Paolo Bonzini (13): > dma-helpers: make QEMUSGList target independent > dma-helpers: add dma_buf_read and dma_buf_write > dma-helpers: add accounting wrappers > ahci: use new DMA helpers > scsi: pass residual amount to command_complete > scsi: add scatter/gather functionality > scsi-disk: enable scatter/gather functionality > scsi: add SCSIDevice vmstate definitions > scsi-generic: add migration support > scsi-disk: add migration support > virtio-scsi: add basic SCSI bus operation > virtio-scsi: process control queue requests > virtio-scsi: add migration support > > Stefan Hajnoczi (2): > virtio-scsi: Add virtio-scsi stub device > virtio-scsi: Add basic request processing infrastructure > > Makefile.target | 1 + > default-configs/pci.mak | 1 + > default-configs/s390x-softmmu.mak | 1 + > dma-helpers.c | 36 +++ > dma.h | 20 +- > hw/esp.c | 3 +- > hw/ide/ahci.c | 82 +- > hw/lsi53c895a.c | 2 +- > hw/pci.h | 1 + > hw/s390-virtio-bus.c | 24 ++ > hw/s390-virtio-bus.h | 2 + > hw/scsi-bus.c | 143 +- > hw/scsi-disk.c | 120 +++- > hw/scsi-generic.c | 25 ++ > hw/scsi.h | 22 ++- > hw/spapr_vscsi.c | 2 +- > hw/usb-msd.c | 2 +- > hw/virtio-pci.c | 42 +++ > hw/virtio-pci.h | 2 + > hw/virtio-scsi.c | 607 > + > hw/virtio-scsi.h | 36 +++ > hw/virtio.h | 3 + > 22 files changed, 1074 insertions(+), 103 deletions(-) > create mode 100644 hw/virtio-scsi.c > create mode 100644 hw/virtio-scsi.h The virtio-scsi portions look good. Stefan
Re: [Qemu-devel] [PATCH 3/5] raw-posix: keep complete control of door locking if possible
On 02/10/2012 01:49 PM, Markus Armbruster wrote: With manage_door off: * cdrom_lock_medium() does nothing. Thus, guest OS operating the virtual door lock does not affect the physical door. * cdrom_eject() does nothing. Thus, guest OS moving the virtual tray does not affect the physical tray. That's because manage_door off means "we couldn't get O_EXCL to work". udev will affect the physical tray and we cannot really compete with it. Compare to before this patch: * cdrom_lock_medium() fails silently. Thus, guest OS operating the virtual door may or may not affect the physical door. It usually does unless the CD-ROM is mounted in the host. * cdrom_eject() perror()s when it fails. Thus, guest OS moving the virtual tray may or may not affect the physocal tray. It usually does unless the CD-ROM is mounted in the host, or udev got its paws on it (I think). With manage_door on: * cdrom_lock_medium() works exactly as before, except the common failure mode "CD-ROM is mounted in the host" can't happen. * cdrom_eject() works exactly as before, except the common failure mode "CD-ROM is mounted in the host" can't happen. Is this correct? If yes, is it what we want? For virtio-scsi+scsi-block, we definitely want O_EXCL to remove the device from udev and the in-kernel poller. That's because GESN reports events only once, and we do not want the host and guest to race on receiving events. But in order to open with O_EXCL we need to unmount (GNOME3 doesn't have an unmount menu item anymore, which is why I did it myself in patch 5/5). For IDE we do not need O_EXCL in principle. However, using the emulated passthrough CD-ROM gets confusing without O_EXCL (to the user and to the guest, always; and sometimes, to the host udev as well). Basically, the guest tries to lock the disk, but udev runs as root so it can unlock it under its feet as soon as you press the button. With O_EXCL and some extra patches (waiting for Luiz's eject event discussion), everything kinda works; still confusing to the user, but not to the host or VM. I have some prototype patches to improve the situation on IDE somehow (still a far cry from scsi-block), but I'm waiting for Luiz's eject event patches to reach a conclusion first. There is also the case of emulated passthrough SCSI CD-ROM, but I don't care much about it. Shouldn't the user be able to ask for one of "grab the CD-ROM exclusively, else fail", "grab it if you can", "don't grab it even if you could"? Perhaps IDE could be made to work cooperatively, but right now it doesn't. But scsi-block should fail if it cannot manage the door because it bypasses all the CD-ROM machinery and issues SCSI commands directly. +static bool cdrom_get_options(int fd) Shouldn't this return int? Yes. *paper-bag* +{ +/* CDROM_SET_OPTIONS with arg == 0 returns the current options! */ +return ioctl(fd, CDROM_SET_OPTIONS, 0); +} + +static int cdrom_is_locked(int fd) +{ +int opts = cdrom_get_options(fd); + +/* This is the only way we have to probe the current status of + * CDROM_LOCKDOOR (EBUSY = locked). We use CDROM_SET_OPTIONS to + * reset the previous state in case the ioctl succeeds. + */ +if (ioctl(fd, CDROMEJECT_SW, 0) == 0) { +ioctl(fd, CDROM_SET_OPTIONS, opts); +return false; +} else if (errno == EBUSY) { +return true; +} else { +return -errno; +} +} + + static int cdrom_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRawState *s = bs->opaque; +int rc; s->type = FTYPE_CD; -/* open will not fail even if no CD is inserted, so add O_NONBLOCK */ -return raw_open_common(bs, filename, flags, O_NONBLOCK); +/* open will not fail even if no CD is inserted, so add O_NONBLOCK. First Long line, please wrap. I count 78 chars. :) @@ -1086,6 +1157,10 @@ static void cdrom_eject(BlockDriverState *bs, int eject_flag) { BDRVRawState *s = bs->opaque; +if (!s->cd.manage_door) { +return; +} + if (eject_flag) { if (ioctl(s->fd, CDROMEJECT, NULL) < 0) perror("CDROMEJECT"); We report ioctl() failing here... @@ -1099,12 +1174,8 @@ static void cdrom_lock_medium(BlockDriverState *bs, bool locked) { BDRVRawState *s = bs->opaque; -if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) { -/* - * Note: an error can happen if the distribution automatically - * mounts the CD-ROM - */ -/* perror("CDROM_LOCKDOOR"); */ +if (s->cd.manage_door) { +ioctl(s->fd, CDROM_LOCKDOOR, locked); } } ... but not here. Any particular reason for treating the two differently? Not really, I was just keeping the existing code, but the comment about automatic mount does not hold anymore since we have O_EXCL. I think not reporting any error should work just as well. Paolo
[Qemu-devel] [PATCH 22/28] usb: add USBBusOps->wakeup_endpoint
Add usb bus op which is called whenever a usb endpoint becomes ready, so the host adapter emulation can react on that event. Signed-off-by: Gerd Hoffmann --- hw/usb.c |4 hw/usb.h |1 + 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/hw/usb.c b/hw/usb.c index 0572547..e5b8f33 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -73,10 +73,14 @@ void usb_device_reset(USBDevice *dev) void usb_wakeup(USBEndpoint *ep) { USBDevice *dev = ep->dev; +USBBus *bus = usb_bus_from_device(dev); if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) { dev->port->ops->wakeup(dev->port); } +if (bus->ops->wakeup_endpoint) { +bus->ops->wakeup_endpoint(bus, ep); +} } /**/ diff --git a/hw/usb.h b/hw/usb.h index b2caa77..4470ea8 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -425,6 +425,7 @@ struct USBBus { struct USBBusOps { int (*register_companion)(USBBus *bus, USBPort *ports[], uint32_t portcount, uint32_t firstport); +void (*wakeup_endpoint)(USBBus *bus, USBEndpoint *ep); }; void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host); -- 1.7.1
[Qemu-devel] [PATCH v3 07/11] trace: [tracetool] Rewrite event argument parsing
Signed-off-by: Lluís Vilanova --- scripts/tracetool.py | 192 -- 1 files changed, 91 insertions(+), 101 deletions(-) diff --git a/scripts/tracetool.py b/scripts/tracetool.py index b185724..cd1c29d 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -38,49 +38,6 @@ Options: ''' sys.exit(1) -def get_argnames(args): -nfields = 0 -str = [] -for field in args.split(): - nfields = nfields + 1 - # Drop pointer star - type, ptr, tail = field.partition('*') - if type != field: -field = tail - - name, sep, tail = field.partition(',') - - if name == field: -continue - str.append(name) - str.append(", ") - -if nfields > 1: - str.append(name) - return ''.join(str) -else: - return '' - -def calc_sizeofargs(args, argc): -strtype = ('const char*', 'char*', 'const char *', 'char *') -str = [] -newstr = "" -if argc > 0: - str = args.split(',') - for elem in str: -if elem.lstrip().startswith(strtype): #strings - type, sep, var = elem.rpartition('*') - newstr = newstr+"4 + strlen("+var.lstrip()+") + " -#elif '*' in elem: -# newstr = newstr + "4 + " # pointer vars -else: - #type, sep, var = elem.rpartition(' ') - #newstr = newstr+"sizeof("+type.lstrip()+") + " - newstr = newstr + '8 + ' -newstr = newstr + '0' # for last + -return newstr - - def trace_h_begin(): print '''#ifndef TRACE_H #define TRACE_H @@ -133,13 +90,6 @@ def simple_h(events): return -def is_string(arg): -strtype = ('const char*', 'char*', 'const char *', 'char *') -if arg.lstrip().startswith(strtype): -return True -else: -return False - def simple_c(events): rec_off = 0 print '#include "trace.h"' @@ -154,8 +104,16 @@ def simple_c(events): print print '};' print + for num, event in enumerate(events): -argc = event.argc +sizes = [] +for type_, name in event.args: +if type_is_string(type_): +sizes.append("4 + strlen(%s)" % name) +else: +sizes.append("8 + sizeof(%s)" % type_) +sizestr = " + ".join(sizes) + print '''void trace_%(name)s(%(args)s) { unsigned int tbuf_idx, rec_off __attribute__((unused)); @@ -166,52 +124,52 @@ def simple_c(events): if (!trace_list[%(event_id)s].state) { return; } + +tbuf_idx = trace_alloc_record(%(event_id)s, %(sizestr)s); +rec_off = (tbuf_idx + ST_V2_REC_HDR_LEN) %% TRACE_BUF_LEN; /* seek record header */ ''' % { 'name': event.name, 'args': event.args, 'event_id': num, +'sizestr' : sizestr, } -print ''' -tbuf_idx = trace_alloc_record(%(event_id)s, %(sizestr)s); -rec_off = (tbuf_idx + ST_V2_REC_HDR_LEN) %% TRACE_BUF_LEN; /* seek record header */ -''' % {'event_id': num, 'sizestr': event.sizestr,} -if argc > 0: -str = event.arglist -for elem in str: -if is_string(elem): # if string -type, sep, var = elem.rpartition('*') +if len(event.args) > 0: +for type_, name in event.args: +# string +if type_is_string(type_): print ''' -slen = strlen(%(var)s); +slen = strlen(%(name)s); write_to_buffer(rec_off, (uint8_t*)&slen, sizeof(slen)); rec_off += sizeof(slen);''' % { -'var': var.lstrip() +'name': name } print ''' -write_to_buffer(rec_off, (uint8_t*)%(var)s, slen); +write_to_buffer(rec_off, (uint8_t*)%(name)s, slen); rec_off += slen;''' % { -'var': var.lstrip() +'name': name } -elif '*' in elem: # pointer var (not string) -type, sep, var = elem.rpartition('*') +# pointer var (not string) +elif type_.endswith('*'): print ''' -pvar64 = (uint64_t)(uint64_t*)%(var)s; +pvar64 = (uint64_t)(uint64_t*)%(name)s; write_to_buffer(rec_off, (uint8_t*)&pvar64, sizeof(uint64_t)); rec_off += sizeof(uint64_t);''' % { -'var': var.lstrip() +'name': name } -else: # primitive data type -type, sep, var = elem.rpartition(' ') +# primitive data type +else: print ''' -var64 = (uint64_t)%(var)s; +var64 = (uint64_t)%(name)s; write_to_buffer(rec_off, (uint8_t*)&var64, sizeof(uint64_t)); rec_off += sizeof(uint64_t);''' % { -'var': var.lstrip() +'name': name } print ''' -trace_mark_record_complete(tbuf_idx);''' -print '}' -print +trace_mark_record_complete(tbuf_idx); +} + +''' return @@ -220,12 +178,11 @@ def stderr_h(events): #include "trace/stderr.h" extern TraceEvent trace_lis
[Qemu-devel] [PATCH 07/15] iSCSI: add configuration variables for iSCSI
From: Ronnie Sahlberg This patch adds configuration variables for iSCSI to set initiator-name to use when logging in to the target, which type of header-digest to negotiate with the target and username and password for CHAP authentication. This allows specifying a initiator-name either from the command line -iscsi initiator-name=iqn.2004-01.com.example:test or from a configuration file included with -readconfig [iscsi] initiator-name = iqn.2004-01.com.example:test header-digest = CRC32C|CRC32C-NONE|NONE-CRC32C|NONE user = CHAP username password = CHAP password If you use several different targets, you can also configure this on a per target basis by using a group name: [iscsi "iqn.target.name"] ... The configuration file can be read using -readconfig. Example : qemu-system-i386 -drive file=iscsi://127.0.0.1/iqn.ronnie.test/1 -readconfig iscsi.conf Signed-off-by: Ronnie Sahlberg Signed-off-by: Kevin Wolf --- block/iscsi.c | 139 +++ qemu-config.c | 27 +++ qemu-doc.texi | 54 +- qemu-options.hx | 16 +-- vl.c|8 +++ 5 files changed, 229 insertions(+), 15 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index 938c568..bd3ca11 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -455,6 +455,109 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data, } } +static int parse_chap(struct iscsi_context *iscsi, const char *target) +{ +QemuOptsList *list; +QemuOpts *opts; +const char *user = NULL; +const char *password = NULL; + +list = qemu_find_opts("iscsi"); +if (!list) { +return 0; +} + +opts = qemu_opts_find(list, target); +if (opts == NULL) { +opts = QTAILQ_FIRST(&list->head); +if (!opts) { +return 0; +} +} + +user = qemu_opt_get(opts, "user"); +if (!user) { +return 0; +} + +password = qemu_opt_get(opts, "password"); +if (!password) { +error_report("CHAP username specified but no password was given"); +return -1; +} + +if (iscsi_set_initiator_username_pwd(iscsi, user, password)) { +error_report("Failed to set initiator username and password"); +return -1; +} + +return 0; +} + +static void parse_header_digest(struct iscsi_context *iscsi, const char *target) +{ +QemuOptsList *list; +QemuOpts *opts; +const char *digest = NULL; + +list = qemu_find_opts("iscsi"); +if (!list) { +return; +} + +opts = qemu_opts_find(list, target); +if (opts == NULL) { +opts = QTAILQ_FIRST(&list->head); +if (!opts) { +return; +} +} + +digest = qemu_opt_get(opts, "header-digest"); +if (!digest) { +return; +} + +if (!strcmp(digest, "CRC32C")) { +iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C); +} else if (!strcmp(digest, "NONE")) { +iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE); +} else if (!strcmp(digest, "CRC32C-NONE")) { +iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE); +} else if (!strcmp(digest, "NONE-CRC32C")) { +iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C); +} else { +error_report("Invalid header-digest setting : %s", digest); +} +} + +static char *parse_initiator_name(const char *target) +{ +QemuOptsList *list; +QemuOpts *opts; +const char *name = NULL; + +list = qemu_find_opts("iscsi"); +if (!list) { +return g_strdup("iqn.2008-11.org.linux-kvm"); +} + +opts = qemu_opts_find(list, target); +if (opts == NULL) { +opts = QTAILQ_FIRST(&list->head); +if (!opts) { +return g_strdup("iqn.2008-11.org.linux-kvm"); +} +} + +name = qemu_opt_get(opts, "initiator-name"); +if (!name) { +return g_strdup("iqn.2008-11.org.linux-kvm"); +} + +return g_strdup(name); +} + /* * We support iscsi url's on the form * iscsi://[%@][:]// @@ -465,6 +568,7 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) struct iscsi_context *iscsi = NULL; struct iscsi_url *iscsi_url = NULL; struct IscsiTask task; +char *initiator_name = NULL; int ret; if ((BDRV_SECTOR_SIZE % 512) != 0) { @@ -474,16 +578,6 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) return -EINVAL; } -memset(iscsilun, 0, sizeof(IscsiLun)); - -/* Should really append the KVM name after the ':' here */ -iscsi = iscsi_create_context("iqn.2008-11.org.linux-kvm:"); -if (iscsi == NULL) { -error_report("iSCSI: Failed to create iSCSI context."); -ret = -ENOMEM; -goto failed; -} - iscsi_url = iscsi_parse_full_url(iscsi, filename); if (iscsi_url == NULL) { error_report(
[Qemu-devel] [PATCH 07/28] usb: add usb_find_device()
Add usb_find_device(). This function will check whenever a device with a specific address is connected to the specified port. Usually this will just check state and address of the device hooked up to the port, but in case of a hub it will ask the hub to check all hub ports for a matching device. This patch doesn't put the code into use yet, see the following patches for details. The master plan is to separate device lookup and packet processing. Right now the usb code simply walks all devices, calls usb_handle_packet() on each until one accepts the packet (by returning something different that USB_RET_NODEV). I want to have a device lookup first, then call usb_handle_packet() once, for the device which actually processes the packet. Signed-off-by: Gerd Hoffmann --- hw/usb-bus.c |9 + hw/usb.c | 13 + hw/usb.h | 10 ++ 3 files changed, 32 insertions(+), 0 deletions(-) diff --git a/hw/usb-bus.c b/hw/usb-bus.c index b753834..5c05ed5 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -74,6 +74,15 @@ static int usb_device_init(USBDevice *dev) return 0; } +USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr) +{ +USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); +if (klass->find_device) { +return klass->find_device(dev, addr); +} +return NULL; +} + static void usb_device_handle_destroy(USBDevice *dev) { USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); diff --git a/hw/usb.c b/hw/usb.c index 0c26164..bacdc81 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -295,6 +295,19 @@ int set_usb_string(uint8_t *buf, const char *str) return q - buf; } +USBDevice *usb_find_device(USBPort *port, uint8_t addr) +{ +USBDevice *dev = port->dev; + +if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) { +return NULL; +} +if (dev->addr == addr) { +return dev; +} +return usb_device_find_device(dev, addr); +} + /* Hand over a packet to a device for processing. Return value USB_RET_ASYNC indicates the processing isn't finished yet, the driver will call usb_packet_complete() when done processing it. */ diff --git a/hw/usb.h b/hw/usb.h index 6127176..1beb4b3 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -229,6 +229,12 @@ typedef struct USBDeviceClass { int (*init)(USBDevice *dev); /* + * Walk (enabled) downstream ports, check for a matching device. + * Only hubs implement this. + */ +USBDevice *(*find_device)(USBDevice *dev, uint8_t addr); + +/* * Process USB packet. * Called by the HC (Host Controller). * @@ -332,6 +338,8 @@ void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes); void usb_packet_skip(USBPacket *p, size_t bytes); void usb_packet_cleanup(USBPacket *p); +USBDevice *usb_find_device(USBPort *port, uint8_t addr); + int usb_handle_packet(USBDevice *dev, USBPacket *p); void usb_packet_complete(USBDevice *dev, USBPacket *p); void usb_cancel_packet(USBPacket * p); @@ -446,6 +454,8 @@ extern const VMStateDescription vmstate_usb_device; .offset = vmstate_offset_value(_state, _field, USBDevice), \ } +USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr); + int usb_device_handle_packet(USBDevice *dev, USBPacket *p); void usb_device_cancel_packet(USBDevice *dev, USBPacket *p); -- 1.7.1
[Qemu-devel] [PATCH v4 09/11] trace: [tracetool] Automatically establish available backends and formats
Signed-off-by: Lluís Vilanova --- Makefile.objs|6 - Makefile.target |3 scripts/tracetool.py | 357 -- 3 files changed, 230 insertions(+), 136 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 2b68739..941386b 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -354,12 +354,12 @@ else trace.h: trace.h-timestamp endif trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -h < $< > $@," GEN trace.h") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h trace.c: trace.c-timestamp trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -c < $< > $@," GEN trace.c") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c") @cmp -s $@ trace.c || cp $@ trace.c trace.o: trace.c $(GENERATED_HEADERS) @@ -372,7 +372,7 @@ trace-dtrace.h: trace-dtrace.dtrace # rule file. So we use '.dtrace' instead trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace") @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) diff --git a/Makefile.target b/Makefile.target index 2b24ea1..2bdf955 100644 --- a/Makefile.target +++ b/Makefile.target @@ -53,11 +53,12 @@ endif $(QEMU_PROG).stp: $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ + --format=stap \ --backend=$(TRACE_BACKEND) \ --binary=$(bindir)/$(QEMU_PROG) \ --target-arch=$(TARGET_ARCH) \ --target-type=$(TARGET_TYPE) \ - --stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") + < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") else stap: endif diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 91e7620..8ce39df 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -11,33 +11,109 @@ import sys import getopt -def usage(): -print "Tracetool: Generate tracing code for trace events file on stdin" -print "Usage:" -print sys.argv[0], " --backend=[nop|simple|stderr|dtrace|ust] [-h|-c|-d|--stap]" -print ''' -Backends: - --nop Tracing disabled - --simple Simple built-in backend - --stderr Stderr built-in backend - --dtrace DTrace/SystemTAP backend - --ust LTTng User Space Tracing backend - -Output formats: - -h Generate .h file - -c Generate .c file - -d Generate .d file (DTrace only) - --stap Generate .stp file (DTrace with SystemTAP only) -Options: - --binary [path]Full path to QEMU binary - --target-arch [arch]QEMU emulator target arch - --target-type [type]QEMU emulator target type ('system' or 'user') - --probe-prefix [prefix] Prefix for dtrace probe names - (default: qemu-targettype-targetarch) -''' -sys.exit(1) +## +# format auto-registration + +class _Tag: +pass + +_formats = {} + +BEGIN = _Tag() +END = _Tag() +_DESCR = _Tag() + +def for_format(format_, when, descr = None): +"""Decorator for format generator functions.""" + +if when is not BEGIN and when is not END: +raise ValueError("Invalid 'when' tag") +if format_ in _formats and when in _formats[format_]: +raise ValueError("Format '%s' already set for given 'when' tag" % format_) + +if format_ not in _formats: +_formats[format_] = {} +if descr is not None: +if _DESCR in _formats[format_]: +raise ValueError("Description already set") +_formats[format_][_DESCR] = descr + +def func(f): +_formats[format_][when] = f +return f +return func + +def get_format(format_, when): +"""Get a format generator function.""" + +def nop(*args, **kwargs): +pass +if format_ in _formats and when in _formats[format_]: +return _formats[format_][when] +else: +return nop + +def get_format_descr(format_): +"""Get the description of a format generator.""" + +if format_ in _formats and _DESCR in _formats[format_]: +return _formats[f
[Qemu-devel] [PATCH 01/28] usb-uhci: implement bandwidth management
The OS is allowed to make the UHCI Controller run in circles. That is usually done to serve multiple connected USB devices in a robin-round fashion, so the available USB bandwidth is evenly distributed between devices. The uhci emulation handles this in a very poor way though. When it figures it runs in circles it stops processing unconditionally, so it usually processes at most a single transfer desriptor per queue, even if there are multiple transfer descriptors are queued up. This patch makes uhci act in a more sophisticated way. It keeps track of successful processed transfer descriptors and transfered bytes. Then it will stop processing when there is nothing to do (no transfer descriptor was completed the last round) or when the transfered data reaches the usb bandwidth limit. Result is that the usb-storage devices connected to uhci are ten times faster, mkfs.vfat time for a 64M stick goes down from five seconds to a half second. Reason for this is that we are now processing up to 20 transfer descriptors (with 64 bytes each) per frame instead of a single one. Signed-off-by: Gerd Hoffmann --- hw/usb-uhci.c | 29 ++--- 1 files changed, 22 insertions(+), 7 deletions(-) diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index cddcc89..e0c7dbb 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -73,7 +73,7 @@ #define FRAME_TIMER_FREQ 1000 -#define FRAME_MAX_LOOPS 100 +#define FRAME_MAX_LOOPS 256 #define NB_PORTS 2 @@ -942,7 +942,7 @@ static int qhdb_insert(QhDb *db, uint32_t addr) static void uhci_process_frame(UHCIState *s) { uint32_t frame_addr, link, old_td_ctrl, val, int_mask; -uint32_t curr_qh; +uint32_t curr_qh, td_count = 0, bytes_count = 0; int cnt, ret; UHCI_TD td; UHCI_QH qh; @@ -967,13 +967,26 @@ static void uhci_process_frame(UHCIState *s) if (qhdb_insert(&qhdb, link)) { /* * We're going in circles. Which is not a bug because - * HCD is allowed to do that as part of the BW management. - * In our case though it makes no sense to spin here. Sync transations - * are already done, and async completion handler will re-process - * the frame when something is ready. + * HCD is allowed to do that as part of the BW management. + * + * Stop processing here if + * (a) no transaction has been done since we've been + * here last time, or + * (b) we've reached the usb 1.1 bandwidth, which is + * 1280 bytes/frame. */ DPRINTF("uhci: detected loop. qh 0x%x\n", link); -break; +if (td_count == 0) { +DPRINTF("uhci: no transaction last round, stop\n"); +break; +} else if (bytes_count >= 1280) { +DPRINTF("uhci: bandwidth limit reached, stop\n"); +break; +} else { +td_count = 0; +qhdb_reset(&qhdb); +qhdb_insert(&qhdb, link); +} } pci_dma_read(&s->dev, link & ~0xf, &qh, sizeof(qh)); @@ -1033,6 +1046,8 @@ static void uhci_process_frame(UHCIState *s) link, td.link, td.ctrl, td.token, curr_qh); link = td.link; +td_count++; +bytes_count += (td.ctrl & 0x7ff) + 1; if (curr_qh) { /* update QH element link */ -- 1.7.1
[Qemu-devel] [PATCH 17/28] usb: USBPacket: add status, rename owner -> ep
Add enum to track the status of USBPackets, use that instead of the owner pointer to figure whenever a usb packet is currently in flight or not. Add some more packet status sanity checks. Also rename the USBEndpoint pointer from "owner" to "ep". Signed-off-by: Gerd Hoffmann --- hw/usb-ehci.c |4 ++-- hw/usb-musb.c |4 ++-- hw/usb-ohci.c |4 ++-- hw/usb-uhci.c |4 ++-- hw/usb.c | 18 +++--- hw/usb.h | 19 --- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index 8f7b3c4..f0213ad 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -715,8 +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 == NULL || -q->packet.owner->dev != dev) { +if (!usb_packet_is_inflight(&q->packet) || +q->packet.ep->dev != dev) { continue; } ehci_free_queue(q); diff --git a/hw/usb-musb.c b/hw/usb-musb.c index ecac631..f4e52f1 100644 --- a/hw/usb-musb.c +++ b/hw/usb-musb.c @@ -811,8 +811,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 == NULL || -s->ep[ep].packey[dir].p.owner->dev != dev) { +if (!usb_packet_is_inflight(&s->ep[ep].packey[dir].p) || +s->ep[ep].packey[dir].p.ep->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 ba854c7..8a8f3bc 100644 --- a/hw/usb-ohci.c +++ b/hw/usb-ohci.c @@ -1709,8 +1709,8 @@ 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 != NULL && -ohci->usb_packet.owner->dev == dev) { +usb_packet_is_inflight(&ohci->usb_packet) && +ohci->usb_packet.ep->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 a1f597a..ef08145 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -236,8 +236,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 == NULL || -curr->packet.owner->dev != dev) { +if (!usb_packet_is_inflight(&curr->packet) || +curr->packet.ep->dev != dev) { continue; } uhci_async_unlink(s, curr); diff --git a/hw/usb.c b/hw/usb.c index 91107f9..8584db0 100644 --- a/hw/usb.c +++ b/hw/usb.c @@ -291,7 +291,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) } assert(dev->addr == p->devaddr); assert(dev->state == USB_STATE_DEFAULT); -assert(p->owner == NULL); +assert(p->state == USB_PACKET_SETUP); if (p->devep == 0) { /* control pipe */ @@ -315,7 +315,8 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) } if (ret == USB_RET_ASYNC) { -p->owner = usb_ep_get(dev, p->pid, p->devep); +p->ep = usb_ep_get(dev, p->pid, p->devep); +p->state = USB_PACKET_ASYNC; } return ret; } @@ -325,8 +326,8 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) handle_packet. */ void usb_packet_complete(USBDevice *dev, USBPacket *p) { -assert(p->owner != NULL); -p->owner = NULL; +assert(p->state == USB_PACKET_ASYNC); +p->state = USB_PACKET_COMPLETE; dev->port->ops->complete(dev->port, p); } @@ -335,9 +336,9 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) completed. */ void usb_cancel_packet(USBPacket * p) { -assert(p->owner != NULL); -usb_device_cancel_packet(p->owner->dev, p); -p->owner = NULL; +assert(p->state == USB_PACKET_ASYNC); +p->state = USB_PACKET_CANCELED; +usb_device_cancel_packet(p->ep->dev, p); } @@ -348,6 +349,8 @@ void usb_packet_init(USBPacket *p) void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep) { +assert(!usb_packet_is_inflight(p)); +p->state = USB_PACKET_SETUP; p->pid = pid; p->devaddr = addr; p->devep = ep; @@ -391,6 +394,7 @@ void usb_packet_skip(USBPacket *p, size_t bytes) void usb_packet_cleanup(USBPacket *p) { +assert(!usb_packet_is_inflight(p)); qemu_iovec_destroy(&p->iov); } diff --git a/hw/usb.h b/hw/usb.h index 294c33d..4e878d3 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -289,8 +289,7 @@ typedef struct USBPortOps { void (*wakeup)(USBPort *port); /* * Note that port->dev will be different then the device from which - * the packet originated when a hub is involved, if you want the orginating - * device use p->owner + * the
[Qemu-devel] [PATCH 23/28] xhci: signal low- and fullspeed support
Signed-off-by: Gerd Hoffmann --- hw/usb-xhci.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c index b274b80..27bdc2b 100644 --- a/hw/usb-xhci.c +++ b/hw/usb-xhci.c @@ -2672,7 +2672,10 @@ static void usb_xhci_init(XHCIState *xhci, DeviceState *dev) for (i = 0; i < MAXPORTS; i++) { memset(&xhci->ports[i], 0, sizeof(xhci->ports[i])); usb_register_port(&xhci->bus, &xhci->ports[i].port, xhci, i, - &xhci_port_ops, USB_SPEED_MASK_HIGH); + &xhci_port_ops, + USB_SPEED_MASK_LOW | + USB_SPEED_MASK_FULL | + USB_SPEED_MASK_HIGH); } for (i = 0; i < MAXSLOTS; i++) { xhci->slots[i].enabled = 0; -- 1.7.1
[Qemu-devel] [PATCH v3 11/11] trace: [tracetool] Add error-reporting functions
Signed-off-by: Lluís Vilanova --- scripts/tracetool.py | 27 +++ 1 files changed, 15 insertions(+), 12 deletions(-) diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 1134544..7053a74 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -12,6 +12,13 @@ import sys import getopt +def error_write(*lines): +sys.stderr.writelines(lines) + +def error(*lines): +error_write(*lines) +sys.exit(1) + ## # format auto-registration @@ -443,14 +450,11 @@ def dtrace_nop_d(events): def trace_stap_begin(events): global probeprefix if binary == "": -print '--binary is required for SystemTAP tapset generator' -sys.exit(1) +error("--binary is required for SystemTAP tapset generator\n") if ((probeprefix == "") and (targettype == "")): -print '--target-type is required for SystemTAP tapset generator' -sys.exit(1) +error("--target-type is required for SystemTAP tapset generator\n") if ((probeprefix == "") and (targetarch == "")): -print '--target-arch is required for SystemTAP tapset generator' -sys.exit(1) +error("--target-arch is required for SystemTAP tapset generator\n") if probeprefix == "": probeprefix = 'qemu.' + targettype + '.' + targetarch print '/* This file is autogenerated by tracetool, do not edit. */' @@ -601,8 +605,9 @@ def main(): try: opts, args = getopt.getopt(sys.argv[1:], "", long_options) except getopt.GetoptError, err: -# print help information and exit: -print str(err) # will print something like "option -a not recognized" +# print help information and exit +# will print something like "option -a not recognized" +error_write(str(err)+"\n") usage() sys.exit(2) for opt, arg in opts: @@ -631,12 +636,10 @@ def main(): usage() if format_ not in _formats: -print "Unknown format: %s" % format_ -print +error_write("Unknown format: %s\n\n" % format_) usage() if backend not in _backends: -print "Unknown backend: %s" % backend -print +error_write("Unknown backend: %s\n\n" % backend) usage() events = read_events(sys.stdin)
[Qemu-devel] [PATCH v3 09/11] trace: [tracetool] Automatically establish available backends and formats
Signed-off-by: Lluís Vilanova --- Makefile.objs|6 - Makefile.target |3 scripts/tracetool.py | 357 -- 3 files changed, 230 insertions(+), 136 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 2b68739..941386b 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -354,12 +354,12 @@ else trace.h: trace.h-timestamp endif trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -h < $< > $@," GEN trace.h") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h trace.c: trace.c-timestamp trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -c < $< > $@," GEN trace.c") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c") @cmp -s $@ trace.c || cp $@ trace.c trace.o: trace.c $(GENERATED_HEADERS) @@ -372,7 +372,7 @@ trace-dtrace.h: trace-dtrace.dtrace # rule file. So we use '.dtrace' instead trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace") @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) diff --git a/Makefile.target b/Makefile.target index 2b24ea1..2bdf955 100644 --- a/Makefile.target +++ b/Makefile.target @@ -53,11 +53,12 @@ endif $(QEMU_PROG).stp: $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ + --format=stap \ --backend=$(TRACE_BACKEND) \ --binary=$(bindir)/$(QEMU_PROG) \ --target-arch=$(TARGET_ARCH) \ --target-type=$(TARGET_TYPE) \ - --stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") + < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") else stap: endif diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 91e7620..8ce39df 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -11,33 +11,109 @@ import sys import getopt -def usage(): -print "Tracetool: Generate tracing code for trace events file on stdin" -print "Usage:" -print sys.argv[0], " --backend=[nop|simple|stderr|dtrace|ust] [-h|-c|-d|--stap]" -print ''' -Backends: - --nop Tracing disabled - --simple Simple built-in backend - --stderr Stderr built-in backend - --dtrace DTrace/SystemTAP backend - --ust LTTng User Space Tracing backend - -Output formats: - -h Generate .h file - -c Generate .c file - -d Generate .d file (DTrace only) - --stap Generate .stp file (DTrace with SystemTAP only) -Options: - --binary [path]Full path to QEMU binary - --target-arch [arch]QEMU emulator target arch - --target-type [type]QEMU emulator target type ('system' or 'user') - --probe-prefix [prefix] Prefix for dtrace probe names - (default: qemu-targettype-targetarch) -''' -sys.exit(1) +## +# format auto-registration + +class _Tag: +pass + +_formats = {} + +BEGIN = _Tag() +END = _Tag() +_DESCR = _Tag() + +def for_format(format_, when, descr = None): +"""Decorator for format generator functions.""" + +if when is not BEGIN and when is not END: +raise ValueError("Invalid 'when' tag") +if format_ in _formats and when in _formats[format_]: +raise ValueError("Format '%s' already set for given 'when' tag" % format_) + +if format_ not in _formats: +_formats[format_] = {} +if descr is not None: +if _DESCR in _formats[format_]: +raise ValueError("Description already set") +_formats[format_][_DESCR] = descr + +def func(f): +_formats[format_][when] = f +return f +return func + +def get_format(format_, when): +"""Get a format generator function.""" + +def nop(*args, **kwargs): +pass +if format_ in _formats and when in _formats[format_]: +return _formats[format_][when] +else: +return nop + +def get_format_descr(format_): +"""Get the description of a format generator.""" + +if format_ in _formats and _DESCR in _formats[format_]: +return _formats[f
[Qemu-devel] [PATCH 28/28] xhci: handle USB_RET_NAK
Add a field to XHCITransfer to correctly keep track of NAK'ed usb packets. Retry transfers when the endpoint is kicked again. Implement wakeup_endpoint bus op so we can kick the endpoint when needed. With this patch applied the emulated hid devices are working correctly when hooked up to xhci. usb-tabled without polling, yay! Signed-off-by: Gerd Hoffmann --- hw/usb-xhci.c | 107 +++-- 1 files changed, 96 insertions(+), 11 deletions(-) diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c index 3026edb..ac7b12b 100644 --- a/hw/usb-xhci.c +++ b/hw/usb-xhci.c @@ -307,7 +307,8 @@ typedef struct XHCIState XHCIState; typedef struct XHCITransfer { XHCIState *xhci; USBPacket packet; -bool running; +bool running_async; +bool running_retry; bool cancelled; bool complete; bool backgrounded; @@ -338,6 +339,7 @@ typedef struct XHCIEPContext { unsigned int next_xfer; unsigned int comp_xfer; XHCITransfer transfers[TD_QUEUE]; +XHCITransfer *retry; bool bg_running; bool bg_updating; unsigned int next_bg; @@ -915,12 +917,17 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, xferi = epctx->next_xfer; for (i = 0; i < TD_QUEUE; i++) { XHCITransfer *t = &epctx->transfers[xferi]; -if (t->running) { +if (t->running_async) { +usb_cancel_packet(&t->packet); +t->running_async = 0; t->cancelled = 1; -/* libusb_cancel_transfer(t->usbxfer) */ DPRINTF("xhci: cancelling transfer %d, waiting for it to complete...\n", i); killed++; } +if (t->running_retry) { +t->running_retry = 0; +epctx->retry = NULL; +} if (t->backgrounded) { t->backgrounded = 0; } @@ -941,9 +948,10 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid, xferi = epctx->next_bg; for (i = 0; i < BG_XFERS; i++) { XHCITransfer *t = &epctx->bg_transfers[xferi]; -if (t->running) { +if (t->running_async) { +usb_cancel_packet(&t->packet); +t->running_async = 0; t->cancelled = 1; -/* libusb_cancel_transfer(t->usbxfer); */ DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i); killed++; } @@ -1409,12 +1417,20 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev) static int xhci_complete_packet(XHCITransfer *xfer, int ret) { if (ret == USB_RET_ASYNC) { -xfer->running = 1; +xfer->running_async = 1; +xfer->running_retry = 0; +xfer->complete = 0; +xfer->cancelled = 0; +return 0; +} else if (ret == USB_RET_NAK) { +xfer->running_async = 0; +xfer->running_retry = 1; xfer->complete = 0; xfer->cancelled = 0; return 0; } else { -xfer->running = 0; +xfer->running_async = 0; +xfer->running_retry = 0; xfer->complete = 1; } @@ -1529,7 +1545,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) wValue, wIndex, wLength, xfer->data); xhci_complete_packet(xfer, ret); -if (!xfer->running) { +if (!xfer->running_async && !xfer->running_retry) { xhci_kick_ep(xhci, xfer->slotid, xfer->epid); } return 0; @@ -1596,7 +1612,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx ret = usb_handle_packet(dev, &xfer->packet); xhci_complete_packet(xfer, ret); -if (!xfer->running) { +if (!xfer->running_async && !xfer->running_retry) { xhci_kick_ep(xhci, xfer->slotid, xfer->epid); } return 0; @@ -1667,6 +1683,25 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid return; } +if (epctx->retry) { +/* retry nak'ed transfer */ +XHCITransfer *xfer = epctx->retry; +int result; + +DPRINTF("xhci: retry nack'ed transfer ...\n"); +assert(xfer->running_retry); +xhci_setup_packet(xfer, xfer->packet.ep->dev); +result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); +if (result == USB_RET_NAK) { +DPRINTF("xhci: ... xfer still nacked\n"); +return; +} +DPRINTF("xhci: ... result %d\n", result); +xhci_complete_packet(xfer, result); +assert(!xfer->running_retry); +epctx->retry = NULL; +} + if (epctx->state == EP_HALTED) { DPRINTF("xhci: ep halted, not running schedule\n"); return; @@ -1676,9 +1711,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid while (1) { XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer];
[Qemu-devel] [PATCH v4 08/11] trace: [tracetool] Make format-specific code optional and with access to event information
Signed-off-by: Lluís Vilanova --- scripts/tracetool.py | 35 ++- 1 files changed, 10 insertions(+), 25 deletions(-) diff --git a/scripts/tracetool.py b/scripts/tracetool.py index cd1c29d..91e7620 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -38,26 +38,19 @@ Options: ''' sys.exit(1) -def trace_h_begin(): +def trace_h_begin(events): print '''#ifndef TRACE_H #define TRACE_H /* This file is autogenerated by tracetool, do not edit. */ #include "qemu-common.h"''' -return -def trace_h_end(): +def trace_h_end(events): print '#endif /* TRACE_H */' -return -def trace_c_begin(): +def trace_c_begin(events): print '/* This file is autogenerated by tracetool, do not edit. */' -return - -def trace_c_end(): -# nop, required for trace_gen -return def nop_h(events): print @@ -350,7 +343,7 @@ probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s") def dtrace_nop_stp(events): pass -def trace_stap_begin(): +def trace_stap_begin(events): global probeprefix if backend != "dtrace": print 'SystemTAP tapset generator not applicable to %s backend' % backend @@ -367,20 +360,13 @@ def trace_stap_begin(): if probeprefix == "": probeprefix = 'qemu.' + targettype + '.' + targetarch print '/* This file is autogenerated by tracetool, do not edit. */' -return -def trace_stap_end(): -return #nop, reqd for trace_gen - -def trace_d_begin(): +def trace_d_begin(events): if backend != 'dtrace': print 'DTrace probe generator not applicable to %s backend' % backend sys.exit(1) print '/* This file is autogenerated by tracetool, do not edit. */' -def trace_d_end(): -return #nop, reqd for trace_gen - # Registry of backends and their converter functions converters = { @@ -416,22 +402,19 @@ converters = { } # Trace file header and footer code generators -trace_gen = { +formats = { 'h': { 'begin': trace_h_begin, 'end': trace_h_end, }, 'c': { 'begin': trace_c_begin, -'end': trace_c_end, }, 'd': { 'begin': trace_d_begin, -'end': trace_d_end, }, 'stap': { 'begin': trace_stap_begin, -'end': trace_stap_end, }, } @@ -564,10 +547,12 @@ def main(): events = read_events(sys.stdin) -trace_gen[output]['begin']() +if 'begin' in formats[output]: +formats[output]['begin'](events) converters[backend][output]([ e for e in events if 'disable' not in e.properties ]) converters['nop'][output]([ e for e in events if 'disable' in e.properties ]) -trace_gen[output]['end']() +if 'end' in formats[output]: +formats[output]['end'](events) if __name__ == "__main__": main()
[Qemu-devel] [PATCH 04/15] qed: replace is_write with flags field
From: Stefan Hajnoczi Per-request attributes like read/write are currently implemented as bool fields in the QEDAIOCB struct. This becomes unwiedly as the number of attributes grows. For example, the qed_aio_setup() function would have to take multiple bool arguments and at call sites it would be hard to distinguish the meaning of each bool. Instead use a flags field with bitmask constants. This will be used when zero write support is added. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/qed.c | 15 --- block/qed.h |6 +- trace-events |2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/block/qed.c b/block/qed.c index 8da3ebe..b66dd17 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1233,8 +1233,8 @@ static void qed_aio_next_io(void *opaque, int ret) { QEDAIOCB *acb = opaque; BDRVQEDState *s = acb_to_s(acb); -QEDFindClusterFunc *io_fn = -acb->is_write ? qed_aio_write_data : qed_aio_read_data; +QEDFindClusterFunc *io_fn = (acb->flags & QED_AIOCB_WRITE) ? +qed_aio_write_data : qed_aio_read_data; trace_qed_aio_next_io(s, acb, ret, acb->cur_pos + acb->cur_qiov.size); @@ -1264,14 +1264,14 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, - void *opaque, bool is_write) + void *opaque, int flags) { QEDAIOCB *acb = qemu_aio_get(&qed_aio_pool, bs, cb, opaque); trace_qed_aio_setup(bs->opaque, acb, sector_num, nb_sectors, - opaque, is_write); +opaque, flags); -acb->is_write = is_write; +acb->flags = flags; acb->finished = NULL; acb->qiov = qiov; acb->qiov_offset = 0; @@ -1291,7 +1291,7 @@ static BlockDriverAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { -return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, false); +return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); } static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs, @@ -1300,7 +1300,8 @@ static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { -return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, true); +return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, + opaque, QED_AIOCB_WRITE); } static BlockDriverAIOCB *bdrv_qed_aio_flush(BlockDriverState *bs, diff --git a/block/qed.h b/block/qed.h index 62cbd3b..abed147 100644 --- a/block/qed.h +++ b/block/qed.h @@ -123,12 +123,16 @@ typedef struct QEDRequest { CachedL2Table *l2_table; } QEDRequest; +enum { +QED_AIOCB_WRITE = 0x0001, /* read or write? */ +}; + typedef struct QEDAIOCB { BlockDriverAIOCB common; QEMUBH *bh; int bh_ret; /* final return status for completion bh */ QSIMPLEQ_ENTRY(QEDAIOCB) next; /* next request */ -bool is_write; /* false - read, true - write */ +int flags; /* QED_AIOCB_* bits ORed together */ bool *finished; /* signal for cancel completion */ uint64_t end_pos; /* request end on block device, in bytes */ diff --git a/trace-events b/trace-events index 3372087..9b26ce2 100644 --- a/trace-events +++ b/trace-events @@ -321,7 +321,7 @@ qed_need_check_timer_cb(void *s) "s %p" qed_start_need_check_timer(void *s) "s %p" qed_cancel_need_check_timer(void *s) "s %p" qed_aio_complete(void *s, void *acb, int ret) "s %p acb %p ret %d" -qed_aio_setup(void *s, void *acb, int64_t sector_num, int nb_sectors, void *opaque, int is_write) "s %p acb %p sector_num %"PRId64" nb_sectors %d opaque %p is_write %d" +qed_aio_setup(void *s, void *acb, int64_t sector_num, int nb_sectors, void *opaque, int flags) "s %p acb %p sector_num %"PRId64" nb_sectors %d opaque %p flags %#x" qed_aio_next_io(void *s, void *acb, int ret, uint64_t cur_pos) "s %p acb %p ret %d cur_pos %"PRIu64 qed_aio_read_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" -- 1.7.6.5
[Qemu-devel] [PATCH 14/15] sheepdog: fix co_recv coroutine context
From: MORITA Kazutaka The co_recv coroutine has two things that will try to enter it: 1. The select(2) read callback on the sheepdog socket. 2. The aio_add_request() blocking operations, including a coroutine mutex. This patch fixes it by setting NULL to co_recv before sending data. In future, we should make the sheepdog driver fully coroutine-based and simplify request handling. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf --- block/sheepdog.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index 9416400..00276f6f 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -629,6 +629,9 @@ static void coroutine_fn aio_read_response(void *opaque) switch (acb->aiocb_type) { case AIOCB_WRITE_UDATA: +/* this coroutine context is no longer suitable for co_recv + * because we may send data to update vdi objects */ +s->co_recv = NULL; if (!is_data_obj(aio_req->oid)) { break; } -- 1.7.6.5
[Qemu-devel] [PATCH 13/15] AHCI: Fix port reset race
From: Alexander Graf bdrv_aio_cancel() can trigger bdrv_aio_flush() which makes all aio that is currently in flight finish. So what we do is: port reset detect ncq in flight cancel ncq delete ncq sg list at which point we have double freed the sg list. Instead, with this patch we do: port reset detect ncq in flight cancel ncq check if we are really still in flight delete ncq sg list which makes things work and gets rid of the race. Signed-off-by: Alexander Graf Signed-off-by: Kevin Wolf --- hw/ide/ahci.c |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index c87a6ca..caff7bc 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -560,6 +560,11 @@ static void ahci_reset_port(AHCIState *s, int port) ncq_tfs->aiocb = NULL; } +/* Maybe we just finished the request thanks to bdrv_aio_cancel() */ +if (!ncq_tfs->used) { +continue; +} + qemu_sglist_destroy(&ncq_tfs->sglist); ncq_tfs->used = 0; } -- 1.7.6.5
Re: [Qemu-devel] [PATCH 5/5] raw-posix: unmount CD-ROM filesystem via udisks
Paolo Bonzini writes: > We need to use O_EXCL in order to suppress event generation in the > kernel. However, O_EXCL by definition fails when the CD-ROM drive > is mounted. Automatically unmount it when it is passed through to > the guest. I'm not sure automatic unmount is worth the trouble, and I'm even less sure making the auto-unmount mandatory is a smart move.
[Qemu-devel] [PATCH 08/28] usb-hub: implement find_device
Implement the find_device callback for the usb hub. It'll loop over all ports, calling usb_find_device for all enabled ports until it finds a matching device. Signed-off-by: Gerd Hoffmann --- hw/usb-hub.c | 21 + 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 0f3b2dd..bd7641c 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -220,6 +220,26 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet) s->dev.port->ops->complete(s->dev.port, packet); } +static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr) +{ +USBHubState *s = DO_UPCAST(USBHubState, dev, dev); +USBHubPort *port; +USBDevice *downstream; +int i; + +for (i = 0; i < NUM_PORTS; i++) { +port = &s->ports[i]; +if (!(port->wPortStatus & PORT_STAT_ENABLE)) { +continue; +} +downstream = usb_find_device(&port->port, addr); +if (downstream != NULL) { +return downstream; +} +} +return NULL; +} + static void usb_hub_handle_reset(USBDevice *dev) { USBHubState *s = DO_UPCAST(USBHubState, dev, dev); @@ -541,6 +561,7 @@ static void usb_hub_class_initfn(ObjectClass *klass, void *data) uc->init = usb_hub_initfn; uc->product_desc = "QEMU USB Hub"; uc->usb_desc = &desc_hub; +uc->find_device= usb_hub_find_device; uc->handle_packet = usb_hub_handle_packet; uc->handle_reset = usb_hub_handle_reset; uc->handle_control = usb_hub_handle_control; -- 1.7.1
[Qemu-devel] [PATCH v4 11/11] trace: [tracetool] Add error-reporting functions
Signed-off-by: Lluís Vilanova --- scripts/tracetool.py | 27 +++ 1 files changed, 15 insertions(+), 12 deletions(-) diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 1134544..7053a74 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -12,6 +12,13 @@ import sys import getopt +def error_write(*lines): +sys.stderr.writelines(lines) + +def error(*lines): +error_write(*lines) +sys.exit(1) + ## # format auto-registration @@ -443,14 +450,11 @@ def dtrace_nop_d(events): def trace_stap_begin(events): global probeprefix if binary == "": -print '--binary is required for SystemTAP tapset generator' -sys.exit(1) +error("--binary is required for SystemTAP tapset generator\n") if ((probeprefix == "") and (targettype == "")): -print '--target-type is required for SystemTAP tapset generator' -sys.exit(1) +error("--target-type is required for SystemTAP tapset generator\n") if ((probeprefix == "") and (targetarch == "")): -print '--target-arch is required for SystemTAP tapset generator' -sys.exit(1) +error("--target-arch is required for SystemTAP tapset generator\n") if probeprefix == "": probeprefix = 'qemu.' + targettype + '.' + targetarch print '/* This file is autogenerated by tracetool, do not edit. */' @@ -601,8 +605,9 @@ def main(): try: opts, args = getopt.getopt(sys.argv[1:], "", long_options) except getopt.GetoptError, err: -# print help information and exit: -print str(err) # will print something like "option -a not recognized" +# print help information and exit +# will print something like "option -a not recognized" +error_write(str(err)+"\n") usage() sys.exit(2) for opt, arg in opts: @@ -631,12 +636,10 @@ def main(): usage() if format_ not in _formats: -print "Unknown format: %s" % format_ -print +error_write("Unknown format: %s\n\n" % format_) usage() if backend not in _backends: -print "Unknown backend: %s" % backend -print +error_write("Unknown backend: %s\n\n" % backend) usage() events = read_events(sys.stdin)
[Qemu-devel] [PATCH 10/28] usb-uhci: switch to usb_find_device()
Switch over UHCI to use the new usb_find_device() function for device lookup. Signed-off-by: Gerd Hoffmann --- hw/usb-uhci.c | 45 +++-- 1 files changed, 15 insertions(+), 30 deletions(-) diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 407e0f3..a1f597a 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -94,15 +94,6 @@ static const char *pid2str(int pid) #define DPRINTF(...) #endif -#ifdef DEBUG_DUMP_DATA -static void dump_data(USBPacket *p, int ret) -{ -iov_hexdump(p->iov.iov, p->iov.niov, stderr, "uhci", ret); -} -#else -static void dump_data(USBPacket *p, int ret) {} -#endif - typedef struct UHCIState UHCIState; /* @@ -643,30 +634,22 @@ static void uhci_wakeup(USBPort *port1) } } -static int uhci_broadcast_packet(UHCIState *s, USBPacket *p) +static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr) { -int i, ret; - -DPRINTF("uhci: packet enter. pid %s addr 0x%02x ep %d len %zd\n", - pid2str(p->pid), p->devaddr, p->devep, p->iov.size); -if (p->pid == USB_TOKEN_OUT || p->pid == USB_TOKEN_SETUP) -dump_data(p, 0); +USBDevice *dev; +int i; -ret = USB_RET_NODEV; -for (i = 0; i < NB_PORTS && ret == USB_RET_NODEV; i++) { +for (i = 0; i < NB_PORTS; i++) { UHCIPort *port = &s->ports[i]; -USBDevice *dev = port->port.dev; - -if (dev && dev->attached && (port->ctrl & UHCI_PORT_EN)) { -ret = usb_handle_packet(dev, p); +if (!(port->ctrl & UHCI_PORT_EN)) { +continue; +} +dev = usb_find_device(&port->port, addr); +if (dev != NULL) { +return dev; } } - -DPRINTF("uhci: packet exit. ret %d len %zd\n", ret, p->iov.size); -if (p->pid == USB_TOKEN_IN && ret > 0) -dump_data(p, ret); - -return ret; +return NULL; } static void uhci_async_complete(USBPort *port, USBPacket *packet); @@ -830,13 +813,15 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in switch(pid) { case USB_TOKEN_OUT: case USB_TOKEN_SETUP: -len = uhci_broadcast_packet(s, &async->packet); +len = usb_handle_packet(uhci_find_device(s, async->packet.devaddr), +&async->packet); if (len >= 0) len = max_len; break; case USB_TOKEN_IN: -len = uhci_broadcast_packet(s, &async->packet); +len = usb_handle_packet(uhci_find_device(s, async->packet.devaddr), +&async->packet); break; default: -- 1.7.1
[Qemu-devel] [PATCH 7/9] net: remove extra spaces in help messages
From: Benjamin MARSILI Signed-off-by: Benjamin MARSILI Signed-off-by: Stefan Hajnoczi --- net/socket.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/socket.c b/net/socket.c index d4c2002..0bcf229 100644 --- a/net/socket.c +++ b/net/socket.c @@ -664,8 +664,8 @@ int net_init_socket(QemuOpts *opts, qemu_opt_get(opts, "connect") || qemu_opt_get(opts, "listen") || qemu_opt_get(opts, "mcast")) { -error_report("fd=, connect=, listen=\ - and mcast= is invalid with udp="); +error_report("fd=, connect=, listen=" + " and mcast= is invalid with udp="); return -1; } @@ -680,8 +680,8 @@ int net_init_socket(QemuOpts *opts, return -1; } } else { -error_report("-socket requires fd=, listen=, \ - connect=, mcast= or udp="); +error_report("-socket requires fd=, listen=," + " connect=, mcast= or udp="); return -1; } return 0; -- 1.7.8.3