[Qemu-devel] [PATCH uq/master 2/2] MCE, unpoison memory address across reboot
In Linux kernel HWPoison processing implementation, the virtual address in processes mapping the error physical memory page is marked as HWPoison. So that, the further accessing to the virtual address will kill corresponding processes with SIGBUS. If the error physical memory page is used by a KVM guest, the SIGBUS will be sent to QEMU, and QEMU will simulate a MCE to report that memory error to the guest OS. If the guest OS can not recover from the error (for example, the page is accessed by kernel code), guest OS will reboot the system. But because the underlying host virtual address backing the guest physical memory is still poisoned, if the guest system accesses the corresponding guest physical memory even after rebooting, the SIGBUS will still be sent to QEMU and MCE will be simulated. That is, guest system can not recover via rebooting. In fact, across rebooting, the contents of guest physical memory page need not to be kept. We can allocate a new host physical page to back the corresponding guest physical address. This patch fixes this issue in QEMU via calling qemu_ram_remap() to clear the corresponding page table entry, so that make it possible to allocate a new page to recover the issue. Signed-off-by: Huang Ying ying.hu...@intel.com --- kvm.h |2 ++ target-i386/kvm.c | 39 +++ 2 files changed, 41 insertions(+) --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -580,6 +580,42 @@ static int kvm_get_supported_msrs(void) return ret; } +struct HWPoisonPage; +typedef struct HWPoisonPage HWPoisonPage; +struct HWPoisonPage +{ +ram_addr_t ram_addr; +QLIST_ENTRY(HWPoisonPage) list; +}; + +static QLIST_HEAD(hwpoison_page_list, HWPoisonPage) hwpoison_page_list = +QLIST_HEAD_INITIALIZER(hwpoison_page_list); + +void kvm_unpoison_all(void *param) +{ +HWPoisonPage *page, *next_page; + +QLIST_FOREACH_SAFE(page, hwpoison_page_list, list, next_page) { +QLIST_REMOVE(page, list); +qemu_ram_remap(page-ram_addr, TARGET_PAGE_SIZE); +qemu_free(page); +} +} + +static void kvm_hwpoison_page_add(ram_addr_t ram_addr) +{ +HWPoisonPage *page; + +QLIST_FOREACH(page, hwpoison_page_list, list) { +if (page-ram_addr == ram_addr) +return; +} + +page = qemu_malloc(sizeof(HWPoisonPage)); +page-ram_addr = ram_addr; +QLIST_INSERT_HEAD(hwpoison_page_list, page, list); +} + int kvm_arch_init(void) { uint64_t identity_base = 0xfffbc000; @@ -632,6 +668,7 @@ int kvm_arch_init(void) fprintf(stderr, e820_add_entry() table is full\n); return ret; } +qemu_register_reset(kvm_unpoison_all, NULL); return 0; } @@ -1940,6 +1977,7 @@ int kvm_on_sigbus_vcpu(CPUState *env, in hardware_memory_error(); } } +kvm_hwpoison_page_add(ram_addr); if (code == BUS_MCEERR_AR) { /* Fake an Intel architectural Data Load SRAR UCR */ @@ -1984,6 +2022,7 @@ int kvm_on_sigbus(int code, void *addr) QEMU itself instead of guest system!: %p\n, addr); return 0; } +kvm_hwpoison_page_add(ram_addr); kvm_mce_inj_srao_memscrub2(first_cpu, paddr); } else #endif --- a/kvm.h +++ b/kvm.h @@ -188,6 +188,8 @@ int kvm_physical_memory_addr_from_ram(ra target_phys_addr_t *phys_addr); #endif +void kvm_unpoison_all(void *param); + #endif int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign);
[Qemu-devel] [PATCH uq/master 1/2] Add qemu_ram_remap
qemu_ram_remap() unmaps the specified RAM pages, then re-maps these pages again. This is used by KVM HWPoison support to clear HWPoisoned page tables across guest rebooting, so that a new page may be allocated later to recover the memory error. Signed-off-by: Huang Ying ying.hu...@intel.com --- cpu-all.h|4 +++ cpu-common.h |1 exec.c | 61 ++- 3 files changed, 65 insertions(+), 1 deletion(-) --- a/cpu-all.h +++ b/cpu-all.h @@ -863,10 +863,14 @@ target_phys_addr_t cpu_get_phys_page_deb extern int phys_ram_fd; extern ram_addr_t ram_size; +/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */ +#define RAM_PREALLOC_MASK (1 0) + typedef struct RAMBlock { uint8_t *host; ram_addr_t offset; ram_addr_t length; +uint32_t flags; char idstr[256]; QLIST_ENTRY(RAMBlock) next; #if defined(__linux__) !defined(TARGET_S390X) --- a/exec.c +++ b/exec.c @@ -2830,6 +2830,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(Devic if (host) { new_block-host = host; +new_block-flags |= RAM_PREALLOC_MASK; } else { if (mem_path) { #if defined (__linux__) !defined(TARGET_S390X) @@ -2883,7 +2884,9 @@ void qemu_ram_free(ram_addr_t addr) QLIST_FOREACH(block, ram_list.blocks, next) { if (addr == block-offset) { QLIST_REMOVE(block, next); -if (mem_path) { +if (block-flags RAM_PREALLOC_MASK) +; +else if (mem_path) { #if defined (__linux__) !defined(TARGET_S390X) if (block-fd) { munmap(block-host, block-length); @@ -2906,6 +2909,62 @@ void qemu_ram_free(ram_addr_t addr) } +void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) +{ +RAMBlock *block; +ram_addr_t offset; +int flags; +void *area, *vaddr; + +QLIST_FOREACH(block, ram_list.blocks, next) { +offset = addr - block-offset; +if (offset block-length) { +vaddr = block-host + offset; +if (block-flags RAM_PREALLOC_MASK) { +; +} else { +flags = MAP_FIXED; +munmap(vaddr, length); +if (mem_path) { +#if defined (__linux__) !defined(TARGET_S390X) +if (block-fd) { +#ifdef MAP_POPULATE +flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED : +MAP_PRIVATE; +#else +flags |= MAP_PRIVATE; +#endif +area = mmap(vaddr, length, PROT_READ | PROT_WRITE, +flags, block-fd, offset); +} else { +flags |= MAP_PRIVATE | MAP_ANONYMOUS; +area = mmap(vaddr, length, PROT_READ | PROT_WRITE, +flags, -1, 0); +} +#endif +} else { +#if defined(TARGET_S390X) defined(CONFIG_KVM) +flags |= MAP_SHARED | MAP_ANONYMOUS; +area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE, +flags, -1, 0); +#else +flags |= MAP_PRIVATE | MAP_ANONYMOUS; +area = mmap(vaddr, length, PROT_READ | PROT_WRITE, +flags, -1, 0); +#endif +} +if (area != vaddr) { +fprintf(stderr, Could not remap addr: %lx@%lx\n, +length, addr); +exit(1); +} +qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE); +} +return; +} +} +} + /* Return a host pointer to ram allocated with qemu_ram_alloc. With the exception of the softmmu code in this file, this should only be used for local memory (e.g. video ram) that the device owns, --- a/cpu-common.h +++ b/cpu-common.h @@ -50,6 +50,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(Devic ram_addr_t size, void *host); ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size); void qemu_ram_free(ram_addr_t addr); +void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); /* This should only be used for ram local to a device. */ void *qemu_get_ram_ptr(ram_addr_t addr); /* Same but slower, to use for migration, where the order of
Re: [Qemu-devel] spicevmv chardev, guest agents and paravirtual mouse
Hi, There isn't much spice-specific stuff in there. The clipboard bits for example should work unmodified with vnc, one would just have to hack up a vnc extention to tunnel the agent protocol over vnc (and vnc client support of course). VNC already supports copy/paste as part of the protocol so can the agent protocol be terminated in QEMU such that the server can make use of the standard protocol extensions? Should be doable too, didn't look at the vnc extension in detail though. Also related: paravirtual mouse. I'd suggest to go for something new, based on virtio-serial, doing just the mouse and nothing else. I'd agree. I think we want something that actually terminates in the kernel for Linux guests since then we can expose it as an evdev device. No special X driver would be needed. Doesn't have to terminate in the kernel, you can feed the linux input subsystem via uinput (vdagent-linux actually does that btw.), X will get the events via evdev and everything works fine in the singlehead case. I think you need a X driver to handle multihead though. Is this something that makes sense for Spice in the future? Yes. Supporting multihead is a requirement for spice though. Having the initial implementation not support it would be fine, but we need at least a plan how to handle this case. For instance, Spice makes use of a 1-off protocol whereas something like virt-agent uses an established RPC protocol (XML-RPC). I'm not tied to using any particular protocol, but I think it's very important to use a standardized, well specified protocol. If that is a hard requirement it means we'll have to design something new for the agent, take care that it fulfills the spice requirements, then switch over for new deployments. Of course we'll have to maintain current vdagent for backward compatibility. Depending on the design we might be able to translate between the current vdagent and new agent protocol. Being able to do that would be quite helpful for the transition of course. cheers, Gerd
Re: [Qemu-devel] tcg shift ops and magnitudes larger than register size
On Wed, Jan 12, 2011 at 08:13:45PM -0500, Mike Frysinger wrote: are there any rules with the tcg sar/shl/shr ops and their magnitudes ? such as magnitudes cannot be larger than the register size ? Yes, the result is undefined in those cases. i have a 32bit register with the value of 0x1230002 and when i attempt to do a sari with a value =32, it gives me 0x918001 (a single shift right has been done). i would have expected the value to be 0 (as that is what my architecture does). You need to handle it in the translator. CRIS has similar semantics as your arch. See target-cris/translate.c:t_gen_lsl() for one way of doing it. There might be better ways though. Cheers
[Qemu-devel] Re: [PATCH v2] Avoid divide by zero when there is no block device to migrate
Am 12.01.2011 14:41, schrieb Pierre Riteau: When block migration is requested and no read-write block device is present, a divide by zero exception is triggered because total_sector_sum equals zero. Signed-off-by: Pierre Riteau pierre.rit...@irisa.fr --- This v2 fixes a line that was going beyond 80 characters. Thanks, applied to the block branch. Kevin
Re: [Spice-devel] [Qemu-devel] spicevmv chardev, guest agents and paravirtual mouse
Hi, The VDAgentMouseState messages have one problem: They send the pointer position as-is, which introduces a dependency on the screen size. Yeah, if we could get rid of that, that would be great. We could even introduce a new mouse message type to the existing spice vdagent protocol and use capabilities to switch between the 2. I'd rather go straight to the paravirtual mouse. spice can use both vdagent and usual qemu input devices such as usb tablet to route mouse events, so the switchover should be relatively painless and also completely independent from the agent design. cheers, Gerd
Re: [Qemu-devel] [PATCH] Close Gdb stub connection in gdb_exit
On 01/04/2011 11:27 AM, Fabien Chouteau wrote: On Windows, this is required to flush the remaining data in the IO stream, otherwise Gdb do not receive the last packet. Signed-off-by: Fabien Chouteauchout...@adacore.com --- gdbstub.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 0aa081b..dac3ce6 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -2391,6 +2391,10 @@ void gdb_exit(CPUState *env, int code) snprintf(buf, sizeof(buf), W%02x, (uint8_t)code); put_packet(s, buf); + + if (s-chr) { + qemu_chr_close(s-chr); + } } #ifdef CONFIG_USER_ONLY Any comment on this patch? -- Fabien Chouteau
Re: [Spice-devel] [Qemu-devel] spicevmv chardev, guest agents and paravirtual mouse
Hi, The VDAgentMouseState messages have one problem: They send the pointer position as-is, which introduces a dependency on the screen size. Yeah, if we could get rid of that, that would be great. We could even introduce a new mouse message type to the existing spice vdagent protocol and use capabilities to switch between the 2. I think the typical trick is to scale the coordinates to some large resolution. Would there be any issue doing this in vdagent today? No. The vdagent actually registers a uinput device with the size matching the screen resolution today. It could also register a tablet with a -- say -- 65536 x 65536 resolution and scale. Even better would be to let spice-server or qemu do the scaling and feed vdagent/pvmouse with already scaled coordinates, so the vdagent doesn't has to hop through the loops Hans described to get the screen resolution coordinates. qemu already uses a 0 - 0x range internally for absolute input coordinates, the pvmouse (or should we better name it pvtablet?) should probably pass those values as-is to the guest. cheers, Gerd
[Qemu-devel] Re: [PATCH uq/master 2/2] MCE, unpoison memory address across reboot
Am 13.01.2011 09:34, Huang Ying wrote: In Linux kernel HWPoison processing implementation, the virtual address in processes mapping the error physical memory page is marked as HWPoison. So that, the further accessing to the virtual address will kill corresponding processes with SIGBUS. If the error physical memory page is used by a KVM guest, the SIGBUS will be sent to QEMU, and QEMU will simulate a MCE to report that memory error to the guest OS. If the guest OS can not recover from the error (for example, the page is accessed by kernel code), guest OS will reboot the system. But because the underlying host virtual address backing the guest physical memory is still poisoned, if the guest system accesses the corresponding guest physical memory even after rebooting, the SIGBUS will still be sent to QEMU and MCE will be simulated. That is, guest system can not recover via rebooting. In fact, across rebooting, the contents of guest physical memory page need not to be kept. We can allocate a new host physical page to back the corresponding guest physical address. This patch fixes this issue in QEMU via calling qemu_ram_remap() to clear the corresponding page table entry, so that make it possible to allocate a new page to recover the issue. Signed-off-by: Huang Ying ying.hu...@intel.com --- kvm.h |2 ++ target-i386/kvm.c | 39 +++ 2 files changed, 41 insertions(+) --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -580,6 +580,42 @@ static int kvm_get_supported_msrs(void) return ret; } +struct HWPoisonPage; +typedef struct HWPoisonPage HWPoisonPage; +struct HWPoisonPage +{ +ram_addr_t ram_addr; +QLIST_ENTRY(HWPoisonPage) list; +}; + +static QLIST_HEAD(hwpoison_page_list, HWPoisonPage) hwpoison_page_list = +QLIST_HEAD_INITIALIZER(hwpoison_page_list); + +void kvm_unpoison_all(void *param) Minor nit: This can be static now. +{ +HWPoisonPage *page, *next_page; + +QLIST_FOREACH_SAFE(page, hwpoison_page_list, list, next_page) { +QLIST_REMOVE(page, list); +qemu_ram_remap(page-ram_addr, TARGET_PAGE_SIZE); +qemu_free(page); +} +} + +static void kvm_hwpoison_page_add(ram_addr_t ram_addr) +{ +HWPoisonPage *page; + +QLIST_FOREACH(page, hwpoison_page_list, list) { +if (page-ram_addr == ram_addr) +return; +} + +page = qemu_malloc(sizeof(HWPoisonPage)); +page-ram_addr = ram_addr; +QLIST_INSERT_HEAD(hwpoison_page_list, page, list); +} + int kvm_arch_init(void) { uint64_t identity_base = 0xfffbc000; @@ -632,6 +668,7 @@ int kvm_arch_init(void) fprintf(stderr, e820_add_entry() table is full\n); return ret; } +qemu_register_reset(kvm_unpoison_all, NULL); return 0; } @@ -1940,6 +1977,7 @@ int kvm_on_sigbus_vcpu(CPUState *env, in hardware_memory_error(); } } +kvm_hwpoison_page_add(ram_addr); if (code == BUS_MCEERR_AR) { /* Fake an Intel architectural Data Load SRAR UCR */ @@ -1984,6 +2022,7 @@ int kvm_on_sigbus(int code, void *addr) QEMU itself instead of guest system!: %p\n, addr); return 0; } +kvm_hwpoison_page_add(ram_addr); kvm_mce_inj_srao_memscrub2(first_cpu, paddr); } else #endif --- a/kvm.h +++ b/kvm.h @@ -188,6 +188,8 @@ int kvm_physical_memory_addr_from_ram(ra target_phys_addr_t *phys_addr); #endif +void kvm_unpoison_all(void *param); + To be removed if kvm_unpoison_all is static. #endif int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign); As indicated, I'm sitting on lots of fixes and refactorings of the MCE user space code. How do you test your patches? Any suggestions how to do this efficiently would be warmly welcome. Thanks, Jan -- Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
Re: [Qemu-devel] [PATCH 0/8] misc cleanups for x86_64 disabling config settings
How about creating stub functions instead of #ifdefs? something like pc-stubs.c #ifndef CONFIG_VMWARE_VGA pci_vmsvga_init() { error ... } #endif #ifndef CONFIG_... ... On Wed, Jan 12, 2011 at 11:34:29PM -0700, David Ahern wrote: David Ahern (8): fix 'no such file' error from make_device_config.sh x86_64 config: fix compile for CONFIG_VMWARE_VGA=n x86_64 config: fix compile for CONFIG_PARALLEL=n remove unused parallel_* variables from pc.c x86_64 config: fix compile for CONFIG_NE2000_ISA=n x86_64 config: fix compile for CONFIG_VGA_ISA=n x86_64 config: fix compile for CONFIG_IDE_ISA=n x86_64 config: fix compile for CONFIG_FDC=n hw/pc.c | 21 ++--- hw/pc_piix.c | 11 +++ make_device_config.sh |2 +- 3 files changed, 30 insertions(+), 4 deletions(-) -- 1.7.3.4 -- yamahata
Re: [Qemu-devel] Linux as VirtualBox quest OS with QEMU running Solaris
On 13 January 2011 00:34, Mateusz Loskot mate...@loskot.net wrote: On 12/01/11 17:15, Mateusz Loskot wrote: On 12/01/11 16:48, Michal Suchanek wrote: On 12 January 2011 16:21, Mateusz Loskotmate...@loskot.net wrote: Thinking of future, could anyone estimate when it will be possible to boot Solaris 10 installation from ISO disks, if at all? To summary, what OS alternative for SPARC we have got apart from Debian which are known to work under QEMU? *BSD systems? I can run NetBSD sparc install CD just fine. It supports sparc32 in the latest release. Thanks. Great, I'll try. One of the problems I found with Debian Etch is the package repositories are no longer supported and the installer can easily mess with those for Lenny. The only solution is to have all CDs for Etch available and run complete offline installation. I guess the NetBSD option is more up to date here. I have tried the recent NetBSD and it boots without problems, however I can't configure networking to install via FTP/HTTP. Strangely, I don't get question about DHCP. Yes, that's probably an issue with the sparc installer script. However, the sparccd has all the sets so you can easily install from the CD. Once installed you can set up dhclient. HTH Michal
[Qemu-devel] paravirtual mouse/tablet
Hi, Just throwing a quick writeup into the ring to kickstart the design discussion ;) cheers, Gerd #ifndef __QEMU_PVTABLET__ #define __QEMU_PVTABLET__ 1 /* * qemu patavirtual tablet interface */ #include inttypes.h /* our virtio-serial channel */ #define QEMU_PVTABLET_NAME org.qemu.pvtablet.0 enum qemu_pvtablet_buttons { QEMU_PVTABLET_BTN_LEFT, QEMU_PVTABLET_BTN_RIGHT, QEMU_PVTABLET_BTN_MIDDLE, /* * we can handle up to 32 buttons although * not every has a individual name ;) */ }; /* send button down+up events */ typedef struct qemu_pvtablet_button { uint32_t button; uint32_t mask; } qemu_pvtablet_button; /* send pointer move events */ typedef struct qemu_pvtablet_position { uint32_t pos_x; /* range: 0 - 0x */ uint32_t pos_y; /* range: 0 - 0x */ } qemu_pvtablet_position; /* * specify which display all following events refering to * (for multihead setups). */ typedef struct qemu_pvtablet_display { /* * FIXME: spice just uses the display channel number, but that * doesn't fly in general ... */ uint32_t spice_display_channel; } qemu_pvtablet_display; enum qemu_pvtablet_type { QEMU_PVTABLET_MSG_MOVE, /* qemu_pvtablet_position */ QEMU_PVTABLET_MSG_BTN_DOWN, /* qemu_pvtablet_button */ QEMU_PVTABLET_MSG_BTN_UP, /* qemu_pvtablet_button */ QEMU_PVTABLET_MSG_DISPLAY, /* qemu_pvtablet_display */ }; typedef struct qemu_pvtablet_message { uint32_t size;/* whole message size */ uint32_t type;/* qemu_pvtablet_type */ uint64_t tv_secs; uint64_t tv_usecs; union { qemu_pvtablet_position position; qemu_pvtablet_button button; qemu_pvtablet_display display; } m; } qemu_pvtablet_message; #endif /* __QEMU_PVTABLET__ */
[Qemu-devel] Re: [Spice-devel] spicevmv chardev, guest agents and paravirtual mouse
Am Mittwoch, den 12.01.2011, 17:12 +0100 schrieb Gerd Hoffmann: Hi folks, Looks like the spicevmc patch kicked the guest qagent discussion, so lets start with this, although it isn't related much to the agent issue itself ... The spicevmc chardev just pipes data from a chardev user within qemu to libspice and adds a type tag to it so libspice knows now to wind up the other end. There are several types: (1) vdagent, the spice guest agent. Will discuss this in detail below. (2) smartcard, this basically pipes the smartcard protocol over spice. Patches for smartcard support are on the list and should be almost ready for merge now. If you want connect a remote smart card reader to your guest you can use a tcp chardev, which will build a data pipeline like this: ccid-passthrough - tcp chardev - tcp protocol - vcsclient - libcacard Or you can use the spicevmc chardev to use spice as transport: ccid-passthrough - spicevmc chardev - spice protocol - spice client - libcacard If someone comes up with a vnc extention one could create something simliar for vnc tunneling: ccid-passthrough - vnctunnel chardev - vnc protocol - gtk-vnc widget - libcacard (3) usb forwarding. Hans is busy with this. No working code yet. Will probably work pretty simliar to smartcard. (4) termial forwarding. Just an idea right now. Nowdays that the spice client side moves to gtk it would be easy to embed a termial widget, therby allowing easy access to the serial console using something like this: -chardev spicevmc,id=console,type=terminal -device isa-serial,index=0,chardev=console I guess this could be used to get more info about the state of a VM from the host system (like system is ready, system is rebooting, etc), although it needs some adjustments in the guest to use the serial console and string parsing on the host. Would it therefore make sense to have a another type to get such status messages from the guest and have a list of states defined somewhere? If yes, is this something which should be implemented in the spice-part or is this general qemu stuff? Furthermore it would be nice if the client side could get a list of display resolutions supported in the guest and having the possibility to change the resolution when resizing the guest window. The vdagent protocol already has a message to pass this info but it only sends it when going into fullscreen mode. Yet another use case would be: authentication forwarding/injection to the guest OS. With smartcard-support you have something like that, but in our case we have the users authenticate against our management backend first before they get access to a VM and it would be kind of nice to be able to inject authentication data into the guest OS, either via the spice client or coming from the host OS. Cheers, Tiziano
Re: [Qemu-devel] [PATCHv1] slirp: Use strcasecmp() to check tftp mode, tsize
On Wed, Jan 12, 2011 at 03:57:18PM +0200, Sergei Gavrikov wrote: From: Sergei Gavrikov sergei.gavri...@gmail.com According to RFC 1350 (TFTP Revision 2) the mode field can contain any combination of upper and lower case; also RFC 2349 propagates that the transfer size option (tsize) is case in-sensitive too. Current implementation of embedded TFTP server missed that what does mess some TFTP clients. Fixed by using STRCASECMP(3) in the required places. Signed-off-by: Sergei Gavrikov sergei.gavri...@gmail.com Reviewed-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com I've applied this, thanks both of you. Cheers --- slirp/tftp.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/slirp/tftp.c b/slirp/tftp.c index 55e4692..1821648 100644 --- a/slirp/tftp.c +++ b/slirp/tftp.c @@ -311,7 +311,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) return; } - if (memcmp(tp-x.tp_buf[k], octet\0, 6) != 0) { + if (strcasecmp((const char *)tp-x.tp_buf[k], octet) != 0) { tftp_send_error(spt, 4, Unsupported transfer mode, tp); return; } @@ -351,7 +351,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) value = (const char *)tp-x.tp_buf[k]; k += strlen(value) + 1; - if (strcmp(key, tsize) == 0) { + if (strcasecmp(key, tsize) == 0) { int tsize = atoi(value); struct stat stat_p;
[Qemu-devel] Re: [Spice-devel] spicevmv chardev, guest agents and paravirtual mouse
Hi, (4) termial forwarding. Just an idea right now. Nowdays that the spice client side moves to gtk it would be easy to embed a termial widget, therby allowing easy access to the serial console using something like this: -chardev spicevmc,id=console,type=terminal -device isa-serial,index=0,chardev=console I guess this could be used to get more info about the state of a VM from the host system (like system is ready, system is rebooting, etc), although it needs some adjustments in the guest to use the serial console and string parsing on the host. That is really just for a terminal / serial console. Running an guest agent protocol over a serial line instead of virtio-serial would be possible too, but that end would probably better handled by libvirt or some other management tool. Would it therefore make sense to have a another type to get such status messages from the guest and have a list of states defined somewhere? If yes, is this something which should be implemented in the spice-part or is this general qemu stuff? It is general qemu stuff and how to design that best is the whole point of this agent discussion ;) Furthermore it would be nice if the client side could get a list of display resolutions supported in the guest and having the possibility to change the resolution when resizing the guest window. The vdagent protocol already has a message to pass this info but it only sends it when going into fullscreen mode. That is just a client implementation thing. The new spice-gtk client can send messages on window resize too. Guest is supposed to pick the closest resolution it can handle. Yet another use case would be: authentication forwarding/injection to the guest OS. With smartcard-support you have something like that, but in our case we have the users authenticate against our management backend first before they get access to a VM and it would be kind of nice to be able to inject authentication data into the guest OS, either via the spice client or coming from the host OS. Depends on the auth infrastructure whenever this is doable I guess. If you are using x509 certificates the smartcard support should serve just fine. I can also imagine that the guest can aquire kerberos tickets via spice-client or using some other agent for example (don't know kerberos good enougth to be sure though). cheers, Gerd
[Qemu-devel] Re: [Spice-devel] paravirtual mouse/tablet
Can you elaborate how the spice display channel comes into play? On a physical machine you just have input devices with no notion of display. It's up to the windowing system to process input events and handle multihead. Why does a pv tablet tie itself to a display channel? What about mouse wheel (aka z axis motion)? Stefan
Re: [Qemu-devel] [PATCH] Close Gdb stub connection in gdb_exit
On Thu, Jan 13, 2011 at 10:24:50AM +0100, Fabien Chouteau wrote: On 01/04/2011 11:27 AM, Fabien Chouteau wrote: On Windows, this is required to flush the remaining data in the IO stream, otherwise Gdb do not receive the last packet. Signed-off-by: Fabien Chouteauchout...@adacore.com --- gdbstub.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 0aa081b..dac3ce6 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -2391,6 +2391,10 @@ void gdb_exit(CPUState *env, int code) snprintf(buf, sizeof(buf), W%02x, (uint8_t)code); put_packet(s, buf); + + if (s-chr) { + qemu_chr_close(s-chr); + } } #ifdef CONFIG_USER_ONLY Any comment on this patch? Yes, sorry for the delays. This patch breaks the linux-user build. Cheers
[Qemu-devel] Re: [PATCH uq/master 2/2] MCE, unpoison memory address across reboot
Am 13.01.2011 09:34, Huang Ying wrote: In Linux kernel HWPoison processing implementation, the virtual address in processes mapping the error physical memory page is marked as HWPoison. So that, the further accessing to the virtual address will kill corresponding processes with SIGBUS. If the error physical memory page is used by a KVM guest, the SIGBUS will be sent to QEMU, and QEMU will simulate a MCE to report that memory error to the guest OS. If the guest OS can not recover from the error (for example, the page is accessed by kernel code), guest OS will reboot the system. But because the underlying host virtual address backing the guest physical memory is still poisoned, if the guest system accesses the corresponding guest physical memory even after rebooting, the SIGBUS will still be sent to QEMU and MCE will be simulated. That is, guest system can not recover via rebooting. In fact, across rebooting, the contents of guest physical memory page need not to be kept. We can allocate a new host physical page to back the corresponding guest physical address. This patch fixes this issue in QEMU via calling qemu_ram_remap() to clear the corresponding page table entry, so that make it possible to allocate a new page to recover the issue. Signed-off-by: Huang Ying ying.hu...@intel.com --- kvm.h |2 ++ target-i386/kvm.c | 39 +++ 2 files changed, 41 insertions(+) --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -580,6 +580,42 @@ static int kvm_get_supported_msrs(void) return ret; } +struct HWPoisonPage; +typedef struct HWPoisonPage HWPoisonPage; +struct HWPoisonPage +{ +ram_addr_t ram_addr; +QLIST_ENTRY(HWPoisonPage) list; +}; + +static QLIST_HEAD(hwpoison_page_list, HWPoisonPage) hwpoison_page_list = +QLIST_HEAD_INITIALIZER(hwpoison_page_list); + +void kvm_unpoison_all(void *param) Minor nit: This can be static now. +{ +HWPoisonPage *page, *next_page; + +QLIST_FOREACH_SAFE(page, hwpoison_page_list, list, next_page) { +QLIST_REMOVE(page, list); +qemu_ram_remap(page-ram_addr, TARGET_PAGE_SIZE); +qemu_free(page); +} +} + +static void kvm_hwpoison_page_add(ram_addr_t ram_addr) +{ +HWPoisonPage *page; + +QLIST_FOREACH(page, hwpoison_page_list, list) { +if (page-ram_addr == ram_addr) +return; +} + +page = qemu_malloc(sizeof(HWPoisonPage)); +page-ram_addr = ram_addr; +QLIST_INSERT_HEAD(hwpoison_page_list, page, list); +} + int kvm_arch_init(void) { uint64_t identity_base = 0xfffbc000; @@ -632,6 +668,7 @@ int kvm_arch_init(void) fprintf(stderr, e820_add_entry() table is full\n); return ret; } +qemu_register_reset(kvm_unpoison_all, NULL); return 0; } @@ -1940,6 +1977,7 @@ int kvm_on_sigbus_vcpu(CPUState *env, in hardware_memory_error(); } } +kvm_hwpoison_page_add(ram_addr); if (code == BUS_MCEERR_AR) { /* Fake an Intel architectural Data Load SRAR UCR */ @@ -1984,6 +2022,7 @@ int kvm_on_sigbus(int code, void *addr) QEMU itself instead of guest system!: %p\n, addr); return 0; } +kvm_hwpoison_page_add(ram_addr); kvm_mce_inj_srao_memscrub2(first_cpu, paddr); } else #endif --- a/kvm.h +++ b/kvm.h @@ -188,6 +188,8 @@ int kvm_physical_memory_addr_from_ram(ra target_phys_addr_t *phys_addr); #endif +void kvm_unpoison_all(void *param); + To be removed if kvm_unpoison_all is static. #endif int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign); As indicated, I'm sitting on lots of fixes and refactorings of the MCE user space code. How do you test your patches? Any suggestions how to do this efficiently would be warmly welcome. Thanks, Jan -- Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
Re: [Qemu-devel] [PATCH] Close Gdb stub connection in gdb_exit
On 01/13/2011 12:01 PM, Edgar E. Iglesias wrote: On Thu, Jan 13, 2011 at 10:24:50AM +0100, Fabien Chouteau wrote: On 01/04/2011 11:27 AM, Fabien Chouteau wrote: On Windows, this is required to flush the remaining data in the IO stream, otherwise Gdb do not receive the last packet. Signed-off-by: Fabien Chouteauchout...@adacore.com --- gdbstub.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 0aa081b..dac3ce6 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -2391,6 +2391,10 @@ void gdb_exit(CPUState *env, int code) snprintf(buf, sizeof(buf), W%02x, (uint8_t)code); put_packet(s, buf); + + if (s-chr) { + qemu_chr_close(s-chr); + } } #ifdef CONFIG_USER_ONLY Any comment on this patch? Yes, sorry for the delays. This patch breaks the linux-user build. thanks, I'll send new version in a minute. -- Fabien Chouteau
[Qemu-devel] [PATCH v2] gdbstub: Close connection in gdb_exit
On Windows, this is required to flush the remaining data in the IO stream, otherwise Gdb do not receive the last packet. Version 2: Fix linux-user build error. Signed-off-by: Fabien Chouteau chout...@adacore.com --- gdbstub.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 0aa081b..d6556c9 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -2391,6 +2391,12 @@ void gdb_exit(CPUState *env, int code) snprintf(buf, sizeof(buf), W%02x, (uint8_t)code); put_packet(s, buf); + +#ifndef CONFIG_USER_ONLY + if (s-chr) { + qemu_chr_close(s-chr); + } +#endif } #ifdef CONFIG_USER_ONLY -- 1.7.1
[Qemu-devel] Re: [Spice-devel] paravirtual mouse/tablet
On 01/13/11 12:01, Stefan Hajnoczi wrote: Can you elaborate how the spice display channel comes into play? On a physical machine you just have input devices with no notion of display. It's up to the windowing system to process input events and handle multihead. Why does a pv tablet tie itself to a display channel? You have two qxl devices, each linked to a spice display channel. The spice client will open one window for each channel. The mouse position is a triple consisting of (x, y, window/channel). Only the guest knows how it configured the displays, so only the guest is able to create a correct pointer position out of this data. So the X-Server would combine this data with its virtual display configuration (basically adding the display offset to the coordinates), then send this as event to the X clients. What about mouse wheel (aka z axis motion)? It's covered. That are really just button presses at mouse protocol level (buttons 4+5). We can add them to the enum to have fancy names for them, that is just the sugar on top though. cheers, Gerd
Re: [Qemu-devel] [PATCH v2 1/4] pci: allow devices being tagged as not hotpluggable.
@@ -1620,6 +1620,11 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base) info-is_bridge); if (pci_dev == NULL) return -1; +if (qdev-hotplugged info-no_hotplug) { +qerror_report(QERR_DEVICE_NO_HOTPLUG, info-qdev.name); +do_pci_unregister_device(pci_dev); +return -1; +} Any particular reason for not check this before do_pci_register_device()? Don't remember, probably not. I think can could be moved up (and loose the unregister call) and behavior will not change. cheers, Gerd
[Qemu-devel] [PATCH 00/12] Threadlets Infrastructure.
Hi, This series implements threadlets infrastructure: Changelog: * Changed the name aio_thread to handle_work. * Corrected the usage of aiocb-ret which has to be accessed under aiocb_mutex. * Merged the patche which add dequeue_work with the patch which removes the unused active field in paio structure so that the logic of paio_cancel is not broken. Here are the details regarding the testing that has been carried out on the patchset: * kvm-autotest run with guest running fedora 14. The following tests were run successfully: disktest, bonnie, fsstress, blast, ffsb. * bonnie test run on fedora guest on block device. * iozone -l test run on fedora guest to stress the posix-aio-compat.c code. (suggested by Stefan) * windows guest installation test and iozone -l test run on windows guest. The following series implements... --- Arun R Bharadwaj (12): Add aiocb_mutex and aiocb_completion. Introduce work concept in posix-aio-compat.c Add callback function to ThreadletWork structure. Add ThreadletQueue. Threadlet: Add submit_work threadlet API. Threadlet: Add dequeue_work threadlet API and remove active field. Remove thread_create routine. Threadlet: Add aio_signal_handler threadlet API Remove all instances of CONFIG_THREAD Move threadlet code to qemu-threadlets.c Threadlets: Add functionality to create private queues. Threadlets: Add documentation Makefile.objs |3 - configure |2 docs/async-support.txt | 141 posix-aio-compat.c | 242 qemu-threadlets.c | 175 +++ qemu-threadlets.h | 47 + vl.c |3 + 7 files changed, 430 insertions(+), 183 deletions(-) create mode 100644 docs/async-support.txt create mode 100644 qemu-threadlets.c create mode 100644 qemu-threadlets.h -- arun
[Qemu-devel] [PATCH 02/12] Introduce work concept in posix-aio-compat.c
This patch introduces work concept by introducing the ThreadletWork structure. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- posix-aio-compat.c | 20 ++-- 1 files changed, 14 insertions(+), 6 deletions(-) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 82862ec..ddf42f5 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -33,6 +33,10 @@ static QemuMutex aiocb_mutex; static QemuCond aiocb_completion; +typedef struct ThreadletWork +{ +QTAILQ_ENTRY(ThreadletWork) node; +} ThreadletWork; struct qemu_paiocb { BlockDriverAIOCB common; @@ -47,13 +51,13 @@ struct qemu_paiocb { int ev_signo; off_t aio_offset; -QTAILQ_ENTRY(qemu_paiocb) node; int aio_type; ssize_t ret; int active; struct qemu_paiocb *next; int async_context_id; +ThreadletWork work; }; typedef struct PosixAioState { @@ -69,7 +73,7 @@ static pthread_attr_t attr; static int max_threads = 64; static int cur_threads = 0; static int idle_threads = 0; -static QTAILQ_HEAD(, qemu_paiocb) request_list; +static QTAILQ_HEAD(, ThreadletWork) request_list; #ifdef CONFIG_PREADV static int preadv_present = 1; @@ -307,6 +311,7 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb) static void *aio_thread(void *unused) { pid_t pid; +ThreadletWork *work; pid = getpid(); @@ -330,8 +335,11 @@ static void *aio_thread(void *unused) if (QTAILQ_EMPTY(request_list)) break; -aiocb = QTAILQ_FIRST(request_list); -QTAILQ_REMOVE(request_list, aiocb, node); +work = QTAILQ_FIRST(request_list); +QTAILQ_REMOVE(request_list, work, node); + +aiocb = container_of(work, struct qemu_paiocb, work); + aiocb-active = 1; idle_threads--; mutex_unlock(lock); @@ -398,7 +406,7 @@ static void qemu_paio_submit(struct qemu_paiocb *aiocb) mutex_lock(lock); if (idle_threads == 0 cur_threads max_threads) spawn_thread(); -QTAILQ_INSERT_TAIL(request_list, aiocb, node); +QTAILQ_INSERT_TAIL(request_list, aiocb-work, node); mutex_unlock(lock); cond_signal(cond); } @@ -548,7 +556,7 @@ static void paio_cancel(BlockDriverAIOCB *blockacb) qemu_mutex_lock(aiocb_mutex); if (!acb-active) { -QTAILQ_REMOVE(request_list, acb, node); +QTAILQ_REMOVE(request_list, acb-work, node); acb-ret = -ECANCELED; } else if (acb-ret == -EINPROGRESS) { active = 1;
[Qemu-devel] [PATCH 01/12] Add aiocb_mutex and aiocb_completion.
This patch adds the aiocb_mutex to protect aiocb. This patch also removes the infinite loop present in paio_cancel. Since there can only be one cancellation at a time, we need to introduce a condition variable. For this, we need a global aiocb_completion condition variable. This patch also adds the Makefile entry to compile qemu-thread.c when CONFIG_POSIX is set, instead of the unused CONFIG_THREAD. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- Makefile.objs |2 +- posix-aio-compat.c | 39 --- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index cd5a24b..3b7ec27 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -9,6 +9,7 @@ qobject-obj-y += qerror.o block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o block-obj-y += nbd.o block.o aio.o aes.o osdep.o qemu-config.o +block-obj-$(CONFIG_POSIX) += qemu-thread.o block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o @@ -124,7 +125,6 @@ endif common-obj-y += $(addprefix ui/, $(ui-obj-y)) common-obj-y += iov.o acl.o -common-obj-$(CONFIG_THREAD) += qemu-thread.o common-obj-y += notify.o event_notifier.o common-obj-y += qemu-timer.o diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 7b862b5..82862ec 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -27,9 +27,12 @@ #include qemu-common.h #include trace.h #include block_int.h +#include qemu-thread.h #include block/raw-posix-aio.h +static QemuMutex aiocb_mutex; +static QemuCond aiocb_completion; struct qemu_paiocb { BlockDriverAIOCB common; @@ -351,10 +354,14 @@ static void *aio_thread(void *unused) } mutex_lock(lock); -aiocb-ret = ret; idle_threads++; mutex_unlock(lock); +qemu_mutex_lock(aiocb_mutex); +aiocb-ret = ret; +qemu_cond_broadcast(aiocb_completion); +qemu_mutex_unlock(aiocb_mutex); + if (kill(pid, aiocb-ev_signo)) die(kill failed); } @@ -383,8 +390,11 @@ static void spawn_thread(void) static void qemu_paio_submit(struct qemu_paiocb *aiocb) { +qemu_mutex_lock(aiocb_mutex); aiocb-ret = -EINPROGRESS; aiocb-active = 0; +qemu_mutex_unlock(aiocb_mutex); + mutex_lock(lock); if (idle_threads == 0 cur_threads max_threads) spawn_thread(); @@ -397,9 +407,9 @@ static ssize_t qemu_paio_return(struct qemu_paiocb *aiocb) { ssize_t ret; -mutex_lock(lock); +qemu_mutex_lock(aiocb_mutex); ret = aiocb-ret; -mutex_unlock(lock); +qemu_mutex_unlock(aiocb_mutex); return ret; } @@ -536,22 +546,26 @@ static void paio_cancel(BlockDriverAIOCB *blockacb) struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb; int active = 0; -mutex_lock(lock); +qemu_mutex_lock(aiocb_mutex); if (!acb-active) { QTAILQ_REMOVE(request_list, acb, node); acb-ret = -ECANCELED; } else if (acb-ret == -EINPROGRESS) { active = 1; } -mutex_unlock(lock); -if (active) { -/* fail safe: if the aio could not be canceled, we wait for - it */ -while (qemu_paio_error(acb) == EINPROGRESS) -; +if (!active) { +acb-ret = -ECANCELED; +} else { +while (acb-ret == -EINPROGRESS) { +/* + * fail safe: if the aio could not be canceled, + * we wait for it + */ +qemu_cond_wait(aiocb_completion, aiocb_mutex); +} } - +qemu_mutex_unlock(aiocb_mutex); paio_remove(acb); } @@ -623,6 +637,9 @@ int paio_init(void) if (posix_aio_state) return 0; +qemu_mutex_init(aiocb_mutex); +qemu_cond_init(aiocb_completion); + s = qemu_malloc(sizeof(PosixAioState)); sigfillset(act.sa_mask);
[Qemu-devel] [PATCH 03/12] Add callback function to ThreadletWork structure.
This patch adds the callback function to the ThreadletWork structure and moves aio handler as a callback function. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- posix-aio-compat.c | 89 +--- 1 files changed, 50 insertions(+), 39 deletions(-) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index ddf42f5..4fa2c47 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -36,6 +36,7 @@ static QemuCond aiocb_completion; typedef struct ThreadletWork { QTAILQ_ENTRY(ThreadletWork) node; +void (*func)(struct ThreadletWork *work); } ThreadletWork; struct qemu_paiocb { @@ -308,18 +309,14 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb) return nbytes; } -static void *aio_thread(void *unused) +static void *threadlet_worker(void *data) { -pid_t pid; -ThreadletWork *work; - -pid = getpid(); while (1) { -struct qemu_paiocb *aiocb; ssize_t ret = 0; qemu_timeval tv; struct timespec ts; +ThreadletWork *work; qemu_gettimeofday(tv); ts.tv_sec = tv.tv_sec + 10; @@ -332,52 +329,64 @@ static void *aio_thread(void *unused) ret = cond_timedwait(cond, lock, ts); } -if (QTAILQ_EMPTY(request_list)) +if (QTAILQ_EMPTY(request_list)) { +idle_threads--; +cur_threads--; +mutex_unlock(lock); break; - +} work = QTAILQ_FIRST(request_list); QTAILQ_REMOVE(request_list, work, node); - -aiocb = container_of(work, struct qemu_paiocb, work); - -aiocb-active = 1; idle_threads--; mutex_unlock(lock); -switch (aiocb-aio_type QEMU_AIO_TYPE_MASK) { -case QEMU_AIO_READ: -case QEMU_AIO_WRITE: -ret = handle_aiocb_rw(aiocb); -break; -case QEMU_AIO_FLUSH: -ret = handle_aiocb_flush(aiocb); -break; -case QEMU_AIO_IOCTL: -ret = handle_aiocb_ioctl(aiocb); -break; -default: -fprintf(stderr, invalid aio request (0x%x)\n, aiocb-aio_type); -ret = -EINVAL; -break; -} - +work-func(work); mutex_lock(lock); idle_threads++; mutex_unlock(lock); -qemu_mutex_lock(aiocb_mutex); -aiocb-ret = ret; -qemu_cond_broadcast(aiocb_completion); -qemu_mutex_unlock(aiocb_mutex); +} + +return NULL; +} + +static void handle_work(ThreadletWork *work) +{ +pid_t pid; +ssize_t ret = 0; +struct qemu_paiocb *aiocb; -if (kill(pid, aiocb-ev_signo)) die(kill failed); +pid = getpid(); +qemu_mutex_lock(aiocb_mutex); +aiocb = container_of(work, struct qemu_paiocb, work); +aiocb-active = 1; +qemu_mutex_unlock(aiocb_mutex); + +switch (aiocb-aio_type QEMU_AIO_TYPE_MASK) { +case QEMU_AIO_READ: +case QEMU_AIO_WRITE: +ret = handle_aiocb_rw(aiocb); +break; +case QEMU_AIO_FLUSH: +ret = handle_aiocb_flush(aiocb); +break; +case QEMU_AIO_IOCTL: +ret = handle_aiocb_ioctl(aiocb); +break; +default: +fprintf(stderr, invalid aio request (0x%x)\n, aiocb-aio_type); +ret = -EINVAL; +break; } -idle_threads--; -cur_threads--; -mutex_unlock(lock); +qemu_mutex_lock(aiocb_mutex); +aiocb-ret = ret; +qemu_cond_broadcast(aiocb_completion); +qemu_mutex_unlock(aiocb_mutex); -return NULL; +if (kill(pid, aiocb-ev_signo)) { +die(kill failed); +} } static void spawn_thread(void) @@ -391,7 +400,7 @@ static void spawn_thread(void) if (sigfillset(set)) die(sigfillset); if (sigprocmask(SIG_SETMASK, set, oldset)) die(sigprocmask); -thread_create(thread_id, attr, aio_thread, NULL); +thread_create(thread_id, attr, threadlet_worker, NULL); if (sigprocmask(SIG_SETMASK, oldset, NULL)) die(sigprocmask restore); } @@ -406,6 +415,8 @@ static void qemu_paio_submit(struct qemu_paiocb *aiocb) mutex_lock(lock); if (idle_threads == 0 cur_threads max_threads) spawn_thread(); + +aiocb-work.func = handle_work; QTAILQ_INSERT_TAIL(request_list, aiocb-work, node); mutex_unlock(lock); cond_signal(cond);
Re: [Qemu-devel] [PATCH v2 2/4] piix: tag as not hotpluggable.
Hi, +.no_hotplug = 1, What about piix3-usb-uhci friends? Hmm. Good question. UHCI controllers are hotpluggable. But of course it isn't when it is a function of the chipset because pci can hotplug slots only. Guess the best way to handle this for now is to just disable hotplugging for multifunction slots+devices as qemu currently lacks the infrastructure to handle this correctly. cheers, Gerd
[Qemu-devel] [PATCH 04/12] Add ThreadletQueue.
This patch adds a global queue of type ThreadletQueue and removes the earlier usage of request_list queue. We want to create the thread on the first submit. Hence we need to track whether the globalqueue is initialized or not. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- posix-aio-compat.c | 149 +++- 1 files changed, 76 insertions(+), 73 deletions(-) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 4fa2c47..b5d70c9 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -31,8 +31,23 @@ #include block/raw-posix-aio.h +#define MAX_GLOBAL_THREADS 64 +#define MIN_GLOBAL_THREADS 8 + static QemuMutex aiocb_mutex; static QemuCond aiocb_completion; + +typedef struct ThreadletQueue +{ +QemuMutex lock; +QemuCond cond; +int max_threads; +int min_threads; +int cur_threads; +int idle_threads; +QTAILQ_HEAD(, ThreadletWork) request_list; +} ThreadletQueue; + typedef struct ThreadletWork { QTAILQ_ENTRY(ThreadletWork) node; @@ -66,15 +81,10 @@ typedef struct PosixAioState { struct qemu_paiocb *first_aio; } PosixAioState; - -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -static pthread_t thread_id; +/* Default ThreadletQueue */ +static ThreadletQueue globalqueue; +static int globalqueue_init; static pthread_attr_t attr; -static int max_threads = 64; -static int cur_threads = 0; -static int idle_threads = 0; -static QTAILQ_HEAD(, ThreadletWork) request_list; #ifdef CONFIG_PREADV static int preadv_present = 1; @@ -93,32 +103,6 @@ static void die(const char *what) die2(errno, what); } -static void mutex_lock(pthread_mutex_t *mutex) -{ -int ret = pthread_mutex_lock(mutex); -if (ret) die2(ret, pthread_mutex_lock); -} - -static void mutex_unlock(pthread_mutex_t *mutex) -{ -int ret = pthread_mutex_unlock(mutex); -if (ret) die2(ret, pthread_mutex_unlock); -} - -static int cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - struct timespec *ts) -{ -int ret = pthread_cond_timedwait(cond, mutex, ts); -if (ret ret != ETIMEDOUT) die2(ret, pthread_cond_timedwait); -return ret; -} - -static void cond_signal(pthread_cond_t *cond) -{ -int ret = pthread_cond_signal(cond); -if (ret) die2(ret, pthread_cond_signal); -} - static void thread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) { @@ -311,42 +295,45 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb) static void *threadlet_worker(void *data) { +ThreadletQueue *queue = data; +qemu_mutex_lock(queue-lock); while (1) { -ssize_t ret = 0; -qemu_timeval tv; -struct timespec ts; ThreadletWork *work; +int ret = 0; -qemu_gettimeofday(tv); -ts.tv_sec = tv.tv_sec + 10; -ts.tv_nsec = 0; - -mutex_lock(lock); - -while (QTAILQ_EMPTY(request_list) - !(ret == ETIMEDOUT)) { -ret = cond_timedwait(cond, lock, ts); +while (QTAILQ_EMPTY(queue-request_list) + (ret != ETIMEDOUT)) { +/* wait for cond to be signalled or broadcast for 1000s */ +ret = qemu_cond_timedwait((queue-cond), + (queue-lock), 10*10); } -if (QTAILQ_EMPTY(request_list)) { -idle_threads--; -cur_threads--; -mutex_unlock(lock); -break; -} -work = QTAILQ_FIRST(request_list); -QTAILQ_REMOVE(request_list, work, node); -idle_threads--; -mutex_unlock(lock); +assert(queue-idle_threads != 0); +if (QTAILQ_EMPTY(queue-request_list)) { +if (queue-cur_threads queue-min_threads) { +/* We retain the minimum number of threads */ +break; +} +} else { +work = QTAILQ_FIRST(queue-request_list); +QTAILQ_REMOVE(queue-request_list, work, node); + +queue-idle_threads--; +qemu_mutex_unlock(queue-lock); -work-func(work); -mutex_lock(lock); -idle_threads++; -mutex_unlock(lock); +/* execute the work function */ +work-func(work); +qemu_mutex_lock(queue-lock); +queue-idle_threads++; +} } +queue-idle_threads--; +queue-cur_threads--; +qemu_mutex_unlock(queue-lock); + return NULL; } @@ -389,18 +376,19 @@ static void handle_work(ThreadletWork *work) } } -static void spawn_thread(void) +static void spawn_threadlet(ThreadletQueue *queue) { +pthread_t thread_id; sigset_t set, oldset; -cur_threads++; -idle_threads++; +queue-cur_threads++; +queue-idle_threads++; /* block all signals */ if (sigfillset(set))
[Qemu-devel] [PATCH 07/12] Remove thread_create routine.
Remove thread_create and use qemu_thread_create instead. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- posix-aio-compat.c | 29 ++--- 1 files changed, 2 insertions(+), 27 deletions(-) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 2d73846..8c5bb46 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -13,7 +13,6 @@ #include sys/ioctl.h #include sys/types.h -#include pthread.h #include unistd.h #include errno.h #include time.h @@ -83,7 +82,6 @@ typedef struct PosixAioState { /* Default ThreadletQueue */ static ThreadletQueue globalqueue; static int globalqueue_init; -static pthread_attr_t attr; #ifdef CONFIG_PREADV static int preadv_present = 1; @@ -102,13 +100,6 @@ static void die(const char *what) die2(errno, what); } -static void thread_create(pthread_t *thread, pthread_attr_t *attr, - void *(*start_routine)(void*), void *arg) -{ -int ret = pthread_create(thread, attr, start_routine, arg); -if (ret) die2(ret, pthread_create); -} - static ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb) { int ret; @@ -376,19 +367,12 @@ static void handle_work(ThreadletWork *work) static void spawn_threadlet(ThreadletQueue *queue) { -pthread_t thread_id; -sigset_t set, oldset; +QemuThread thread; queue-cur_threads++; queue-idle_threads++; -/* block all signals */ -if (sigfillset(set)) die(sigfillset); -if (sigprocmask(SIG_SETMASK, set, oldset)) die(sigprocmask); - -thread_create(thread_id, attr, threadlet_worker, queue); - -if (sigprocmask(SIG_SETMASK, oldset, NULL)) die(sigprocmask restore); +qemu_thread_create(thread, threadlet_worker, queue); } /** @@ -661,7 +645,6 @@ int paio_init(void) struct sigaction act; PosixAioState *s; int fds[2]; -int ret; if (posix_aio_state) return 0; @@ -691,14 +674,6 @@ int paio_init(void) qemu_aio_set_fd_handler(s-rfd, posix_aio_read, NULL, posix_aio_flush, posix_aio_process_queue, s); -ret = pthread_attr_init(attr); -if (ret) -die2(ret, pthread_attr_init); - -ret = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED); -if (ret) -die2(ret, pthread_attr_setdetachstate); - posix_aio_state = s; return 0; }
[Qemu-devel] [PATCH 05/12] Threadlet: Add submit_work threadlet API.
This patch adds submit work threadlet API and shows how the qemu_paio_submit changes to submit_work. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- posix-aio-compat.c | 33 ++--- 1 files changed, 22 insertions(+), 11 deletions(-) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index b5d70c9..2ab1109 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -393,13 +393,13 @@ static void spawn_threadlet(ThreadletQueue *queue) if (sigprocmask(SIG_SETMASK, oldset, NULL)) die(sigprocmask restore); } -static void qemu_paio_submit(struct qemu_paiocb *aiocb) +/** + * submit_work: Submit to the global queue a new task to be executed + * asynchronously. + * @work: Contains information about the task that needs to be submitted. + */ +static void submit_work(ThreadletWork *work) { -qemu_mutex_lock(aiocb_mutex); -aiocb-ret = -EINPROGRESS; -aiocb-active = 0; -qemu_mutex_unlock(aiocb_mutex); - qemu_mutex_lock(globalqueue.lock); if (!globalqueue_init) { @@ -415,13 +415,13 @@ static void qemu_paio_submit(struct qemu_paiocb *aiocb) } if (globalqueue.idle_threads == 0 -globalqueue.cur_threads globalqueue.max_threads) +globalqueue.cur_threads globalqueue.max_threads) { spawn_threadlet(globalqueue); -aiocb-work.func = handle_work; - -QTAILQ_INSERT_TAIL(globalqueue.request_list, aiocb-work, node); -qemu_cond_signal(globalqueue.cond); +} else { +qemu_cond_signal(globalqueue.cond); +} +QTAILQ_INSERT_TAIL(globalqueue.request_list, work, node); qemu_mutex_unlock(globalqueue.lock); } @@ -448,6 +448,17 @@ static int qemu_paio_error(struct qemu_paiocb *aiocb) return ret; } +static void qemu_paio_submit(struct qemu_paiocb *aiocb) +{ +qemu_mutex_lock(aiocb_mutex); +aiocb-ret = -EINPROGRESS; +aiocb-active = 0; +qemu_mutex_unlock(aiocb_mutex); + +aiocb-work.func = handle_work; +submit_work(aiocb-work); +} + static int posix_aio_process_queue(void *opaque) { PosixAioState *s = opaque;
[Qemu-devel] [PATCH 06/12] Threadlet: Add dequeue_work threadlet API and remove active field.
This patch adds dequeue_work threadlet API and shows how the paio_cancel changes to dequeue_work. The active field in the qemu_aiocb structure is now useless. Remove it. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- posix-aio-compat.c | 38 -- 1 files changed, 16 insertions(+), 22 deletions(-) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 2ab1109..2d73846 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -69,7 +69,6 @@ struct qemu_paiocb { int aio_type; ssize_t ret; -int active; struct qemu_paiocb *next; int async_context_id; @@ -346,7 +345,6 @@ static void handle_work(ThreadletWork *work) pid = getpid(); qemu_mutex_lock(aiocb_mutex); aiocb = container_of(work, struct qemu_paiocb, work); -aiocb-active = 1; qemu_mutex_unlock(aiocb_mutex); switch (aiocb-aio_type QEMU_AIO_TYPE_MASK) { @@ -452,7 +450,6 @@ static void qemu_paio_submit(struct qemu_paiocb *aiocb) { qemu_mutex_lock(aiocb_mutex); aiocb-ret = -EINPROGRESS; -aiocb-active = 0; qemu_mutex_unlock(aiocb_mutex); aiocb-work.func = handle_work; @@ -574,33 +571,30 @@ static void paio_remove(struct qemu_paiocb *acb) } } -static void paio_cancel(BlockDriverAIOCB *blockacb) +/** + * dequeue_work: Cancel a task queued on the global queue. + * @work: Contains the information of the task that needs to be cancelled. + */ +static int dequeue_work(ThreadletWork *work) { -struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb; -int active = 0; - -qemu_mutex_lock(aiocb_mutex); qemu_mutex_lock(globalqueue.lock); -if (!acb-active) { -QTAILQ_REMOVE(globalqueue.request_list, acb-work, node); -acb-ret = -ECANCELED; -} else if (acb-ret == -EINPROGRESS) { -active = 1; -} +QTAILQ_REMOVE(globalqueue.request_list, work, node); qemu_mutex_unlock(globalqueue.lock); -if (!active) { -acb-ret = -ECANCELED; -} else { +return 0; +} + +static void paio_cancel(BlockDriverAIOCB *blockacb) +{ +struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb; +if (dequeue_work(acb-work) != 0) { +/* Wait for running work item to complete */ +qemu_mutex_lock(aiocb_mutex); while (acb-ret == -EINPROGRESS) { -/* - * fail safe: if the aio could not be canceled, - * we wait for it - */ qemu_cond_wait(aiocb_completion, aiocb_mutex); } +qemu_mutex_unlock(aiocb_mutex); } -qemu_mutex_unlock(aiocb_mutex); paio_remove(acb); }
[Qemu-devel] [PATCH 10/12] Move threadlet code to qemu-threadlets.c
This patch moves the threadlet queue API code to qemu-threadlets.c where these APIs can be used by other subsystems. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- Makefile.objs |1 posix-aio-compat.c | 144 qemu-thread.h |1 qemu-threadlets.c | 142 +++ qemu-threadlets.h | 43 vl.c |2 - 6 files changed, 188 insertions(+), 145 deletions(-) create mode 100644 qemu-threadlets.c create mode 100644 qemu-threadlets.h diff --git a/Makefile.objs b/Makefile.objs index 3b7ec27..2cf8aba 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -10,6 +10,7 @@ qobject-obj-y += qerror.o block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o block-obj-y += nbd.o block.o aio.o aes.o osdep.o qemu-config.o block-obj-$(CONFIG_POSIX) += qemu-thread.o +block-obj-$(CONFIG_POSIX) += qemu-threadlets.o block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 94dd007..df55ce6 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -26,33 +26,13 @@ #include qemu-common.h #include trace.h #include block_int.h -#include qemu-thread.h +#include qemu-threadlets.h #include block/raw-posix-aio.h -#define MAX_GLOBAL_THREADS 64 -#define MIN_GLOBAL_THREADS 8 - static QemuMutex aiocb_mutex; static QemuCond aiocb_completion; -typedef struct ThreadletQueue -{ -QemuMutex lock; -QemuCond cond; -int max_threads; -int min_threads; -int cur_threads; -int idle_threads; -QTAILQ_HEAD(, ThreadletWork) request_list; -} ThreadletQueue; - -typedef struct ThreadletWork -{ -QTAILQ_ENTRY(ThreadletWork) node; -void (*func)(struct ThreadletWork *work); -} ThreadletWork; - struct qemu_paiocb { BlockDriverAIOCB common; int aio_fildes; @@ -79,10 +59,6 @@ typedef struct PosixAioState { struct qemu_paiocb *first_aio; } PosixAioState; -/* Default ThreadletQueue */ -static ThreadletQueue globalqueue; -static int globalqueue_init; - #ifdef CONFIG_PREADV static int preadv_present = 1; #else @@ -283,50 +259,6 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb) return nbytes; } -static void *threadlet_worker(void *data) -{ -ThreadletQueue *queue = data; - -qemu_mutex_lock(queue-lock); -while (1) { -ThreadletWork *work; -int ret = 0; - -while (QTAILQ_EMPTY(queue-request_list) - (ret != ETIMEDOUT)) { -/* wait for cond to be signalled or broadcast for 1000s */ -ret = qemu_cond_timedwait((queue-cond), - (queue-lock), 10*10); -} - -assert(queue-idle_threads != 0); -if (QTAILQ_EMPTY(queue-request_list)) { -if (queue-cur_threads queue-min_threads) { -/* We retain the minimum number of threads */ -break; -} -} else { -work = QTAILQ_FIRST(queue-request_list); -QTAILQ_REMOVE(queue-request_list, work, node); - -queue-idle_threads--; -qemu_mutex_unlock(queue-lock); - -/* execute the work function */ -work-func(work); - -qemu_mutex_lock(queue-lock); -queue-idle_threads++; -} -} - -queue-idle_threads--; -queue-cur_threads--; -qemu_mutex_unlock(queue-lock); - -return NULL; -} - static PosixAioState *posix_aio_state; static void handle_work(ThreadletWork *work) @@ -373,67 +305,6 @@ static void handle_work(ThreadletWork *work) } } -static void threadlet_io_completion_signal_handler(int signum) -{ -qemu_service_io(); -} - -static void threadlet_register_signal_handler(void) -{ -struct sigaction act; -sigfillset(act.sa_mask); -act.sa_flags = 0; /* do not restart syscalls to interrupt select() */ -act.sa_handler = threadlet_io_completion_signal_handler; -sigaction(SIGUSR2, act, NULL); -} - -void threadlet_init(void) -{ -threadlet_register_signal_handler(); -} - -static void spawn_threadlet(ThreadletQueue *queue) -{ -QemuThread thread; - -queue-cur_threads++; -queue-idle_threads++; - -qemu_thread_create(thread, threadlet_worker, queue); -} - -/** - * submit_work: Submit to the global queue a new task to be executed - * asynchronously. - * @work: Contains information about the task that needs to be submitted. - */ -static void submit_work(ThreadletWork *work) -{ -qemu_mutex_lock(globalqueue.lock); - -if (!globalqueue_init) { -globalqueue.cur_threads = 0; -globalqueue.idle_threads = 0; -globalqueue.max_threads = MAX_GLOBAL_THREADS; -globalqueue.min_threads = MIN_GLOBAL_THREADS; -QTAILQ_INIT(globalqueue.request_list); -qemu_mutex_init(globalqueue.lock); -
[Qemu-devel] [PATCH 08/12] Threadlet: Add aio_signal_handler threadlet API
This patch adds aio_signal_handler threadlet API. Earler posix-aio-compat.c had its own signal handler code. Now abstract this, in the later patch it is moved to a generic code so that it can be used by other subsystems. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- posix-aio-compat.c | 49 +++-- qemu-thread.h |1 + vl.c |3 +++ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 8c5bb46..94dd007 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -327,11 +327,14 @@ static void *threadlet_worker(void *data) return NULL; } +static PosixAioState *posix_aio_state; + static void handle_work(ThreadletWork *work) { pid_t pid; ssize_t ret = 0; struct qemu_paiocb *aiocb; +char byte = 0; pid = getpid(); qemu_mutex_lock(aiocb_mutex); @@ -360,11 +363,35 @@ static void handle_work(ThreadletWork *work) qemu_cond_broadcast(aiocb_completion); qemu_mutex_unlock(aiocb_mutex); +ret = write(posix_aio_state-wfd, byte, sizeof(byte)); +if (ret 0 errno != EAGAIN) { +die(write()); +} + if (kill(pid, aiocb-ev_signo)) { die(kill failed); } } +static void threadlet_io_completion_signal_handler(int signum) +{ +qemu_service_io(); +} + +static void threadlet_register_signal_handler(void) +{ +struct sigaction act; +sigfillset(act.sa_mask); +act.sa_flags = 0; /* do not restart syscalls to interrupt select() */ +act.sa_handler = threadlet_io_completion_signal_handler; +sigaction(SIGUSR2, act, NULL); +} + +void threadlet_init(void) +{ +threadlet_register_signal_handler(); +} + static void spawn_threadlet(ThreadletQueue *queue) { QemuThread thread; @@ -520,22 +547,6 @@ static int posix_aio_flush(void *opaque) return !!s-first_aio; } -static PosixAioState *posix_aio_state; - -static void aio_signal_handler(int signum) -{ -if (posix_aio_state) { -char byte = 0; -ssize_t ret; - -ret = write(posix_aio_state-wfd, byte, sizeof(byte)); -if (ret 0 errno != EAGAIN) -die(write()); -} - -qemu_service_io(); -} - static void paio_remove(struct qemu_paiocb *acb) { struct qemu_paiocb **pacb; @@ -642,7 +653,6 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd, int paio_init(void) { -struct sigaction act; PosixAioState *s; int fds[2]; @@ -654,11 +664,6 @@ int paio_init(void) s = qemu_malloc(sizeof(PosixAioState)); -sigfillset(act.sa_mask); -act.sa_flags = 0; /* do not restart syscalls to interrupt select() */ -act.sa_handler = aio_signal_handler; -sigaction(SIGUSR2, act, NULL); - s-first_aio = NULL; if (qemu_pipe(fds) == -1) { fprintf(stderr, failed to create pipe\n); diff --git a/qemu-thread.h b/qemu-thread.h index 19bb30c..c5b579c 100644 --- a/qemu-thread.h +++ b/qemu-thread.h @@ -40,5 +40,6 @@ void qemu_thread_signal(QemuThread *thread, int sig); void qemu_thread_self(QemuThread *thread); int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2); void qemu_thread_exit(void *retval); +void threadlet_init(void); #endif diff --git a/vl.c b/vl.c index df414ef..aba805f 100644 --- a/vl.c +++ b/vl.c @@ -148,6 +148,7 @@ int main(int argc, char **argv) #include qemu-config.h #include qemu-objects.h #include qemu-options.h +#include qemu-thread.h #ifdef CONFIG_VIRTFS #include fsdev/qemu-fsdev.h #endif @@ -2922,6 +2923,8 @@ int main(int argc, char **argv, char **envp) exit(1); } +threadlet_init(); + /* init generic devices */ if (qemu_opts_foreach(qemu_find_opts(device), device_init_func, NULL, 1) != 0) exit(1);
[Qemu-devel] [PATCH 11/12] Threadlets: Add functionality to create private queues.
This patch allows subsystems to create their own private queues with associated pools of threads. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- qemu-threadlets.c | 75 ++--- qemu-threadlets.h |4 +++ 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/qemu-threadlets.c b/qemu-threadlets.c index 42dd3d1..4df79b8 100644 --- a/qemu-threadlets.c +++ b/qemu-threadlets.c @@ -99,6 +99,25 @@ static void spawn_threadlet(ThreadletQueue *queue) } /** + * submit_work_to_queue: Submit a new task to a private queue to be + *executed asynchronously. + * @queue: Per-subsystem private queue to which the new task needs + * to be submitted. + * @work: Contains information about the task that needs to be submitted. + */ +void submit_work_to_queue(ThreadletQueue *queue, ThreadletWork *work) +{ +qemu_mutex_lock(queue-lock); +if (queue-idle_threads == 0 queue-cur_threads queue-max_threads) { +spawn_threadlet(queue); +} else { +qemu_cond_signal(queue-cond); +} +QTAILQ_INSERT_TAIL(queue-request_list, work, node); +qemu_mutex_unlock(queue-lock); +} + +/** * submit_work: Submit to the global queue a new task to be executed * asynchronously. * @work: Contains information about the task that needs to be submitted. @@ -106,26 +125,26 @@ static void spawn_threadlet(ThreadletQueue *queue) void submit_work(ThreadletWork *work) { if (!globalqueue_init) { -globalqueue.cur_threads = 0; -globalqueue.idle_threads = 0; -globalqueue.max_threads = MAX_GLOBAL_THREADS; -globalqueue.min_threads = MIN_GLOBAL_THREADS; -QTAILQ_INIT(globalqueue.request_list); -qemu_mutex_init(globalqueue.lock); -qemu_cond_init(globalqueue.cond); - +threadlet_queue_init(globalqueue, MAX_GLOBAL_THREADS, +MIN_GLOBAL_THREADS); globalqueue_init = 1; } -qemu_mutex_lock(globalqueue.lock); -if (globalqueue.idle_threads == 0 -globalqueue.cur_threads globalqueue.max_threads) { -spawn_threadlet(globalqueue); -} else { -qemu_cond_signal(globalqueue.cond); -} -QTAILQ_INSERT_TAIL(globalqueue.request_list, work, node); -qemu_mutex_unlock(globalqueue.lock); +submit_work_to_queue(globalqueue, work); +} + +/** + * dequeue_work_on_queue: Cancel a task queued on a Queue. + * @queue: The queue containing the task to be cancelled. + * @work: Contains the information of the task that needs to be cancelled. + */ +int dequeue_work_on_queue(ThreadletQueue *queue, ThreadletWork *work) +{ +qemu_mutex_lock(queue-lock); +QTAILQ_REMOVE(queue-request_list, work, node); +qemu_mutex_unlock(queue-lock); + +return 0; } /** @@ -134,9 +153,23 @@ void submit_work(ThreadletWork *work) */ int dequeue_work(ThreadletWork *work) { -qemu_mutex_lock(globalqueue.lock); -QTAILQ_REMOVE(globalqueue.request_list, work, node); -qemu_mutex_unlock(globalqueue.lock); +return dequeue_work_on_queue(globalqueue, work); +} -return 0; +/** + * threadlet_queue_init: Initialize a threadlet queue. + * @queue: The threadlet queue to be initialized. + * @max_threads: Maximum number of threads processing the queue. + * @min_threads: Minimum number of threads processing the queue. + */ +void threadlet_queue_init(ThreadletQueue *queue, +int max_threads, int min_threads) +{ +queue-cur_threads = 0; +queue-idle_threads = 0; +queue-max_threads = max_threads; +queue-min_threads = min_threads; +QTAILQ_INIT(queue-request_list); +qemu_mutex_init(queue-lock); +qemu_cond_init(queue-cond); } diff --git a/qemu-threadlets.h b/qemu-threadlets.h index 03bb86b..993d7ab 100644 --- a/qemu-threadlets.h +++ b/qemu-threadlets.h @@ -37,7 +37,11 @@ typedef struct ThreadletWork void (*func)(struct ThreadletWork *work); } ThreadletWork; +void submit_work_to_queue(ThreadletQueue *queue, ThreadletWork *work); void submit_work(ThreadletWork *work); +int dequeue_work_on_queue(ThreadletQueue *queue, ThreadletWork *work); int dequeue_work(ThreadletWork *work); void threadlet_init(void); +void threadlet_queue_init(ThreadletQueue *queue, int max_threads, + int min_threads); #endif
[Qemu-devel] [PATCH 09/12] Remove all instances of CONFIG_THREAD
Remove all instances of CONFIG_THREAD, which is not used anymore. Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- configure |2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/configure b/configure index a079a49..addf733 100755 --- a/configure +++ b/configure @@ -2456,7 +2456,6 @@ if test $vnc_png != no ; then fi if test $vnc_thread != no ; then echo CONFIG_VNC_THREAD=y $config_host_mak - echo CONFIG_THREAD=y $config_host_mak fi if test $fnmatch = yes ; then echo CONFIG_FNMATCH=y $config_host_mak @@ -2534,7 +2533,6 @@ if test $xen = yes ; then fi if test $io_thread = yes ; then echo CONFIG_IOTHREAD=y $config_host_mak - echo CONFIG_THREAD=y $config_host_mak fi if test $linux_aio = yes ; then echo CONFIG_LINUX_AIO=y $config_host_mak
[Qemu-devel] Re: [PATCH] softfloat: fix floatx80_is_{quiet, signaling}_nan()
On 13 January 2011 01:31, Aurelien Jarno aurel...@aurel32.net wrote: On Wed, Jan 12, 2011 at 03:05:10PM -0600, Peter Maydell wrote: Actually, will return ((a.high 0x7fff) == 0x7fff) (a.low = LIT64(0x4000)); do? Untested but I think it will do the right thing. I'm not sure The explicit bit might be one for a NaN, so you should filter it first. Whoops, yes, explicit-bit-set but signalling-bit-clear would be a false positive. -- PMM
[Qemu-devel] [PATCH 12/12] Threadlets: Add documentation
Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com Signed-off-by: Gautham R Shenoy gautham.she...@gmail.com --- docs/async-support.txt | 141 1 files changed, 141 insertions(+), 0 deletions(-) create mode 100644 docs/async-support.txt diff --git a/docs/async-support.txt b/docs/async-support.txt new file mode 100644 index 000..9f22b9a --- /dev/null +++ b/docs/async-support.txt @@ -0,0 +1,141 @@ +== How to use the threadlets infrastructure supported in Qemu == + +== Threadlets == + +Q.1: What are threadlets ? +A.1: Threadlets is an infrastructure within QEMU that allows other subsystems + to offload possibly blocking work to a queue to be processed by a pool + of threads asynchronously. + +Q.2: When would one want to use threadlets ? +A.2: Threadlets are useful when there are operations that can be performed + outside the context of the VCPU/IO threads inorder to free these latter + to service any other guest requests. + +Q.3: I have some work that can be executed in an asynchronous context. How + should I go about it ? +A.3: One could follow the steps listed below: + + - Define a function which would do the asynchronous work. + static void my_threadlet_func(ThreadletWork *work) + { + } + + - Declare an object of type ThreadletWork; + ThreadletWork work; + + + - Assign a value to the func member of ThreadletWork object. + work.func = my_threadlet_func; + + - Submit the threadlet to the global queue. + submit_threadletwork(work); + + - Continue servicing some other guest operations. + +Q.4: I want to my_threadlet_func to access some non-global data. How do I do + that ? +A.4: Suppose you want my_threadlet_func to access some non-global data-object + of type myPrivateData. In that case one could follow the following steps. + + - Define a member of the type ThreadletWork within myPrivateData. + typedef struct MyPrivateData { + ...; + ...; + ...; + ThreadletWork work; + } MyPrivateData; + + MyPrivateData my_data; + + - Initialize myData.work as described in A.3 + myData.work.func = my_threadlet_func; + submit_threadletwork(myData.work); + + - Access the myData object inside my_threadlet_func() using container_of + primitive + static void my_threadlet_func(ThreadletWork *work) + { + myPrivateData *mydata_ptr; + mydata_ptr = container_of(work, myPrivateData, work); + + /* mydata_ptr now points to myData object */ + } + +Q.5: Are there any precautions one must take while sharing data with the + Asynchronous thread-pool ? +A.5: Yes, make sure that the helper function of the type my_threadlet_func() + does not access/modify data when it can be accessed or modified in the + context of VCPU thread or IO thread. This is because the asynchronous + threads in the pool can run in parallel with the VCPU/IOThreads as shown + in the figure. + + A typical workflow is as follows: + + VCPU/IOThread + | + | (1) + | + V +Offload work (2) + |--- to threadlets - Helper thread + || | + || | + || (3) | (4) + || | + | Handle other Guest requests| + || | + || V + || (3) Signal the I/O Thread + |(6) | | + || / + || / + |V/ + | Do the post -/ + | processing (5) + || + || (6) + |V + |-Yes-- More async work? + | + | (7) + No + | + | + . + . + +Hence one needs to make sure that in the steps (3) and (4) which run in +parallel, any global data is accessed within only one context. + +Q.6: I have queued a threadlet which I want to cancel. How do I do that ? +A.6: Threadlets framework provides the API cancel_threadlet: + - int cancel_threadletwork(ThreadletWork *work) + + The API scans the ThreadletQueue to
Re: [Qemu-devel] Linux as VirtualBox quest OS with QEMU running Solaris
On 13/01/11 10:13, Michal Suchanek wrote: On 13 January 2011 00:34, Mateusz Loskotmate...@loskot.net wrote: On 12/01/11 17:15, Mateusz Loskot wrote: On 12/01/11 16:48, Michal Suchanek wrote: On 12 January 2011 16:21, Mateusz Loskotmate...@loskot.netwrote: Thinking of future, could anyone estimate when it will be possible to boot Solaris 10 installation from ISO disks, if at all? To summary, what OS alternative for SPARC we have got apart from Debian which are known to work under QEMU? *BSD systems? I can run NetBSD sparc install CD just fine. It supports sparc32 in the latest release. Thanks. Great, I'll try. One of the problems I found with Debian Etch is the package repositories are no longer supported and the installer can easily mess with those for Lenny. The only solution is to have all CDs for Etch available and run complete offline installation. I guess the NetBSD option is more up to date here. I have tried the recent NetBSD and it boots without problems, however I can't configure networking to install via FTP/HTTP. Strangely, I don't get question about DHCP. Yes, that's probably an issue with the sparc installer script. However, the sparccd has all the sets so you can easily install from the CD. Once installed you can set up dhclient. Thanks for the hint. Indeed, I managed to install the base system from CD and boot from QEMU image. I performed post-install configuration according to the NetBSD guide and I have dhclient=YET in /etc/rc.conf. The only problem I find is that I'm unable to configure any other networking than the user mode with QEMU network 10.0.2.0. I'm still using QEMU 0.13 binaries installed using Qemu Manager 0.7. I tried to play with -nic option and the only model supported by qemu-system-sparc is lance (iface=le0). I tried to pass both -net nic -net user with hope to get two network interfaces so I can setup one to obtain IP from my external DHCP, no luck. I have read through manual and Web resoruces, but I feel I'm still missing something something, in particular, I don't understand how to make the iface connecting to my external DHCP instead of QEMU's. Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org Member of ACCU, http://accu.org
[Qemu-devel] [PATCH 4/5] iohandlers: Enable an iohandler only if the associated handler exists
If an iohandler is asked to be enabled but the handler doesn't exist, don't enable the handler. This can be used to simplify the conditions in main_loop_wait(). Signed-off-by: Amit Shah amit.s...@redhat.com --- vl.c | 29 - 1 files changed, 20 insertions(+), 9 deletions(-) diff --git a/vl.c b/vl.c index a0b14b5..42ec36a 100644 --- a/vl.c +++ b/vl.c @@ -1084,7 +1084,11 @@ int set_read_poll_fd_action(int fd, bool enable) if (!ioh) { return -1; } -ioh-read_poll_enabled = enable; + +ioh-read_poll_enabled = false; +if (enable ioh-fd_read_poll) { +ioh-read_poll_enabled = true; +} return 0; } @@ -1098,7 +1102,11 @@ int set_read_fd_action(int fd, bool enable) if (!ioh) { return -1; } -ioh-read_enabled = enable; + +ioh-read_enabled = false; +if (enable ioh-fd_read) { +ioh-read_enabled = true; +} return 0; } @@ -1112,7 +1120,11 @@ int set_write_fd_action(int fd, bool enable) if (!ioh) { return -1; } -ioh-write_enabled = enable; + +ioh-write_enabled = false; +if (enable ioh-fd_write) { +ioh-write_enabled = true; +} return 0; } @@ -1391,14 +1403,13 @@ void main_loop_wait(int nonblocking) QLIST_FOREACH(ioh, io_handlers, next) { if (ioh-deleted) continue; -if (ioh-fd_read ioh-read_enabled -(!ioh-fd_read_poll || - (!ioh-read_poll_enabled || ioh-fd_read_poll(ioh-opaque) != 0))) { +if (ioh-read_enabled +(!ioh-read_poll_enabled || ioh-fd_read_poll(ioh-opaque) != 0)) { FD_SET(ioh-fd, rfds); if (ioh-fd nfds) nfds = ioh-fd; } -if (ioh-fd_write ioh-write_enabled) { +if (ioh-write_enabled) { FD_SET(ioh-fd, wfds); if (ioh-fd nfds) nfds = ioh-fd; @@ -1417,10 +1428,10 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) { -if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd, rfds)) { +if (!ioh-deleted ioh-read_enabled FD_ISSET(ioh-fd, rfds)) { ioh-fd_read(ioh-opaque); } -if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd, wfds)) { +if (!ioh-deleted ioh-write_enabled FD_ISSET(ioh-fd, wfds)) { ioh-fd_write(ioh-opaque); } -- 1.7.3.4
[Qemu-devel] [PATCH 1/5] iohandlers: Avoid code duplication
Add a get_iohandler() function instead of looking up the ioh twice in qemu_set_fd_handler2(). Signed-off-by: Amit Shah amit.s...@redhat.com --- vl.c | 44 ++-- 1 files changed, 26 insertions(+), 18 deletions(-) diff --git a/vl.c b/vl.c index 0292184..9e365f6 100644 --- a/vl.c +++ b/vl.c @@ -1022,6 +1022,17 @@ typedef struct IOHandlerRecord { static QLIST_HEAD(, IOHandlerRecord) io_handlers = QLIST_HEAD_INITIALIZER(io_handlers); +static IOHandlerRecord *get_iohandler(int fd) +{ +IOHandlerRecord *ioh; + +QLIST_FOREACH(ioh, io_handlers, next) { +if (ioh-fd == fd) { +return ioh; +} +} +return NULL; +} /* XXX: fd_read_poll should be suppressed, but an API change is necessary in the character devices to suppress fd_can_read(). */ @@ -1033,28 +1044,25 @@ int qemu_set_fd_handler2(int fd, { IOHandlerRecord *ioh; -if (!fd_read !fd_write) { -QLIST_FOREACH(ioh, io_handlers, next) { -if (ioh-fd == fd) { -ioh-deleted = 1; -break; -} -} -} else { -QLIST_FOREACH(ioh, io_handlers, next) { -if (ioh-fd == fd) -goto found; -} +ioh = get_iohandler(fd); + +if (ioh !fd_read !fd_write) { +ioh-deleted = 1; +return 0; +} + +if (!ioh) { ioh = qemu_mallocz(sizeof(IOHandlerRecord)); QLIST_INSERT_HEAD(io_handlers, ioh, next); -found: + ioh-fd = fd; -ioh-fd_read_poll = fd_read_poll; -ioh-fd_read = fd_read; -ioh-fd_write = fd_write; -ioh-opaque = opaque; -ioh-deleted = 0; } +ioh-fd_read_poll = fd_read_poll; +ioh-fd_read = fd_read; +ioh-fd_write = fd_write; +ioh-opaque = opaque; +ioh-deleted = 0; + return 0; } -- 1.7.3.4
Re: [Qemu-devel] [PATCH v2] gdbstub: Close connection in gdb_exit
On Thu, Jan 13, 2011 at 12:46:57PM +0100, Fabien Chouteau wrote: On Windows, this is required to flush the remaining data in the IO stream, otherwise Gdb do not receive the last packet. Version 2: Fix linux-user build error. Hi, It seems a bit odd to explicitely close for system mode but to implicitely close (at exit) for user mode. But if no one complains, I'm OK with this version. Cheers Signed-off-by: Fabien Chouteau chout...@adacore.com --- gdbstub.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 0aa081b..d6556c9 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -2391,6 +2391,12 @@ void gdb_exit(CPUState *env, int code) snprintf(buf, sizeof(buf), W%02x, (uint8_t)code); put_packet(s, buf); + +#ifndef CONFIG_USER_ONLY + if (s-chr) { + qemu_chr_close(s-chr); + } +#endif } #ifdef CONFIG_USER_ONLY -- 1.7.1
[Qemu-devel] [PATCH 0/5] iohandlers: Add support for enabling/disabling individual handlers
Hi, This patchset adds new interfaces to work with iohandlers. It adds: int assign_fd_handlers(int fd, IOHandlerOps *ops, void *opaque) -- Specify io handlers for an fd int remove_fd_handlers(int fd) -- Remove fd handlers for fd (mark ioh for deletion) int set_read_poll_fd_action(int fd, bool enable) -- Enable or disable the fd_read_poll fd handler int set_read_fd_action(int fd, bool enable) -- Enable or disable the fd_read fd handler int set_write_fd_action(int fd, bool enable) -- Enable or disable the fd_read fd handler A new struct, IOHandlerOps, is added, to collect all the ops together instead of passing individual ones to functions. The older function, qemu_set_fd_handler2(), is now a wrapper to assign_fd_handlers() and can be deprecated by converting the existing usage to assign_fd_handlers(). Please apply. Amit Shah (5): iohandlers: Avoid code duplication iohandlers: Introduce assign_fd_handlers() and remove_fd_handlers iohandlers: Allow each iohandler to be enabled/disabled individually iohandlers: Enable an iohandler only if the associated handler exists iohandlers: Add IOHandlerOps struct qemu-char.h |7 +++ vl.c| 162 +++ 2 files changed, 136 insertions(+), 33 deletions(-) -- 1.7.3.4
[Qemu-devel] [PATCH 2/5] iohandlers: Introduce assign_fd_handlers() and remove_fd_handlers
This function will be used to assign fd handlers. Future commits will be enable each handler to be enabled/disabled individually. Make qemu_set_fd_handler2() a wrapper to assign_fd_handlers(). remove_fd_handlers() removes all the assigned handlers and marks the iohandler for deletion. It's a wrapper to assign_fd_handlers() with NULL handlers. Signed-off-by: Amit Shah amit.s...@redhat.com --- qemu-char.h |6 ++ vl.c| 24 +++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/qemu-char.h b/qemu-char.h index e6ee6c4..0ef83f4 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -109,6 +109,12 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr); /* async I/O support */ +int assign_fd_handlers(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque); +void remove_fd_handlers(int fd); int qemu_set_fd_handler2(int fd, IOCanReadHandler *fd_read_poll, IOHandler *fd_read, diff --git a/vl.c b/vl.c index 9e365f6..38e0a3c 100644 --- a/vl.c +++ b/vl.c @@ -1036,11 +1036,11 @@ static IOHandlerRecord *get_iohandler(int fd) /* XXX: fd_read_poll should be suppressed, but an API change is necessary in the character devices to suppress fd_can_read(). */ -int qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) +int assign_fd_handlers(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) { IOHandlerRecord *ioh; @@ -1066,6 +1066,20 @@ int qemu_set_fd_handler2(int fd, return 0; } +void remove_fd_handlers(int fd) +{ +assign_fd_handlers(fd, NULL, NULL, NULL, NULL); +} + +int qemu_set_fd_handler2(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) +{ +return assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +} + int qemu_set_fd_handler(int fd, IOHandler *fd_read, IOHandler *fd_write, -- 1.7.3.4
[Qemu-devel] [PATCH 5/5] iohandlers: Add IOHandlerOps struct
Collect all the handlers in a IOHandlerOps struct instead of being passed one at a time to each function. Signed-off-by: Amit Shah amit.s...@redhat.com --- qemu-char.h |7 ++- vl.c| 51 --- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/qemu-char.h b/qemu-char.h index e88a108..ebf9cd1 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -108,12 +108,9 @@ QString *qemu_chr_mem_to_qs(CharDriverState *chr); size_t qemu_chr_mem_osize(const CharDriverState *chr); /* async I/O support */ +typedef struct IOHandlerOps IOHandlerOps; -int assign_fd_handlers(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque); +int assign_fd_handlers(int fd, const IOHandlerOps *ops, void *opaque); void remove_fd_handlers(int fd); int set_read_poll_fd_action(int fd, bool enable); int set_read_fd_action(int fd, bool enable); diff --git a/vl.c b/vl.c index 42ec36a..d2ef63f 100644 --- a/vl.c +++ b/vl.c @@ -1007,11 +1007,15 @@ void pcmcia_info(Monitor *mon) /***/ /* I/O handling */ -typedef struct IOHandlerRecord { -int fd; +struct IOHandlerOps { IOCanReadHandler *fd_read_poll; IOHandler *fd_read; IOHandler *fd_write; +}; + +typedef struct IOHandlerRecord { +int fd; +IOHandlerOps ops; int deleted; void *opaque; bool read_poll_enabled; @@ -1025,6 +1029,10 @@ typedef struct IOHandlerRecord { static QLIST_HEAD(, IOHandlerRecord) io_handlers = QLIST_HEAD_INITIALIZER(io_handlers); +static const IOHandlerOps null_ioh_ops = { +/* All ops are NULL */ +}; + static IOHandlerRecord *get_iohandler(int fd) { IOHandlerRecord *ioh; @@ -1039,17 +1047,16 @@ static IOHandlerRecord *get_iohandler(int fd) /* XXX: fd_read_poll should be suppressed, but an API change is necessary in the character devices to suppress fd_can_read(). */ -int assign_fd_handlers(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) +int assign_fd_handlers(int fd, const IOHandlerOps *ops, void *opaque) { IOHandlerRecord *ioh; ioh = get_iohandler(fd); -if (ioh !fd_read !fd_write) { +if (!ops) { +ops = null_ioh_ops; +} +if (ioh !ops-fd_read !ops-fd_write) { ioh-deleted = 1; return 0; } @@ -1060,9 +1067,9 @@ int assign_fd_handlers(int fd, ioh-fd = fd; } -ioh-fd_read_poll = fd_read_poll; -ioh-fd_read = fd_read; -ioh-fd_write = fd_write; +ioh-ops.fd_read_poll = ops-fd_read_poll; +ioh-ops.fd_read = ops-fd_read; +ioh-ops.fd_write = ops-fd_write; ioh-opaque = opaque; ioh-deleted = 0; ioh-read_poll_enabled = ioh-read_enabled = ioh-write_enabled = false; @@ -1072,7 +1079,7 @@ int assign_fd_handlers(int fd, void remove_fd_handlers(int fd) { -assign_fd_handlers(fd, NULL, NULL, NULL, NULL); +assign_fd_handlers(fd, NULL, NULL); } int set_read_poll_fd_action(int fd, bool enable) @@ -1086,7 +1093,7 @@ int set_read_poll_fd_action(int fd, bool enable) } ioh-read_poll_enabled = false; -if (enable ioh-fd_read_poll) { +if (enable ioh-ops.fd_read_poll) { ioh-read_poll_enabled = true; } @@ -1104,7 +,7 @@ int set_read_fd_action(int fd, bool enable) } ioh-read_enabled = false; -if (enable ioh-fd_read) { +if (enable ioh-ops.fd_read) { ioh-read_enabled = true; } @@ -1122,7 +1129,7 @@ int set_write_fd_action(int fd, bool enable) } ioh-write_enabled = false; -if (enable ioh-fd_write) { +if (enable ioh-ops.fd_write) { ioh-write_enabled = true; } @@ -1135,7 +1142,13 @@ int qemu_set_fd_handler2(int fd, IOHandler *fd_write, void *opaque) { -assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +IOHandlerOps ops; + +ops.fd_read_poll = fd_read_poll; +ops.fd_read = fd_read; +ops.fd_write = fd_write; +assign_fd_handlers(fd, ops, opaque); + set_read_poll_fd_action(fd, true); set_read_fd_action(fd, true); set_write_fd_action(fd, true); @@ -1404,7 +1417,7 @@ void main_loop_wait(int nonblocking) if (ioh-deleted) continue; if (ioh-read_enabled -(!ioh-read_poll_enabled || ioh-fd_read_poll(ioh-opaque) != 0)) { +(!ioh-read_poll_enabled || ioh-ops.fd_read_poll(ioh-opaque) != 0)) { FD_SET(ioh-fd, rfds); if (ioh-fd nfds) nfds = ioh-fd; @@ -1429,10 +1442,10 @@ void main_loop_wait(int nonblocking) QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) { if (!ioh-deleted
Re: [Qemu-devel] [PATCH 1/8] fix 'no such file' error from make_device_config.sh
David Ahern daah...@cisco.com writes: make_device_config currently emits an error: make config-all-devices.mak GEN x86_64-softmmu/config-devices.mak /home/dsa/kvm/releases/qemu.git/make_device_config.sh: line 21: /home/dsa/kvm/releases/qemu.git/default-configs/pci.mak : No such file or directory /bin/sh does not like the file redirection for tr so change it to cat. Signed-off-by: David Ahern daah...@cisco.com --- make_device_config.sh |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/make_device_config.sh b/make_device_config.sh index 596fc5b..1ce4088 100644 --- a/make_device_config.sh +++ b/make_device_config.sh @@ -18,7 +18,7 @@ process_includes () { f=$src while [ -n $f ] ; do - f=`tr -d '\r' $f | awk '/^include / {ORS= ; print '$src_dir'/ $2}'` + f=`cat $f | tr -d '\r' | awk '/^include / {ORS= ; print '$src_dir'/ $2}'` [ $? = 0 ] || exit 1 all_includes=$all_includes $f done This sweeps the real error under the carpet: $f has a trailing space. What about: diff --git a/make_device_config.sh b/make_device_config.sh index 596fc5b..711829c 100644 --- a/make_device_config.sh +++ b/make_device_config.sh @@ -18,7 +18,7 @@ process_includes () { f=$src while [ -n $f ] ; do - f=`tr -d '\r' $f | awk '/^include / {ORS= ; print '$src_dir'/ $2}'` + f=`tr -d '\r' $f | awk '/^include / {print '$src_dir'/ $2}'` [ $? = 0 ] || exit 1 all_includes=$all_includes $f done
[Qemu-devel] Re: [PATCH 3/5] iohandlers: Allow each iohandler to be enabled/disabled individually
On 01/13/11 14:00, Amit Shah wrote: { -return assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +set_read_poll_fd_action(fd, true); +set_read_fd_action(fd, true); +set_write_fd_action(fd, true); +return 0; } I'd suggest to move the *action calls into assign_fd_handlers() so the handlers default to being enabled in all cases. This should match what most users need and thus minimize the number of *_action calls needed. cheers, Gerd
[Qemu-devel] Re: [PATCH 2/5] iohandlers: Introduce assign_fd_handlers() and remove_fd_handlers
On 01/13/11 14:00, Amit Shah wrote: This function will be used to assign fd handlers. Future commits will be enable each handler to be enabled/disabled individually. Make qemu_set_fd_handler2() a wrapper to assign_fd_handlers(). remove_fd_handlers() removes all the assigned handlers and marks the iohandler for deletion. It's a wrapper to assign_fd_handlers() with NULL handlers. Signed-off-by: Amit Shahamit.s...@redhat.com --- qemu-char.h |6 ++ vl.c| 24 +++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/qemu-char.h b/qemu-char.h index e6ee6c4..0ef83f4 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -109,6 +109,12 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr); /* async I/O support */ +int assign_fd_handlers(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque); +void remove_fd_handlers(int fd); A comment documenting the new functions would be nice. cheers, Gerd
[Qemu-devel] Re: [PATCH 3/5] iohandlers: Allow each iohandler to be enabled/disabled individually
On (Thu) Jan 13 2011 [14:55:25], Gerd Hoffmann wrote: On 01/13/11 14:00, Amit Shah wrote: { -return assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +set_read_poll_fd_action(fd, true); +set_read_fd_action(fd, true); +set_write_fd_action(fd, true); +return 0; } I'd suggest to move the *action calls into assign_fd_handlers() so the handlers default to being enabled in all cases. This should match what most users need and thus minimize the number of *_action calls needed. What may happen with that is the fd may get select()-ed for an operation that it didn't want to be put on the queue for. Amit
[Qemu-devel] Re: [PATCH 5/5] iohandlers: Add IOHandlerOps struct
Hi, +ioh-ops.fd_read_poll = ops-fd_read_poll; +ioh-ops.fd_read = ops-fd_read; +ioh-ops.fd_write = ops-fd_write; You can write this as ioh-ops = *ops btw. I guess the long-term plan (to be committed after killing the last user of the old interface) is to store a pointer to the ops struct instead of copying it? cheers, Gerd
[Qemu-devel] Re: [PATCH 0/5] iohandlers: Add support for enabling/disabling individual handlers
On 01/13/11 14:00, Amit Shah wrote: Hi, This patchset adds new interfaces to work with iohandlers. It adds: int assign_fd_handlers(int fd, IOHandlerOps *ops, void *opaque) -- Specify io handlers for an fd int remove_fd_handlers(int fd) -- Remove fd handlers for fd (mark ioh for deletion) int set_read_poll_fd_action(int fd, bool enable) -- Enable or disable the fd_read_poll fd handler int set_read_fd_action(int fd, bool enable) -- Enable or disable the fd_read fd handler int set_write_fd_action(int fd, bool enable) -- Enable or disable the fd_read fd handler A new struct, IOHandlerOps, is added, to collect all the ops together instead of passing individual ones to functions. The older function, qemu_set_fd_handler2(), is now a wrapper to assign_fd_handlers() and can be deprecated by converting the existing usage to assign_fd_handlers(). Looks good overall, just some minor nits, see replies to individual patches. cheers, Gerd
[Qemu-devel] Re: [PATCH 3/5] iohandlers: Allow each iohandler to be enabled/disabled individually
On 01/13/11 15:00, Amit Shah wrote: On (Thu) Jan 13 2011 [14:55:25], Gerd Hoffmann wrote: On 01/13/11 14:00, Amit Shah wrote: { -return assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +set_read_poll_fd_action(fd, true); +set_read_fd_action(fd, true); +set_write_fd_action(fd, true); +return 0; } I'd suggest to move the *action calls into assign_fd_handlers() so the handlers default to being enabled in all cases. This should match what most users need and thus minimize the number of *_action calls needed. What may happen with that is the fd may get select()-ed for an operation that it didn't want to be put on the queue for. I can't see such a race window given that most qemu code runs serialized anyway. If you call assign_fd_handlers() + set_write_fd_action(false) in sequence I can't see how a select call can happen inbetween ... cheers, Gerd
[Qemu-devel] Re: [PATCH 5/5] iohandlers: Add IOHandlerOps struct
On (Thu) Jan 13 2011 [15:02:37], Gerd Hoffmann wrote: Hi, +ioh-ops.fd_read_poll = ops-fd_read_poll; +ioh-ops.fd_read = ops-fd_read; +ioh-ops.fd_write = ops-fd_write; You can write this as ioh-ops = *ops btw. I guess the long-term plan (to be committed after killing the last user of the old interface) is to store a pointer to the ops struct instead of copying it? Yes, that's what I have in mind. Amit
[Qemu-devel] Re: [PATCH 2/5] iohandlers: Introduce assign_fd_handlers() and remove_fd_handlers
On (Thu) Jan 13 2011 [14:59:26], Gerd Hoffmann wrote: +int assign_fd_handlers(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque); +void remove_fd_handlers(int fd); A comment documenting the new functions would be nice. Good idea; I'll do that. Amit
[Qemu-devel] Re: [PATCH 3/5] iohandlers: Allow each iohandler to be enabled/disabled individually
On (Thu) Jan 13 2011 [15:08:51], Gerd Hoffmann wrote: On 01/13/11 15:00, Amit Shah wrote: On (Thu) Jan 13 2011 [14:55:25], Gerd Hoffmann wrote: On 01/13/11 14:00, Amit Shah wrote: { -return assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +set_read_poll_fd_action(fd, true); +set_read_fd_action(fd, true); +set_write_fd_action(fd, true); +return 0; } I'd suggest to move the *action calls into assign_fd_handlers() so the handlers default to being enabled in all cases. This should match what most users need and thus minimize the number of *_action calls needed. What may happen with that is the fd may get select()-ed for an operation that it didn't want to be put on the queue for. I can't see such a race window given that most qemu code runs serialized anyway. If you call assign_fd_handlers() + set_write_fd_action(false) in sequence I can't see how a select call can happen inbetween ... Not today, but later when we have threads doing this stuff? Should I just leave a comment to take care of this for later? Amit
Re: [Qemu-devel] [PATCH 0/8] misc cleanups for x86_64 disabling config settings
On 01/13/11 02:57, Isaku Yamahata wrote: How about creating stub functions instead of #ifdefs? something like pc-stubs.c #ifndef CONFIG_VMWARE_VGA pci_vmsvga_init() { error ... } #endif #ifndef CONFIG_... ... I wasn't trying to re-architect how the CONFIG_ is implemented; I only wanted the existing design to actually work. There are a number of CONFIG settings which exist in name, but cannot in fact be disabled. David On Wed, Jan 12, 2011 at 11:34:29PM -0700, David Ahern wrote: David Ahern (8): fix 'no such file' error from make_device_config.sh x86_64 config: fix compile for CONFIG_VMWARE_VGA=n x86_64 config: fix compile for CONFIG_PARALLEL=n remove unused parallel_* variables from pc.c x86_64 config: fix compile for CONFIG_NE2000_ISA=n x86_64 config: fix compile for CONFIG_VGA_ISA=n x86_64 config: fix compile for CONFIG_IDE_ISA=n x86_64 config: fix compile for CONFIG_FDC=n hw/pc.c | 21 ++--- hw/pc_piix.c | 11 +++ make_device_config.sh |2 +- 3 files changed, 30 insertions(+), 4 deletions(-) -- 1.7.3.4
Re: [Qemu-devel] [PATCH 1/8] fix 'no such file' error from make_device_config.sh
On 01/13/11 06:43, Markus Armbruster wrote: David Ahern daah...@cisco.com writes: make_device_config currently emits an error: make config-all-devices.mak GEN x86_64-softmmu/config-devices.mak /home/dsa/kvm/releases/qemu.git/make_device_config.sh: line 21: /home/dsa/kvm/releases/qemu.git/default-configs/pci.mak : No such file or directory /bin/sh does not like the file redirection for tr so change it to cat. Signed-off-by: David Ahern daah...@cisco.com --- make_device_config.sh |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/make_device_config.sh b/make_device_config.sh index 596fc5b..1ce4088 100644 --- a/make_device_config.sh +++ b/make_device_config.sh @@ -18,7 +18,7 @@ process_includes () { f=$src while [ -n $f ] ; do - f=`tr -d '\r' $f | awk '/^include / {ORS= ; print '$src_dir'/ $2}'` + f=`cat $f | tr -d '\r' | awk '/^include / {ORS= ; print '$src_dir'/ $2}'` [ $? = 0 ] || exit 1 all_includes=$all_includes $f done This sweeps the real error under the carpet: $f has a trailing space. What about: diff --git a/make_device_config.sh b/make_device_config.sh index 596fc5b..711829c 100644 --- a/make_device_config.sh +++ b/make_device_config.sh @@ -18,7 +18,7 @@ process_includes () { f=$src while [ -n $f ] ; do - f=`tr -d '\r' $f | awk '/^include / {ORS= ; print '$src_dir'/ $2}'` + f=`tr -d '\r' $f | awk '/^include / {print '$src_dir'/ $2}'` [ $? = 0 ] || exit 1 all_includes=$all_includes $f done That works too. Any idea why the '%/config-devices.mak' rule does not work for a build directory != src directory? e.g., src=/my/qemu.git, build=/tmp/build-qemu x86_64-softmmu/config-devices.mak is not created, so config-all-devices.mak is empty and the build blows up. David
[Qemu-devel] Re: [PATCH 3/5] iohandlers: Allow each iohandler to be enabled/disabled individually
Hi, I can't see such a race window given that most qemu code runs serialized anyway. If you call assign_fd_handlers() + set_write_fd_action(false) in sequence I can't see how a select call can happen inbetween ... Not today, but later when we have threads doing this stuff? Unlikely I think. Seems we will go offload specific tasks to threads using threadlets (especially in the block layer), but I expect the main even loop will not be splitted into multiple threads. Should I just leave a comment to take care of this for later? Thats fine I guess. Or maybe add arguments to assign_fd_handlers() with the initial state. cheers, Gerd
Re: [Qemu-devel] Re: [PATCH] scsi-generic: bugfixes for 'SCSIRequest' conversion
Am 23.12.2010 22:58, schrieb Nicholas A. Bellinger: On Tue, 2010-12-21 at 12:49 +1100, Benjamin Herrenschmidt wrote: Yep, so it appears that commit 89c0f6438d16 did introduce the bogus 'double complete' in scsi_read_complete, which I think was intended to handle residual counts for TYPE_TYPE... /* Cancel a pending data transfer. */ @@ -251,6 +257,8 @@ static void scsi_read_complete(void * opaque, int ret) r-len = -1; s-completion(s-opaque, SCSI_REASON_DATA, r-tag, len); +if (len == 0) +scsi_command_complete(r, 0); } I am currently under the assumption for this and bsg_read_complete that s-completion(..., len) is handling the residual count back to block. Is this correct..? So I just debugged a crash where loading my vscsi driver kills qemu (segfault) after trying to complete a command twice with scsi-generic. Removing the above hunk fixes it. So this is a genuine fix that should be applied (asap even :-) Hi Ben, Thanks for verifying this one. Kevin, please make sure this original patch to drop the bogus double complete gets picked up. Wasn't the original patch NACKed by Hannes in parts? Can you re-post a patch that includes only this specific fix? Kevin
[Qemu-devel] [PATCH v2 0/5] iohandlers: Add support for enabling/disabling individual handlers
Hi, This patchset adds new interfaces to work with iohandlers. It adds: int assign_fd_handlers(int fd, IOHandlerOps *ops, void *opaque) -- Specify io handlers for an fd int remove_fd_handlers(int fd) -- Remove fd handlers for fd (mark ioh for deletion) int set_read_poll_fd_action(int fd, bool enable) -- Enable or disable the fd_read_poll fd handler int set_read_fd_action(int fd, bool enable) -- Enable or disable the fd_read fd handler int set_write_fd_action(int fd, bool enable) -- Enable or disable the fd_read fd handler A new struct, IOHandlerOps, is added, to collect all the ops together instead of passing individual ones to functions. The older function, qemu_set_fd_handler2(), is now a wrapper to assign_fd_handlers() and can be deprecated by converting the existing usage to assign_fd_handlers(). v2: Address comments from Gerd: - add comments to new interfaces - enable all specified handlers by default in assign_fd_handlers() - Add comments for TODO items on deprecation of older interfaces. Please apply. Amit Shah (5): iohandlers: Avoid code duplication iohandlers: Introduce assign_fd_handlers() and remove_fd_handlers iohandlers: Allow each iohandler to be enabled/disabled individually iohandlers: Enable an iohandler only if the associated handler exists iohandlers: Add IOHandlerOps struct qemu-char.h |7 ++ vl.c| 197 -- 2 files changed, 170 insertions(+), 34 deletions(-) -- 1.7.3.4
[Qemu-devel] [PATCH v2 5/5] iohandlers: Add IOHandlerOps struct
Collect all the handlers in a IOHandlerOps struct instead of being passed one at a time to each function. Signed-off-by: Amit Shah amit.s...@redhat.com --- qemu-char.h |7 ++- vl.c| 56 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/qemu-char.h b/qemu-char.h index e88a108..ebf9cd1 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -108,12 +108,9 @@ QString *qemu_chr_mem_to_qs(CharDriverState *chr); size_t qemu_chr_mem_osize(const CharDriverState *chr); /* async I/O support */ +typedef struct IOHandlerOps IOHandlerOps; -int assign_fd_handlers(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque); +int assign_fd_handlers(int fd, const IOHandlerOps *ops, void *opaque); void remove_fd_handlers(int fd); int set_read_poll_fd_action(int fd, bool enable); int set_read_fd_action(int fd, bool enable); diff --git a/vl.c b/vl.c index 4aa4158..a98256c 100644 --- a/vl.c +++ b/vl.c @@ -1007,11 +1007,20 @@ void pcmcia_info(Monitor *mon) /***/ /* I/O handling */ -typedef struct IOHandlerRecord { -int fd; +struct IOHandlerOps { IOCanReadHandler *fd_read_poll; IOHandler *fd_read; IOHandler *fd_write; +}; + +typedef struct IOHandlerRecord { +int fd; +/* + * TODO: once the users of qemu_set_fd_handler*() functions have + * been removed, just store the ops pointer instead of copying + * over each element here. + */ +IOHandlerOps ops; int deleted; void *opaque; bool read_poll_enabled; @@ -1025,6 +1034,10 @@ typedef struct IOHandlerRecord { static QLIST_HEAD(, IOHandlerRecord) io_handlers = QLIST_HEAD_INITIALIZER(io_handlers); +static const IOHandlerOps null_ioh_ops = { +/* All ops are NULL */ +}; + static IOHandlerRecord *get_iohandler(int fd) { IOHandlerRecord *ioh; @@ -1051,7 +1064,7 @@ int set_read_poll_fd_action(int fd, bool enable) } ioh-read_poll_enabled = false; -if (enable ioh-fd_read_poll) { +if (enable ioh-ops.fd_read_poll) { ioh-read_poll_enabled = true; } @@ -1072,7 +1085,7 @@ int set_read_fd_action(int fd, bool enable) } ioh-read_enabled = false; -if (enable ioh-fd_read) { +if (enable ioh-ops.fd_read) { ioh-read_enabled = true; } @@ -1093,7 +1106,7 @@ int set_write_fd_action(int fd, bool enable) } ioh-write_enabled = false; -if (enable ioh-fd_write) { +if (enable ioh-ops.fd_write) { ioh-write_enabled = true; } @@ -1106,17 +1119,16 @@ int set_write_fd_action(int fd, bool enable) * XXX: fd_read_poll should be suppressed, but an API change is * necessary in the character devices to suppress fd_can_read(). */ -int assign_fd_handlers(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) +int assign_fd_handlers(int fd, const IOHandlerOps *ops, void *opaque) { IOHandlerRecord *ioh; ioh = get_iohandler(fd); -if (ioh !fd_read !fd_write) { +if (!ops) { +ops = null_ioh_ops; +} +if (ioh !ops-fd_read !ops-fd_write) { ioh-deleted = 1; return 0; } @@ -1127,9 +1139,7 @@ int assign_fd_handlers(int fd, ioh-fd = fd; } -ioh-fd_read_poll = fd_read_poll; -ioh-fd_read = fd_read; -ioh-fd_write = fd_write; +ioh-ops = *ops; ioh-opaque = opaque; ioh-deleted = 0; @@ -1156,12 +1166,13 @@ int assign_fd_handlers(int fd, */ void remove_fd_handlers(int fd) { -assign_fd_handlers(fd, NULL, NULL, NULL, NULL); +assign_fd_handlers(fd, NULL, NULL); } /* * TODO: Deprecate these two function calls in favour of - * assign_fd_handlers(). + * assign_fd_handlers(). When that happens, also see the TODO in the + * IOHandlerRecord struct above. */ int qemu_set_fd_handler2(int fd, IOCanReadHandler *fd_read_poll, @@ -1169,7 +1180,12 @@ int qemu_set_fd_handler2(int fd, IOHandler *fd_write, void *opaque) { -return assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +IOHandlerOps ops; + +ops.fd_read_poll = fd_read_poll; +ops.fd_read = fd_read; +ops.fd_write = fd_write; +return assign_fd_handlers(fd, ops, opaque); } int qemu_set_fd_handler(int fd, @@ -1434,7 +1450,7 @@ void main_loop_wait(int nonblocking) if (ioh-deleted) continue; if (ioh-read_enabled -(!ioh-read_poll_enabled || ioh-fd_read_poll(ioh-opaque) != 0)) { +(!ioh-read_poll_enabled || ioh-ops.fd_read_poll(ioh-opaque) != 0)) { FD_SET(ioh-fd, rfds); if (ioh-fd
Re: spice vdagent protocol, was Re: [Qemu-devel] KVM call minutes for Jan 11
On Tue, 2011-01-11 at 20:33 +0200, Alon Levy wrote: Spice guest agent: - virt agent, matahari, spice agent...what is in spice agent? - spice char device - mouse, copy 'n paste, screen resolution change - could be generic (at least input and copy/paste) - send protocol details of what is being sent - need to look at how difficult it is to split it out from spice (how to split out in qemu vs. libspice) - goal to converge on common framework - more discussion on char device vs. protocol - eg. mouse_set breaks if mouse channel is part pv and part spice specific - Alon will send link to protocol and try to propose new interfaces http://spice-space.org/page/Whiteboard/AgentProtocol That's the corrent documentation. Notably the clipboard is a todo there, I'll try to get that filled in. I'll continue this discussion on a separate thread later. Thanks for sending this out Alon. The use cases you have outlined are very similar to the ones we have for virtagent. The main differences I can see so far are the the data encoding strategy and the spice agent's method for delivery of events (mouse, etc). Virtagent implements an RPC interface and uses xmlrpc-c to encode data in XML. This approach seems more general-purpose, extensible and easier to manage over the long term than relying on a custom binary representation. As for event delivery, virtagent does not yet have an interface to allow external programs to subscribe to events. I am sure this can be done in a generic way that is backwards-compatible with the current spice architecture. Such an interface should allow arbitrary programs to subscribe to events but have no dependencies on those programs. I am not sure if something like D-Bus would be appropriate for Linux guests. We'd need to consider Windows too. I see no reason why the core qemu use cases (shutdown, exec, copyfile) and the spice use cases (mouse, copy-paste, graphics reconfiguration) cannot (and should not) be satisfied by a single agent. Going forward, I think we'd need to agree on the wire protocol and guest-side event subscription. Thoughts? -- Thanks, Adam
[Qemu-devel] [PATCH v2 1/5] iohandlers: Avoid code duplication
Add a get_iohandler() function instead of looking up the ioh twice in qemu_set_fd_handler2(). Signed-off-by: Amit Shah amit.s...@redhat.com --- vl.c | 44 ++-- 1 files changed, 26 insertions(+), 18 deletions(-) diff --git a/vl.c b/vl.c index 0292184..9e365f6 100644 --- a/vl.c +++ b/vl.c @@ -1022,6 +1022,17 @@ typedef struct IOHandlerRecord { static QLIST_HEAD(, IOHandlerRecord) io_handlers = QLIST_HEAD_INITIALIZER(io_handlers); +static IOHandlerRecord *get_iohandler(int fd) +{ +IOHandlerRecord *ioh; + +QLIST_FOREACH(ioh, io_handlers, next) { +if (ioh-fd == fd) { +return ioh; +} +} +return NULL; +} /* XXX: fd_read_poll should be suppressed, but an API change is necessary in the character devices to suppress fd_can_read(). */ @@ -1033,28 +1044,25 @@ int qemu_set_fd_handler2(int fd, { IOHandlerRecord *ioh; -if (!fd_read !fd_write) { -QLIST_FOREACH(ioh, io_handlers, next) { -if (ioh-fd == fd) { -ioh-deleted = 1; -break; -} -} -} else { -QLIST_FOREACH(ioh, io_handlers, next) { -if (ioh-fd == fd) -goto found; -} +ioh = get_iohandler(fd); + +if (ioh !fd_read !fd_write) { +ioh-deleted = 1; +return 0; +} + +if (!ioh) { ioh = qemu_mallocz(sizeof(IOHandlerRecord)); QLIST_INSERT_HEAD(io_handlers, ioh, next); -found: + ioh-fd = fd; -ioh-fd_read_poll = fd_read_poll; -ioh-fd_read = fd_read; -ioh-fd_write = fd_write; -ioh-opaque = opaque; -ioh-deleted = 0; } +ioh-fd_read_poll = fd_read_poll; +ioh-fd_read = fd_read; +ioh-fd_write = fd_write; +ioh-opaque = opaque; +ioh-deleted = 0; + return 0; } -- 1.7.3.4
[Qemu-devel] [PATCH v2 2/5] iohandlers: Introduce assign_fd_handlers() and remove_fd_handlers
This function will be used to assign fd handlers. Future commits will be enable each handler to be enabled/disabled individually. Make qemu_set_fd_handler2() a wrapper to assign_fd_handlers(). remove_fd_handlers() removes all the assigned handlers and marks the iohandler for deletion. It's a wrapper to assign_fd_handlers() with NULL handlers. Signed-off-by: Amit Shah amit.s...@redhat.com --- qemu-char.h |6 ++ vl.c| 36 +--- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/qemu-char.h b/qemu-char.h index e6ee6c4..0ef83f4 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -109,6 +109,12 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr); /* async I/O support */ +int assign_fd_handlers(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque); +void remove_fd_handlers(int fd); int qemu_set_fd_handler2(int fd, IOCanReadHandler *fd_read_poll, IOHandler *fd_read, diff --git a/vl.c b/vl.c index 9e365f6..30256e1 100644 --- a/vl.c +++ b/vl.c @@ -1034,13 +1034,17 @@ static IOHandlerRecord *get_iohandler(int fd) return NULL; } -/* XXX: fd_read_poll should be suppressed, but an API change is - necessary in the character devices to suppress fd_can_read(). */ -int qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) +/* + * Specify function pointers for the various IOHandlers for an fd here. + * + * XXX: fd_read_poll should be suppressed, but an API change is + * necessary in the character devices to suppress fd_can_read(). + */ +int assign_fd_handlers(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) { IOHandlerRecord *ioh; @@ -1066,6 +1070,24 @@ int qemu_set_fd_handler2(int fd, return 0; } +/* + * Remove IO handlers for fd. Marks the IOHandler, if one exists, for + * deletion. + */ +void remove_fd_handlers(int fd) +{ +assign_fd_handlers(fd, NULL, NULL, NULL, NULL); +} + +int qemu_set_fd_handler2(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) +{ +return assign_fd_handlers(fd, fd_read_poll, fd_read, fd_write, opaque); +} + int qemu_set_fd_handler(int fd, IOHandler *fd_read, IOHandler *fd_write, -- 1.7.3.4
[Qemu-devel] [PATCH v2 4/5] iohandlers: Enable an iohandler only if the associated handler exists
If an iohandler is asked to be enabled but the handler doesn't exist, don't enable the handler. This can be used to simplify the conditions in main_loop_wait(). Signed-off-by: Amit Shah amit.s...@redhat.com --- vl.c | 29 - 1 files changed, 20 insertions(+), 9 deletions(-) diff --git a/vl.c b/vl.c index b9c902a..4aa4158 100644 --- a/vl.c +++ b/vl.c @@ -1049,7 +1049,11 @@ int set_read_poll_fd_action(int fd, bool enable) if (!ioh) { return -1; } -ioh-read_poll_enabled = enable; + +ioh-read_poll_enabled = false; +if (enable ioh-fd_read_poll) { +ioh-read_poll_enabled = true; +} return 0; } @@ -1066,7 +1070,11 @@ int set_read_fd_action(int fd, bool enable) if (!ioh) { return -1; } -ioh-read_enabled = enable; + +ioh-read_enabled = false; +if (enable ioh-fd_read) { +ioh-read_enabled = true; +} return 0; } @@ -1083,7 +1091,11 @@ int set_write_fd_action(int fd, bool enable) if (!ioh) { return -1; } -ioh-write_enabled = enable; + +ioh-write_enabled = false; +if (enable ioh-fd_write) { +ioh-write_enabled = true; +} return 0; } @@ -1421,14 +1433,13 @@ void main_loop_wait(int nonblocking) QLIST_FOREACH(ioh, io_handlers, next) { if (ioh-deleted) continue; -if (ioh-fd_read ioh-read_enabled -(!ioh-fd_read_poll || - (!ioh-read_poll_enabled || ioh-fd_read_poll(ioh-opaque) != 0))) { +if (ioh-read_enabled +(!ioh-read_poll_enabled || ioh-fd_read_poll(ioh-opaque) != 0)) { FD_SET(ioh-fd, rfds); if (ioh-fd nfds) nfds = ioh-fd; } -if (ioh-fd_write ioh-write_enabled) { +if (ioh-write_enabled) { FD_SET(ioh-fd, wfds); if (ioh-fd nfds) nfds = ioh-fd; @@ -1447,10 +1458,10 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) { -if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd, rfds)) { +if (!ioh-deleted ioh-read_enabled FD_ISSET(ioh-fd, rfds)) { ioh-fd_read(ioh-opaque); } -if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd, wfds)) { +if (!ioh-deleted ioh-write_enabled FD_ISSET(ioh-fd, wfds)) { ioh-fd_write(ioh-opaque); } -- 1.7.3.4
[Qemu-devel] [PATCH v2 3/5] iohandlers: Allow each iohandler to be enabled/disabled individually
Each iohandler for an fd can now be individually enabled or disabled. Signed-off-by: Amit Shah amit.s...@redhat.com --- qemu-char.h |4 +++ vl.c| 78 -- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/qemu-char.h b/qemu-char.h index 0ef83f4..e88a108 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -115,6 +115,10 @@ int assign_fd_handlers(int fd, IOHandler *fd_write, void *opaque); void remove_fd_handlers(int fd); +int set_read_poll_fd_action(int fd, bool enable); +int set_read_fd_action(int fd, bool enable); +int set_write_fd_action(int fd, bool enable); + int qemu_set_fd_handler2(int fd, IOCanReadHandler *fd_read_poll, IOHandler *fd_read, diff --git a/vl.c b/vl.c index 30256e1..b9c902a 100644 --- a/vl.c +++ b/vl.c @@ -1014,6 +1014,9 @@ typedef struct IOHandlerRecord { IOHandler *fd_write; int deleted; void *opaque; +bool read_poll_enabled; +bool read_enabled; +bool write_enabled; /* temporary data */ struct pollfd *ufd; QLIST_ENTRY(IOHandlerRecord) next; @@ -1035,6 +1038,57 @@ static IOHandlerRecord *get_iohandler(int fd) } /* + * Enable the fd_read_poll handler for fd if the fd_read_poll handler exists. + */ +int set_read_poll_fd_action(int fd, bool enable) +{ +IOHandlerRecord *ioh; + +ioh = get_iohandler(fd); + +if (!ioh) { +return -1; +} +ioh-read_poll_enabled = enable; + +return 0; +} + +/* + * Enable the fd_read handler for fd if the fd_read handler exists. + */ +int set_read_fd_action(int fd, bool enable) +{ +IOHandlerRecord *ioh; + +ioh = get_iohandler(fd); + +if (!ioh) { +return -1; +} +ioh-read_enabled = enable; + +return 0; +} + +/* + * Enable the fd_write handler for fd if the fd_write handler exists. + */ +int set_write_fd_action(int fd, bool enable) +{ +IOHandlerRecord *ioh; + +ioh = get_iohandler(fd); + +if (!ioh) { +return -1; +} +ioh-write_enabled = enable; + +return 0; +} + +/* * Specify function pointers for the various IOHandlers for an fd here. * * XXX: fd_read_poll should be suppressed, but an API change is @@ -1067,6 +1121,20 @@ int assign_fd_handlers(int fd, ioh-opaque = opaque; ioh-deleted = 0; +/* + * To maintain compatibility with the callers that expect all + * handlers to be enabled. Callers that wish for some handlers + * not to be enabled right away should ensure they call + * set_xx_fd_action(fd, false) after this call. + * + * Note: if gets threading and one day is capable of running + * main_loop_wait() in parallel to this function, ensure this call + * and any later set_xx_fd_action() calls can execute atomically. + */ +set_read_poll_fd_action(fd, true); +set_read_fd_action(fd, true); +set_write_fd_action(fd, true); + return 0; } @@ -1079,6 +1147,10 @@ void remove_fd_handlers(int fd) assign_fd_handlers(fd, NULL, NULL, NULL, NULL); } +/* + * TODO: Deprecate these two function calls in favour of + * assign_fd_handlers(). + */ int qemu_set_fd_handler2(int fd, IOCanReadHandler *fd_read_poll, IOHandler *fd_read, @@ -1349,14 +1421,14 @@ void main_loop_wait(int nonblocking) QLIST_FOREACH(ioh, io_handlers, next) { if (ioh-deleted) continue; -if (ioh-fd_read +if (ioh-fd_read ioh-read_enabled (!ioh-fd_read_poll || - ioh-fd_read_poll(ioh-opaque) != 0)) { + (!ioh-read_poll_enabled || ioh-fd_read_poll(ioh-opaque) != 0))) { FD_SET(ioh-fd, rfds); if (ioh-fd nfds) nfds = ioh-fd; } -if (ioh-fd_write) { +if (ioh-fd_write ioh-write_enabled) { FD_SET(ioh-fd, wfds); if (ioh-fd nfds) nfds = ioh-fd; -- 1.7.3.4
[Qemu-devel] No rule to make target ../libhw32/virtio.o
Hi, I'm building current Git master (SHA1:facf1a60) using latest MingW32 on Windows Vista and compilation fails with the following error: g:/src/qemu/_git/master/disas.c: In function 'generic_print_address': g:/src/qemu/_git/master/disas.c:65:5: warning: 'I' flag used with '%x' gnu_printf format g:/src/qemu/_git/master/disas.c:65:5: warning: format '%I64x' expects type 'unsigned int', but argument 3 has type 'bfd_vma' make[1]: *** No rule to make target `../libhw32/virtio.o', needed by `qemu.exe'. Stop. make: *** [subdir-i386-softmmu] Error 2 Here is my ./configure summary $ ./configure --prefix=/g/src/qemu/_git/install --enable-sdl Install prefix/g/src//qemu/_git/install BIOS directory/g/src//qemu/_git/install binary directory /g/src//qemu/_git/install config directory /g/src//qemu/_git/install Source path /g/src/qemu/_git/master C compilergcc Host C compiler gcc CFLAGS-O2 -g QEMU_CFLAGS -m32 -D__USE_MINGW_ANSI_STDIO=1 -DWIN32_LEAN_AND_MEAN -DWINVER=0x501 -I. -I$(SRC_PATH) -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fstack-protector-all -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits LDFLAGS -Wl,--nxcompat -Wl,--no-seh -Wl,--dynamicbase -Wl,--warn-common -m32 -g make make install install host CPU i386 host big endian no target list i386-softmmu x86_64-softmmu arm-softmmu cris-softmmu m68k-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu ppc-softmmu ppcemb-softmmu ppc64-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu sparc64-softmmu tcg debug enabled no Mon debug enabled no gprof enabled no sparse enabledno strip binariesyes profiler no static build no -Werror enabled no SDL support yes curses supportno curl support no check support no mingw32 support yes Audio drivers winwave Extra audio cards ac97 es1370 sb16 hda Block whitelist Mixer emulation no VNC TLS support no VNC SASL support no VNC JPEG support no VNC PNG support no VNC threadno xen support no brlapi supportno bluez supportno Documentation no NPTL support no GUEST_BASEyes PIE user targets no vde support no IO thread no Linux AIO support no ATTR/XATTR support no Install blobs yes KVM support no fdt support no preadv supportno fdatasync no madvise no posix_madvise no uuid support no vhost-net support no Trace backend nop Trace output file trace-pid spice support no rbd support no xfsctl supportno Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org Member of ACCU, http://accu.org
[Qemu-devel] Re: [PATCH v2 0/5] iohandlers: Add support for enabling/disabling individual handlers
On 01/13/11 16:00, Amit Shah wrote: This patchset adds new interfaces to work with iohandlers. It adds: int assign_fd_handlers(int fd, IOHandlerOps *ops, void *opaque) -- Specify io handlers for an fd int remove_fd_handlers(int fd) -- Remove fd handlers for fd (mark ioh for deletion) int set_read_poll_fd_action(int fd, bool enable) -- Enable or disable the fd_read_poll fd handler int set_read_fd_action(int fd, bool enable) -- Enable or disable the fd_read fd handler int set_write_fd_action(int fd, bool enable) -- Enable or disable the fd_read fd handler A new struct, IOHandlerOps, is added, to collect all the ops together instead of passing individual ones to functions. The older function, qemu_set_fd_handler2(), is now a wrapper to assign_fd_handlers() and can be deprecated by converting the existing usage to assign_fd_handlers(). Looks good now. Acked-by: Gerd Hoffmann kra...@redhat.com cheers, Gerd
Re: [Qemu-devel] No rule to make target ../libhw32/virtio.o
On 13/01/11 15:09, Mateusz Loskot wrote: Hi, I'm building current Git master (SHA1:facf1a60) using latest MingW32 on Windows Vista and compilation fails with the following error: g:/src/qemu/_git/master/disas.c: In function 'generic_print_address': g:/src/qemu/_git/master/disas.c:65:5: warning: 'I' flag used with '%x' gnu_printf format g:/src/qemu/_git/master/disas.c:65:5: warning: format '%I64x' expects type 'unsigned int', but argument 3 has type 'bfd_vma' make[1]: *** No rule to make target `../libhw32/virtio.o', needed by `qemu.exe'. Stop. make: *** [subdir-i386-softmmu] Error 2 Hi Mateusz, Good to hear from you again. On a separate note, as a Windows user have you tried using the mingw-w64 compiler (http://mingw-w64.sourceforge.net/) to build qemu instead? While the name suggests only a 64-bit compiler, the basic installation consists of both 32 and 64 bit compilers, plus the team there are currently very active and in my experience a lot more responsive when it comes to fixing any problems that may arise. HTH, Mark. -- Mark Cave-Ayland - Senior Technical Architect PostgreSQL - PostGIS Sirius Corporation plc - control through freedom http://www.siriusit.co.uk t: +44 870 608 0063 Sirius Labs: http://www.siriusit.co.uk/labs
[Qemu-devel] Re: Linux as VirtualBox quest OS with QEMU running Solaris
On 07/01/11 17:28, Mateusz Loskot wrote: I'm wondering if the following setup would work at all: 1. Quad-core workstation with 16GB RAM with Windows Vista 64-bit as host OS 2. The Windows runs VirtualBox with Linux installed as guest OS. 3. The Linux guest OS runs QEMU 4. QEMU runs Solaris (SPARC) Quick summary of results with the original idea: So, instead of Solaris I installed NetBSD 5.1/SPARC under QEMU. I performed the installation using QEMU 0.13 on Windows Vista. Next, I copied .img file from Vista to Linux Ubuntu (64-bit) I also cloned QEMU Git repo. built QEMU from source and installed. Finally, I successfully booted the NetBSD system on Linux guest running under VirtualBox hosted on Windows Vista: http://www.flickr.com/photos/mloskot/5352200198/ The idea seems to work. I haven't solved the networking problem with configuring the only existing iface=le0 with external DHCP, but that's another story. Folks, thanks for help! Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org Member of ACCU, http://accu.org
[Qemu-devel] [PATCH 1/3] mainstone: fix name of the allocated memory for roms
Mainstone board has two flash chips (emulated by two ram regions), however currently code tries to allocate them with the same name, which fails. Fix that to make mainstone emulation work again. Signed-off-by: Dmitry Eremin-Solenikov dbarysh...@gmail.com --- hw/mainstone.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/hw/mainstone.c b/hw/mainstone.c index efa2959..d8e41cf 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -106,7 +106,8 @@ static void mainstone_common_init(ram_addr_t ram_size, } if (!pflash_cfi01_register(mainstone_flash_base[i], - qemu_ram_alloc(NULL, mainstone.flash, + qemu_ram_alloc(NULL, i ? mainstone.flash1 : + mainstone.flash0, MAINSTONE_FLASH), dinfo-bdrv, sector_len, MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0, -- 1.7.2.3
[Qemu-devel] [PATCH 2/3] Scoop: fix access to registers from second instance
Second instance of scoop contains registers shifted to 0x40 from the start of the page. Instead of messing with register mapping, just limit register address to 0x00..0x3f. Signed-off-by: Dmitry Eremin-Solenikov dbarysh...@gmail.com --- hw/zaurus.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/zaurus.c b/hw/zaurus.c index 54ec3f0..36be94a 100644 --- a/hw/zaurus.c +++ b/hw/zaurus.c @@ -70,7 +70,7 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr) { ScoopInfo *s = (ScoopInfo *) opaque; -switch (addr) { +switch (addr 0x3f) { case SCOOP_MCR: return s-mcr; case SCOOP_CDR: @@ -104,7 +104,7 @@ static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) ScoopInfo *s = (ScoopInfo *) opaque; value = 0x; -switch (addr) { +switch (addr 0x3f) { case SCOOP_MCR: s-mcr = value; break; -- 1.7.2.3
[Qemu-devel] [PATCH 3/3] pxa2xx: fix vmstate_pxa2xx_i2c
vmstate_pxa2xx_i2c incorrectly recursed to itself instead of going to store slave device. Fix that stop stop qemu from segfaulting during savevm for pxa2xx-based devices. Signed-off-by: Dmitry Eremin-Solenikov dbarysh...@gmail.com --- hw/pxa2xx.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index ab524a7..6e72a5c 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -1476,7 +1476,7 @@ static const VMStateDescription vmstate_pxa2xx_i2c = { VMSTATE_UINT8(ibmr, PXA2xxI2CState), VMSTATE_UINT8(data, PXA2xxI2CState), VMSTATE_STRUCT_POINTER(slave, PXA2xxI2CState, - vmstate_pxa2xx_i2c, PXA2xxI2CSlaveState *), + vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState *), VMSTATE_END_OF_LIST() } }; -- 1.7.2.3
Re: [Qemu-devel] [PATCH 1/3] ide: factor dma handling helpers
Am 20.12.2010 13:45, schrieb Christoph Hellwig: Factor the DMA I/O path that is duplicated between read and write commands, into common helpers using the s-is_read flag added for the macio ATA controller. Signed-off-by: Christoph Hellwig h...@lst.de Thanks, applied all to the block branch. Kevin
Re: [Qemu-devel] paravirtual mouse/tablet
On 01/13/2011 04:19 AM, Gerd Hoffmann wrote: Hi, Just throwing a quick writeup into the ring to kickstart the design discussion ;) cheers, Gerd #ifndef __QEMU_PVTABLET__ #define __QEMU_PVTABLET__ 1 /* * qemu patavirtual tablet interface */ #includeinttypes.h /* our virtio-serial channel */ #define QEMU_PVTABLET_NAME org.qemu.pvtablet.0 enum qemu_pvtablet_buttons { QEMU_PVTABLET_BTN_LEFT, QEMU_PVTABLET_BTN_RIGHT, QEMU_PVTABLET_BTN_MIDDLE, /* * we can handle up to 32 buttons although * not every has a individual name;) */ }; /* send button down+up events */ typedef struct qemu_pvtablet_button { uint32_t button; uint32_t mask; } qemu_pvtablet_button; /* send pointer move events */ typedef struct qemu_pvtablet_position { uint32_t pos_x; /* range: 0 - 0x */ uint32_t pos_y; /* range: 0 - 0x */ } qemu_pvtablet_position; Let's add feature negotiation and not hardcode the resolution. typedef enum qemu_pvtablet_features { /* None yet */ }; /* host-guest, sent before any other events */ typedef struct qemu_pvtablet_init { uint32_t res_x; /* x axis resolution */ uint32_t res_y; /* y axis resolution */ uint32_t features; /* qemu_pvtablet_features */ } qemu_pvtablet_init; /* guest-host, sent after pvtablet_init. host will not send additional messages until this is received */ typedef struct qemu_pvtablet_ack { uint32_t features; /* qemu_pvtable_features */ }; enum qemu_pvtablet_type { QEMU_PVTABLET_MSG_MOVE, /* qemu_pvtablet_position */ QEMU_PVTABLET_MSG_BTN_DOWN, /* qemu_pvtablet_button */ QEMU_PVTABLET_MSG_BTN_UP, /* qemu_pvtablet_button */ QEMU_PVTABLET_MSG_INIT, /* qemu_pvtable_init */ QEMU_PVTABLE_MSG_ACK, /* qemu_pvtable_ack */ Regards, Anthony Liguori }; typedef struct qemu_pvtablet_message { uint32_t size;/* whole message size */ uint32_t type;/* qemu_pvtablet_type */ uint64_t tv_secs; uint64_t tv_usecs; union { qemu_pvtablet_position position; qemu_pvtablet_button button; qemu_pvtablet_display display; } m; } qemu_pvtablet_message; #endif /* __QEMU_PVTABLET__ */
Re: [Qemu-devel] Re: [Spice-devel] paravirtual mouse/tablet
On 01/13/2011 05:51 AM, Gerd Hoffmann wrote: On 01/13/11 12:01, Stefan Hajnoczi wrote: Can you elaborate how the spice display channel comes into play? On a physical machine you just have input devices with no notion of display. It's up to the windowing system to process input events and handle multihead. Why does a pv tablet tie itself to a display channel? You have two qxl devices, each linked to a spice display channel. The spice client will open one window for each channel. The mouse position is a triple consisting of (x, y, window/channel). Would be slightly cleaner to have multiple devices. That avoids breaking the abstraction and sets us up to handling multiple mice properly in the future. That maybe implies that we need an offscreen coordinate for the mouse so that you can hide the mouse when it leaves one window. Only the guest knows how it configured the displays, so only the guest is able to create a correct pointer position out of this data. So the X-Server would combine this data with its virtual display configuration (basically adding the display offset to the coordinates), then send this as event to the X clients. What about mouse wheel (aka z axis motion)? It's covered. That are really just button presses at mouse protocol level (buttons 4+5). We can add them to the enum to have fancy names for them, that is just the sugar on top though. If we add features, then we can deal with things like an additional axis to cover pressure sensitive touchpads. Not worth designing now but a feature negotiation gives us the option later. Regards, Anthony Liguori cheers, Gerd
Re: [Qemu-devel] Linux as VirtualBox quest OS with QEMU running Solaris
On 13/01/11 12:40, Mateusz Loskot wrote: On 13/01/11 10:13, Michal Suchanek wrote: On 13 January 2011 00:34, Mateusz Loskotmate...@loskot.net wrote: On 12/01/11 17:15, Mateusz Loskot wrote: On 12/01/11 16:48, Michal Suchanek wrote: On 12 January 2011 16:21, Mateusz Loskotmate...@loskot.net wrote: Thinking of future, could anyone estimate when it will be possible to boot Solaris 10 installation from ISO disks, if at all? To summary, what OS alternative for SPARC we have got apart from Debian which are known to work under QEMU? *BSD systems? I can run NetBSD sparc install CD just fine. It supports sparc32 in the latest release. Thanks. Great, I'll try. One of the problems I found with Debian Etch is the package repositories are no longer supported and the installer can easily mess with those for Lenny. The only solution is to have all CDs for Etch available and run complete offline installation. I guess the NetBSD option is more up to date here. I have tried the recent NetBSD and it boots without problems, however I can't configure networking to install via FTP/HTTP. Strangely, I don't get question about DHCP. Yes, that's probably an issue with the sparc installer script. However, the sparccd has all the sets so you can easily install from the CD. Once installed you can set up dhclient. Thanks for the hint. Indeed, I managed to install the base system from CD and boot from QEMU image. I performed post-install configuration according to the NetBSD guide and I have dhclient=YET in /etc/rc.conf. Certainly, I mean, dhclient=YES The only problem I find is that I'm unable to configure any other networking than the user mode with QEMU network 10.0.2.0. Learned about the networking better and managed to connect (SSH) to my emulated NetBSD installation from host system (Windows Vista) thanks to ports redirection as explained here: http://en.wikibooks.org/wiki/QEMU/Networking I should have read the docs more carefully. Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org Member of ACCU, http://accu.org
Re: [Qemu-devel] No rule to make target ../libhw32/virtio.o
On 13/01/11 15:24, Mark Cave-Ayland wrote: On 13/01/11 15:09, Mateusz Loskot wrote: Hi, I'm building current Git master (SHA1:facf1a60) using latest MingW32 on Windows Vista and compilation fails with the following error: g:/src/qemu/_git/master/disas.c: In function 'generic_print_address': g:/src/qemu/_git/master/disas.c:65:5: warning: 'I' flag used with '%x' gnu_printf format g:/src/qemu/_git/master/disas.c:65:5: warning: format '%I64x' expects type 'unsigned int', but argument 3 has type 'bfd_vma' make[1]: *** No rule to make target `../libhw32/virtio.o', needed by `qemu.exe'. Stop. make: *** [subdir-i386-softmmu] Error 2 Hi Mateusz, Good to hear from you again. Hi Mark, Hehe, nice to see you here. The world is small and the virtual world too :-) On a separate note, as a Windows user have you tried using the mingw-w64 compiler (http://mingw-w64.sourceforge.net/) to build qemu instead? No, I haven't tried. Actually, the need to build QEMU made me using MinGW for the very first time. I thought the mingw-w64 is still experimental or not production ready. While the name suggests only a 64-bit compiler, the basic installation consists of both 32 and 64 bit compilers, plus the team there are currently very active and in my experience a lot more responsive when it comes to fixing any problems that may arise. You mean mingw-w64 team, right? I think the problem I reported here is not really MinGW related, but to QEMU build configuration. Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org Member of ACCU, http://accu.org
Re: [Qemu-devel] Re: KVM call agenda for Jan 11
On 01/11/2011 04:43 PM, Anthony Liguori wrote: - invalidate all buffers for that block device on machine A after migration. * with NFS, just close + reopen the file (and pray that nobody else has it also opened) * with block devices: use BLKFLBLK ioctl, and pray that nobody else is using the device, that device is not a ramdisk, and some more things. To add injury to insult, you need to be root to be able to issue that ioctl (technically have CAP_SYS_ADMIN). Why isn't fsync() enough for a block device? fsync() is fine on the outgoing side, but not on the incoming side. (the imcoming side might have valid buffers if it was the outgoing side on the previous migration, for example, or because of automatic probing) -- error compiling committee.c: too many arguments to function
Re: [Qemu-devel] paravirtual mouse/tablet
On 01/13/2011 05:52 PM, Anthony Liguori wrote: /* host-guest, sent before any other events */ typedef struct qemu_pvtablet_init { uint32_t res_x; /* x axis resolution */ uint32_t res_y; /* y axis resolution */ uint32_t features; /* qemu_pvtablet_features */ uint32_t available_buttons; /* bitmask */ } qemu_pvtablet_init; -- error compiling committee.c: too many arguments to function
Re: [Qemu-devel] paravirtual mouse/tablet
On 01/13/2011 12:19 PM, Gerd Hoffmann wrote: Hi, Just throwing a quick writeup into the ring to kickstart the design discussion ;) typedef struct qemu_pvtablet_message { uint32_t size;/* whole message size */ uint32_t type;/* qemu_pvtablet_type */ uint64_t tv_secs; uint64_t tv_usecs; time relative to what base? can we actually provide it? if the tablet is remote, there may not be a synchronized time source. union { qemu_pvtablet_position position; qemu_pvtablet_button button; qemu_pvtablet_display display; } m; } qemu_pvtablet_message; So the message size for a qemu_pvtablet_position would only include the position member? -- error compiling committee.c: too many arguments to function
[Qemu-devel] Re: [fedora-virt] Fedora Virt status
Windows 7 KVM install runs unbelievably fast on SL 6 ( alpha 3) vs F14 with the most recent libvirt stuff : [root@fedora14b ~]# rpm -qa|grep libvirt libvirt-python-0.8.7-1.fc14.x86_64 libvirt-0.8.7-1.fc14.x86_64 libvirt-client-0.8.7-1.fc14.x86_64 Boris. P.S. It happens no matter of pre-install loading Virtio SCSI driver, which is also possible only on SL6 via virtio-win.1.1.16.noarch.rpm. --- On Wed, 1/12/11, Justin M. Forbes jmfor...@linuxtx.org wrote: From: Justin M. Forbes jmfor...@linuxtx.org Subject: [fedora-virt] Fedora Virt status To: v...@lists.fedoraproject.org Cc: qemu-devel@nongnu.org Date: Wednesday, January 12, 2011, 5:12 PM Fedora 14 - We have 79 open bugs, 9 of which have fixes in awaiting updates. - 1 bug has been closed in the last week - Virt-preview has been opened for Fedora 14, more details below Fedora 15 - Upcoming Deadlines: 2011-01-25 Feature Submission Deadline (2 Weeks!) 2011-02-08 Feature Freeze--Planning Development Ends 2011-02-08 Branch Fedora 15 from Rawhide-- Branch Freeze 2011-02-15 Software String Freeze 2011-02-15 Alpha Change Deadline 2011-03-01 Alpha Release 2011-03-15 Software Translation Deadline 2011-03-22 Beta Change Deadline Features 100% Complete 2011-04-05 Beta Release 2011-04-25 Final Change Deadline 2011-04-26 Compose 'Final' RC 2011-05-10 Fedora 15 Final Release - Feature submission deadline is fast approaching, let's get those feature submissions done. == Virt Preview Repository == The virt-preview repository is now active for F14 users wishing to run the latest F15 virt packages on their stable F14 systems. F13 virt-preview users will still get the latest F14 packages. For details on how to run enable virt-preview, please see: https://fedoraproject.org/wiki/Virtualization_Preview_Repository Also note that virt-preview for F14 and later releases will live on the new(ish) repos.fedorapeople.org site. == Bugs of importance: == - 662380 Encrypted disks do not work Using virsh to create the encrypted disk, resulting disk is unusable. - 655280 libvirt does not support vendor/product based USB device passthrough with QEMU - 656943 KVM guest crashes if vmware vga option is used Reports of qemu crashing when a vga option is passed, using debian guests - 589130 USB disk not marked as removable USB Mass storage devices are not marked as removable to a guest. Bug has been filed upstream as well there is some debate as to what is the correct behavior here. ___ virt mailing list v...@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/virt
Re: [Qemu-devel] paravirtual mouse/tablet
On 01/13/2011 10:14 AM, Avi Kivity wrote: On 01/13/2011 05:52 PM, Anthony Liguori wrote: /* host-guest, sent before any other events */ typedef struct qemu_pvtablet_init { uint32_t res_x; /* x axis resolution */ uint32_t res_y; /* y axis resolution */ uint32_t features; /* qemu_pvtablet_features */ uint32_t available_buttons; /* bitmask */ Yes, I had intended to do that but left it out. Should it be a bitmask or just a button count? Buttons really have no standard meaning so usually a button count is sufficient. Regards, Anthony Liguori } qemu_pvtablet_init;
Re: [Qemu-devel] paravirtual mouse/tablet
On 01/13/2011 10:18 AM, Avi Kivity wrote: On 01/13/2011 12:19 PM, Gerd Hoffmann wrote: Hi, Just throwing a quick writeup into the ring to kickstart the design discussion ;) typedef struct qemu_pvtablet_message { uint32_t size;/* whole message size */ uint32_t type;/* qemu_pvtablet_type */ uint64_t tv_secs; uint64_t tv_usecs; time relative to what base? can we actually provide it? if the tablet is remote, there may not be a synchronized time source. I had the same thought, but if it's just treated as time since the init message, the guest is capable of working it out (minus drift). union { qemu_pvtablet_position position; qemu_pvtablet_button button; qemu_pvtablet_display display; } m; } qemu_pvtablet_message; So the message size for a qemu_pvtablet_position would only include the position member? I didn't comment on this because I was treating this as a protocol proposal and not actual code but usually the following is clearer: struct qemu_pvtablet_hdr { uint32_t size; uint32_t type; uint64_t tv_secs; uint64_t tv_usecs; }; struct qemu_pvtablet_position { struct qemu_pvtablet_hdr hdr; uint32_t x; uint32_t y; }; union qemu_pvtablet_message { struct qemu_pvtablet_hdr hdr; struct qemu_pvtablet_position position; ... }; Regards, Anthony Liguori
Re: [Qemu-devel] Re: [Spice-devel] paravirtual mouse/tablet
On 01/13/11 16:55, Anthony Liguori wrote: On 01/13/2011 05:51 AM, Gerd Hoffmann wrote: On 01/13/11 12:01, Stefan Hajnoczi wrote: Can you elaborate how the spice display channel comes into play? On a physical machine you just have input devices with no notion of display. It's up to the windowing system to process input events and handle multihead. Why does a pv tablet tie itself to a display channel? You have two qxl devices, each linked to a spice display channel. The spice client will open one window for each channel. The mouse position is a triple consisting of (x, y, window/channel). Would be slightly cleaner to have multiple devices. Yea, right, that would work too. If we have some way to assign a display to a pvmouse device this works equally well. That maybe implies that we need an offscreen coordinate for the mouse so that you can hide the mouse when it leaves one window. Hmm? I fail to see why multihead is special here. cheers, Gerd
[Qemu-devel] Re: [PATCH 8/8] x86_64 config: fix compile for CONFIG_FDC=n
On 01/13/2011 07:34 AM, David Ahern wrote: +#ifdef CONFIG_FDC /* floppy type */ fd0 = fdctrl_get_drive_type(floppy_controller, 0); @@ -403,6 +408,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, val |= 0x02; /* FPU is there */ val |= 0x04; /* PS/2 mouse installed */ rtc_set_memory(s, REG_EQUIPMENT_BYTE, val); +#endif Isn't it a bit too eager? The equipment byte should still be set, or have you checked with a real machine? Paolo
[Qemu-devel] Re: [PATCH 0/8] misc cleanups for x86_64 disabling config settings
On 01/13/2011 10:57 AM, Isaku Yamahata wrote: How about creating stub functions instead of #ifdefs? I think David's #ifdef's are okay. Ultimately what you'd want is to drive all this from configuration files, and if this were done you wouldn't need stub functions. Paolo
Re: [Qemu-devel] paravirtual mouse/tablet
On 01/13/2011 05:39 PM, Anthony Liguori wrote: On 01/13/2011 10:14 AM, Avi Kivity wrote: On 01/13/2011 05:52 PM, Anthony Liguori wrote: /* host-guest, sent before any other events */ typedef struct qemu_pvtablet_init { uint32_t res_x; /* x axis resolution */ uint32_t res_y; /* y axis resolution */ uint32_t features; /* qemu_pvtablet_features */ uint32_t available_buttons; /* bitmask */ Yes, I had intended to do that but left it out. Should it be a bitmask or just a button count? Buttons really have no standard meaning so usually a button count is sufficient. 3/4 are the mouse wheel, so if you had a mouse with 5 buttons and no wheel those would be buttons 0/1/2/5/6. Paolo
[Qemu-devel] Re: [PATCH 6/8] x86_64 config: fix compile for CONFIG_VGA_ISA=n
On 01/13/2011 07:34 AM, David Ahern wrote: Signed-off-by: David Aherndaah...@cisco.com --- hw/pc.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index e7514fd..11b570f 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1087,8 +1087,10 @@ void pc_vga_init(PCIBus *pci_bus) } else if (std_vga_enabled) { if (pci_bus) { pci_vga_init(pci_bus); +#ifdef CONFIG_VGA_ISA } else { isa_vga_init(); +#endif Should this be an abort for #ifndef CONFIG_VGA_ISA? And maybe the isapc machine should be disabled altogether? Paolo
Re: [Qemu-devel] paravirtual mouse/tablet
On 13.01.2011, at 17:39, Anthony Liguori wrote: On 01/13/2011 10:14 AM, Avi Kivity wrote: On 01/13/2011 05:52 PM, Anthony Liguori wrote: /* host-guest, sent before any other events */ typedef struct qemu_pvtablet_init { uint32_t res_x; /* x axis resolution */ uint32_t res_y; /* y axis resolution */ uint32_t features; /* qemu_pvtablet_features */ uint32_t available_buttons; /* bitmask */ Yes, I had intended to do that but left it out. Should it be a bitmask or just a button count? Buttons really have no standard meaning so usually a button count is sufficient. Some random thoughts: * multitouch capabilities would be good to design in a mouse protocol for 2011, so having say 16 x/y pairs would be better * on mac os at least scrolling is not done by pressing virtual buttons, but by having a separate scroll interface that knows about velocity and such - maybe worth adding that to the protocol from the beginning too. Alex
[Qemu-devel] [PATCH 02/19] Introduce read() to FdMigrationState.
Currently FdMigrationState doesn't support read(), and this patch introduces it to get response from the other side. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- migration-tcp.c | 15 +++ migration.c | 12 migration.h |3 +++ 3 files changed, 30 insertions(+), 0 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index b55f419..96e2411 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -39,6 +39,20 @@ static int socket_write(FdMigrationState *s, const void * buf, size_t size) return send(s-fd, buf, size, 0); } +static int socket_read(FdMigrationState *s, const void * buf, size_t size) +{ +ssize_t len; + +do { +len = recv(s-fd, (void *)buf, size, 0); +} while (len == -1 socket_error() == EINTR); +if (len == -1) { +len = -socket_error(); +} + +return len; +} + static int tcp_close(FdMigrationState *s) { DPRINTF(tcp_close\n); @@ -94,6 +108,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon, s-get_error = socket_errno; s-write = socket_write; +s-read = socket_read; s-close = tcp_close; s-mig_state.cancel = migrate_fd_cancel; s-mig_state.get_status = migrate_fd_get_status; diff --git a/migration.c b/migration.c index e5ba51c..6416ae5 100644 --- a/migration.c +++ b/migration.c @@ -330,6 +330,18 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) return ret; } +int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, int size) +{ +FdMigrationState *s = opaque; +ssize_t ret; +ret = s-read(s, data, size); + +if (ret == -1) +ret = -(s-get_error(s)); + +return ret; +} + void migrate_fd_connect(FdMigrationState *s) { int ret; diff --git a/migration.h b/migration.h index d13ed4f..f033262 100644 --- a/migration.h +++ b/migration.h @@ -47,6 +47,7 @@ struct FdMigrationState int (*get_error)(struct FdMigrationState*); int (*close)(struct FdMigrationState*); int (*write)(struct FdMigrationState*, const void *, size_t); +int (*read)(struct FdMigrationState *, const void *, size_t); void *opaque; }; @@ -115,6 +116,8 @@ void migrate_fd_put_notify(void *opaque); ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size); +int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, int size); + void migrate_fd_connect(FdMigrationState *s); void migrate_fd_put_ready(void *opaque); -- 1.7.1.2
[Qemu-devel] [PATCH 12/19] Insert event_tap_mmio() to cpu_physical_memory_rw() in exec.c.
Record mmio write event to replay it upon failover. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- exec.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/exec.c b/exec.c index 49c28b1..4a171cc 100644 --- a/exec.c +++ b/exec.c @@ -33,6 +33,7 @@ #include osdep.h #include kvm.h #include qemu-timer.h +#include event-tap.h #if defined(CONFIG_USER_ONLY) #include qemu.h #include signal.h @@ -3625,6 +3626,9 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, io_index = (pd IO_MEM_SHIFT) (IO_MEM_NB_ENTRIES - 1); if (p) addr1 = (addr ~TARGET_PAGE_MASK) + p-region_offset; + +event_tap_mmio(addr, buf, len); + /* XXX: could force cpu_single_env to NULL to avoid potential bugs */ if (l = 4 ((addr1 3) == 0)) { -- 1.7.1.2
[Qemu-devel] [PATCH 15/19] savevm: introduce qemu_savevm_trans_{begin, commit}.
Introduce qemu_savevm_state_{begin,commit} to send the memory and device info together, while avoiding cancelling memory state tracking. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- savevm.c | 88 ++ sysemu.h |2 + 2 files changed, 90 insertions(+), 0 deletions(-) diff --git a/savevm.c b/savevm.c index ebb3ef8..9d20c37 100644 --- a/savevm.c +++ b/savevm.c @@ -1722,6 +1722,94 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f) return 0; } +int qemu_savevm_trans_begin(Monitor *mon, QEMUFile *f, int init) +{ +SaveStateEntry *se; +int skipped = 0; + +QTAILQ_FOREACH(se, savevm_handlers, entry) { +int len, stage, ret; + +if (se-save_live_state == NULL) +continue; + +/* Section type */ +qemu_put_byte(f, QEMU_VM_SECTION_START); +qemu_put_be32(f, se-section_id); + +/* ID string */ +len = strlen(se-idstr); +qemu_put_byte(f, len); +qemu_put_buffer(f, (uint8_t *)se-idstr, len); + +qemu_put_be32(f, se-instance_id); +qemu_put_be32(f, se-version_id); + +stage = init ? QEMU_VM_SECTION_START : QEMU_VM_SECTION_PART; +ret = se-save_live_state(mon, f, stage, se-opaque); +if (!ret) { +skipped++; +} +} + +if (qemu_file_has_error(f)) +return -EIO; + +return skipped; +} + +int qemu_savevm_trans_complete(Monitor *mon, QEMUFile *f) +{ +SaveStateEntry *se; + +cpu_synchronize_all_states(); + +QTAILQ_FOREACH(se, savevm_handlers, entry) { +int ret; + +if (se-save_live_state == NULL) +continue; + +/* Section type */ +qemu_put_byte(f, QEMU_VM_SECTION_PART); +qemu_put_be32(f, se-section_id); + +ret = se-save_live_state(mon, f, QEMU_VM_SECTION_PART, se-opaque); +if (!ret) { +/* do not proceed to the next vmstate. */ +return 1; +} +} + +QTAILQ_FOREACH(se, savevm_handlers, entry) { +int len; + +if (se-save_state == NULL se-vmsd == NULL) +continue; + +/* Section type */ +qemu_put_byte(f, QEMU_VM_SECTION_FULL); +qemu_put_be32(f, se-section_id); + +/* ID string */ +len = strlen(se-idstr); +qemu_put_byte(f, len); +qemu_put_buffer(f, (uint8_t *)se-idstr, len); + +qemu_put_be32(f, se-instance_id); +qemu_put_be32(f, se-version_id); + +vmstate_save(f, se); +} + +qemu_put_byte(f, QEMU_VM_EOF); + +if (qemu_file_has_error(f)) +return -EIO; + +return 0; +} + void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f) { SaveStateEntry *se; diff --git a/sysemu.h b/sysemu.h index 81bcf00..9c2c45e 100644 --- a/sysemu.h +++ b/sysemu.h @@ -80,6 +80,8 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable, int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f); int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f); void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f); +int qemu_savevm_trans_begin(Monitor *mon, QEMUFile *f, int init); +int qemu_savevm_trans_complete(Monitor *mon, QEMUFile *f); int qemu_loadvm_state(QEMUFile *f, int skip_header); /* SLIRP */ -- 1.7.1.2
[Qemu-devel] [PATCH 01/19] Make QEMUFile buf expandable, and introduce qemu_realloc_buffer() and qemu_clear_buffer().
Currently buf size is fixed at 32KB. It would be useful if it could be flexible. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- hw/hw.h |2 ++ savevm.c | 20 +++- 2 files changed, 21 insertions(+), 1 deletions(-) diff --git a/hw/hw.h b/hw/hw.h index 163a683..a506688 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -58,6 +58,8 @@ void qemu_fflush(QEMUFile *f); int qemu_fclose(QEMUFile *f); void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); void qemu_put_byte(QEMUFile *f, int v); +void *qemu_realloc_buffer(QEMUFile *f, int size); +void qemu_clear_buffer(QEMUFile *f); static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v) { diff --git a/savevm.c b/savevm.c index 90aa237..8c64c63 100644 --- a/savevm.c +++ b/savevm.c @@ -172,7 +172,8 @@ struct QEMUFile { when reading */ int buf_index; int buf_size; /* 0 when writing */ -uint8_t buf[IO_BUF_SIZE]; +int buf_max_size; +uint8_t *buf; int has_error; }; @@ -423,6 +424,9 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, f-get_rate_limit = get_rate_limit; f-is_write = 0; +f-buf_max_size = IO_BUF_SIZE; +f-buf = qemu_malloc(sizeof(uint8_t) * f-buf_max_size); + return f; } @@ -453,6 +457,19 @@ void qemu_fflush(QEMUFile *f) } } +void *qemu_realloc_buffer(QEMUFile *f, int size) +{ +f-buf_max_size = size; +f-buf = qemu_realloc(f-buf, f-buf_max_size); + +return f-buf; +} + +void qemu_clear_buffer(QEMUFile *f) +{ +f-buf_size = f-buf_index = f-buf_offset = 0; +} + static void qemu_fill_buffer(QEMUFile *f) { int len; @@ -478,6 +495,7 @@ int qemu_fclose(QEMUFile *f) qemu_fflush(f); if (f-close) ret = f-close(f-opaque); +qemu_free(f-buf); qemu_free(f); return ret; } -- 1.7.1.2
Re: [Qemu-devel] paravirtual mouse/tablet
On 01/13/11 17:18, Avi Kivity wrote: On 01/13/2011 12:19 PM, Gerd Hoffmann wrote: Hi, Just throwing a quick writeup into the ring to kickstart the design discussion ;) typedef struct qemu_pvtablet_message { uint32_t size; /* whole message size */ uint32_t type; /* qemu_pvtablet_type */ uint64_t tv_secs; uint64_t tv_usecs; time relative to what base? Guess that needs to be refined ;) Just something relative (if available) should good enougth. The intended purpose is being able to figure how much time passed between two events, so one can figure whenever two mouse clicks should be considered a double-click or not. Ideally the timestamps from the original mouse event in the vnc/spice client would be passed all the way through to the guest. Didn't check the protocols whenever they actually support that, but I think we should have this in the protocol even if they don't ... cheers, Gerd
[Qemu-devel] [PATCH 16/19] migration: introduce migrate_ft_trans_{put, get}_ready(), and modify migrate_fd_put_ready() when ft_mode is on.
Introduce migrate_ft_trans_put_ready() which kicks the FT transaction cycle. When ft_mode is on, migrate_fd_put_ready() would open ft_trans_file and turn on event_tap. To end or cancel FT transaction, ft_mode and event_tap is turned off. migrate_ft_trans_get_ready() is called to receive ack from the receiver. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- migration.c | 266 +- migration.h |2 +- 2 files changed, 262 insertions(+), 6 deletions(-) diff --git a/migration.c b/migration.c index 01b723d..557349b 100644 --- a/migration.c +++ b/migration.c @@ -21,6 +21,7 @@ #include qemu_socket.h #include block-migration.h #include qemu-objects.h +#include event-tap.h //#define DEBUG_MIGRATION @@ -274,6 +275,14 @@ void migrate_fd_error(FdMigrationState *s) migrate_fd_cleanup(s); } +static void migrate_ft_trans_error(FdMigrationState *s) +{ +ft_mode = FT_ERROR; +qemu_savevm_state_cancel(s-mon, s-file); +migrate_fd_error(s); +event_tap_unregister(); +} + int migrate_fd_cleanup(FdMigrationState *s) { int ret = 0; @@ -309,6 +318,17 @@ void migrate_fd_put_notify(void *opaque) qemu_file_put_notify(s-file); } +static void migrate_fd_get_notify(void *opaque) +{ +FdMigrationState *s = opaque; + +qemu_set_fd_handler2(s-fd, NULL, NULL, NULL, NULL); +qemu_file_get_notify(s-file); +if (qemu_file_has_error(s-file)) { +migrate_ft_trans_error(s); +} +} + ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) { FdMigrationState *s = opaque; @@ -333,15 +353,20 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) return ret; } -int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, int size) +int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, size_t size) { FdMigrationState *s = opaque; -ssize_t ret; +int ret; ret = s-read(s, data, size); -if (ret == -1) +if (ret == -1) { ret = -(s-get_error(s)); - +} + +if (ret == -EAGAIN) { +qemu_set_fd_handler2(s-fd, NULL, migrate_fd_get_notify, NULL, s); +} + return ret; } @@ -368,6 +393,226 @@ void migrate_fd_connect(FdMigrationState *s) migrate_fd_put_ready(s); } +static int migrate_ft_trans_commit(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_COMMIT ft_mode != FT_TRANSACTION_ATOMIC) { +fprintf(stderr, +migrate_ft_trans_commit: invalid ft_mode %d\n, ft_mode); +goto out; +} + +do { +if (ft_mode == FT_TRANSACTION_ATOMIC) { +if (qemu_ft_trans_begin(s-file) 0) { +fprintf(stderr, qemu_ft_trans_begin failed\n); +goto out; +} + +if ((ret = qemu_savevm_trans_begin(s-mon, s-file, 0)) 0) { +fprintf(stderr, qemu_savevm_trans_begin failed\n); +goto out; +} + +ft_mode = FT_TRANSACTION_COMMIT; +if (ret) { +/* don't proceed until if fd isn't ready */ +goto out; +} +} + +/* make the VM state consistent by flushing outstanding events */ +vm_stop(0); + +/* send at full speed */ +qemu_file_set_rate_limit(s-file, 0); + +if ((ret = qemu_savevm_trans_complete(s-mon, s-file)) 0) { +fprintf(stderr, qemu_savevm_trans_complete failed\n); +goto out; +} + +if (ret) { +/* don't proceed until if fd isn't ready */ +ret = 1; +goto out; +} + +if ((ret = qemu_ft_trans_commit(s-file)) 0) { +fprintf(stderr, qemu_ft_trans_commit failed\n); +goto out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_RECV; +ret = 1; +goto out; +} + +/* flush and check if events are remaining */ +vm_start(); +if ((ret = event_tap_flush_one()) 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto out; +} + +ft_mode = ret ? FT_TRANSACTION_BEGIN : FT_TRANSACTION_ATOMIC; +} while (ft_mode != FT_TRANSACTION_BEGIN); + +vm_start(); +ret = 0; + +out: +return ret; +} + +static int migrate_ft_trans_get_ready(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_RECV) { +fprintf(stderr, +migrate_ft_trans_get_ready: invalid ft_mode %d\n, ft_mode); +goto error_out; +} + +/* flush and check if events are remaining */ +vm_start(); +if ((ret = event_tap_flush_one()) 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto error_out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_BEGIN; +} else { +
[Qemu-devel] [PATCH 09/19] Introduce event-tap.
event-tap controls when to start FT transaction, and provides proxy functions to called from net/block devices. While FT transaction, it queues up net/block requests, and flush them when the transaction gets completed. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp Signed-off-by: OHMURA Kei ohmura@lab.ntt.co.jp --- Makefile.target |1 + event-tap.c | 836 +++ event-tap.h | 42 +++ qemu-tool.c | 24 ++ trace-events|9 + 5 files changed, 912 insertions(+), 0 deletions(-) create mode 100644 event-tap.c create mode 100644 event-tap.h diff --git a/Makefile.target b/Makefile.target index e15b1c4..f36cd75 100644 --- a/Makefile.target +++ b/Makefile.target @@ -199,6 +199,7 @@ obj-y += rwhandler.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o obj-$(CONFIG_NO_KVM) += kvm-stub.o LIBS+=-lz +obj-y += event-tap.o QEMU_CFLAGS += $(VNC_TLS_CFLAGS) QEMU_CFLAGS += $(VNC_SASL_CFLAGS) diff --git a/event-tap.c b/event-tap.c new file mode 100644 index 000..1010b9e --- /dev/null +++ b/event-tap.c @@ -0,0 +1,836 @@ +/* + * Event Tap functions for QEMU + * + * Copyright (c) 2010 Nippon Telegraph and Telephone Corporation. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include qemu-common.h +#include qemu-error.h +#include block.h +#include block_int.h +#include ioport.h +#include osdep.h +#include sysemu.h +#include hw/hw.h +#include net.h +#include event-tap.h +#include trace.h + +enum EVENT_TAP_STATE { +EVENT_TAP_OFF, +EVENT_TAP_ON, +EVENT_TAP_FLUSH, +EVENT_TAP_LOAD, +EVENT_TAP_REPLAY, +}; + +static enum EVENT_TAP_STATE event_tap_state = EVENT_TAP_OFF; +static BlockDriverAIOCB dummy_acb; /* we may need a pool for dummies */ + +typedef struct EventTapIOport { +uint32_t address; +uint32_t data; +int index; +} EventTapIOport; + +#define MMIO_BUF_SIZE 8 + +typedef struct EventTapMMIO { +uint64_t address; +uint8_t buf[MMIO_BUF_SIZE]; +int len; +} EventTapMMIO; + +typedef struct EventTapNetReq { +char *device_name; +int iovcnt; +struct iovec *iov; +int vlan_id; +bool vlan_needed; +bool async; +NetPacketSent *sent_cb; +} EventTapNetReq; + +#define MAX_BLOCK_REQUEST 32 + +typedef struct EventTapBlkReq { +char *device_name; +int num_reqs; +int num_cbs; +bool is_flush; +BlockRequest reqs[MAX_BLOCK_REQUEST]; +BlockDriverCompletionFunc *cb[MAX_BLOCK_REQUEST]; +void *opaque[MAX_BLOCK_REQUEST]; +} EventTapBlkReq; + +#define EVENT_TAP_IOPORT (1 0) +#define EVENT_TAP_MMIO (1 1) +#define EVENT_TAP_NET(1 2) +#define EVENT_TAP_BLK(1 3) + +#define EVENT_TAP_TYPE_MASK (EVENT_TAP_NET - 1) + +typedef struct EventTapLog { +int mode; +union { +EventTapIOport ioport ; +EventTapMMIO mmio; +}; +union { +EventTapNetReq net_req; +EventTapBlkReq blk_req; +}; +QTAILQ_ENTRY(EventTapLog) node; +} EventTapLog; + +static EventTapLog *last_event_tap; + +static QTAILQ_HEAD(, EventTapLog) event_list; +static QTAILQ_HEAD(, EventTapLog) event_pool; + +static int (*event_tap_cb)(void); +static QEMUBH *event_tap_bh; +static VMChangeStateEntry *vmstate; + +static void event_tap_bh_cb(void *p) +{ +if (event_tap_cb) { +event_tap_cb(); +} + +qemu_bh_delete(event_tap_bh); +event_tap_bh = NULL; +} + +static void event_tap_schedule_bh(void) +{ +trace_event_tap_ignore_bh(!!event_tap_bh); + +/* if bh is already set, we ignore it for now */ +if (event_tap_bh) { +return; +} + +event_tap_bh = qemu_bh_new(event_tap_bh_cb, NULL); +qemu_bh_schedule(event_tap_bh); + +return ; +} + +static void event_tap_alloc_net_req(EventTapNetReq *net_req, + VLANClientState *vc, + const struct iovec *iov, int iovcnt, + NetPacketSent *sent_cb, bool async) +{ +int i; + +net_req-iovcnt = iovcnt; +net_req-async = async; +net_req-device_name = qemu_strdup(vc-name); +net_req-sent_cb = sent_cb; + +if (vc-vlan) { +net_req-vlan_needed = 1; +net_req-vlan_id = vc-vlan-id; +} else { +net_req-vlan_needed = 0; +} + +if (async) { +net_req-iov = (struct iovec *)iov; +} else { +net_req-iov = qemu_malloc(sizeof(struct iovec) * iovcnt); +for (i = 0; i iovcnt; i++) { +net_req-iov[i].iov_base = qemu_malloc(iov[i].iov_len); +memcpy(net_req-iov[i].iov_base, iov[i].iov_base, iov[i].iov_len); +net_req-iov[i].iov_len = iov[i].iov_len; +} +} +} + +static void event_tap_alloc_blk_req(EventTapBlkReq *blk_req, +BlockDriverState *bs, BlockRequest *reqs, +int num_reqs,
[Qemu-devel] [PATCH 04/19] qemu-char: export socket_set_nodelay().
Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- qemu-char.c |2 +- qemu_socket.h |1 + 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index edc9ad6..737d347 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2116,7 +2116,7 @@ static void tcp_chr_telnet_init(int fd) send(fd, (char *)buf, 3, 0); } -static void socket_set_nodelay(int fd) +void socket_set_nodelay(int fd) { int val = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)val, sizeof(val)); diff --git a/qemu_socket.h b/qemu_socket.h index 897a8ae..b7f8465 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -36,6 +36,7 @@ int inet_aton(const char *cp, struct in_addr *ia); int qemu_socket(int domain, int type, int protocol); int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); void socket_set_nonblock(int fd); +void socket_set_nodelay(int fd); int send_all(int fd, const void *buf, int len1); /* New, ipv6-ready socket helper functions, see qemu-sockets.c */ -- 1.7.1.2
[Qemu-devel] [PATCH 14/19] block: insert event-tap to bdrv_aio_writev() and bdrv_aio_flush().
event-tap function is called only when it is on, and requests sent from device emulators. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- block.c | 11 +++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/block.c b/block.c index ff2795b..85bd8b8 100644 --- a/block.c +++ b/block.c @@ -28,6 +28,7 @@ #include block_int.h #include module.h #include qemu-objects.h +#include event-tap.h #ifdef CONFIG_BSD #include sys/types.h @@ -2111,6 +2112,11 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, if (bdrv_check_request(bs, sector_num, nb_sectors)) return NULL; +if (bs-device_name event_tap_is_on()) { +return event_tap_bdrv_aio_writev(bs, sector_num, qiov, nb_sectors, + cb, opaque); +} + if (bs-dirty_bitmap) { blk_cb_data = blk_dirty_cb_alloc(bs, sector_num, nb_sectors, cb, opaque); @@ -2374,6 +2380,11 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, if (!drv) return NULL; + +if (bs-device_name event_tap_is_on()) { +return event_tap_bdrv_aio_flush(bs, cb, opaque); +} + return drv-bdrv_aio_flush(bs, cb, opaque); } -- 1.7.1.2
[Qemu-devel] [PATCH 08/19] savevm: introduce util functions to control ft_trans_file from savevm layer.
To utilize ft_trans_file function, savevm needs interfaces to be exported. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- hw/hw.h |5 ++ savevm.c | 148 ++ 2 files changed, 153 insertions(+), 0 deletions(-) diff --git a/hw/hw.h b/hw/hw.h index a506688..ace1744 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -51,6 +51,7 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, QEMUFile *qemu_fopen(const char *filename, const char *mode); QEMUFile *qemu_fdopen(int fd, const char *mode); QEMUFile *qemu_fopen_socket(int fd); +QEMUFile *qemu_fopen_ft_trans(int s_fd, int c_fd); QEMUFile *qemu_popen(FILE *popen_file, const char *mode); QEMUFile *qemu_popen_cmd(const char *command, const char *mode); int qemu_stdio_fd(QEMUFile *f); @@ -60,6 +61,9 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); void qemu_put_byte(QEMUFile *f, int v); void *qemu_realloc_buffer(QEMUFile *f, int size); void qemu_clear_buffer(QEMUFile *f); +int qemu_ft_trans_begin(QEMUFile *f); +int qemu_ft_trans_commit(QEMUFile *f); +int qemu_ft_trans_cancel(QEMUFile *f); static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v) { @@ -94,6 +98,7 @@ void qemu_file_set_error(QEMUFile *f); * halted due to rate limiting or EAGAIN errors occur as it can be used to * resume output. */ void qemu_file_put_notify(QEMUFile *f); +void qemu_file_get_notify(void *opaque); static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) { diff --git a/savevm.c b/savevm.c index 7bc3699..ebb3ef8 100644 --- a/savevm.c +++ b/savevm.c @@ -83,6 +83,7 @@ #include migration.h #include qemu_socket.h #include qemu-queue.h +#include ft_trans_file.h #define SELF_ANNOUNCE_ROUNDS 5 @@ -190,6 +191,13 @@ typedef struct QEMUFileSocket QEMUFile *file; } QEMUFileSocket; +typedef struct QEMUFileSocketTrans +{ +int fd; +QEMUFileSocket *s; +VMChangeStateEntry *e; +} QEMUFileSocketTrans; + static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) { QEMUFileSocket *s = opaque; @@ -205,6 +213,21 @@ static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) return len; } +static ssize_t socket_put_buffer(void *opaque, const void *buf, size_t size) +{ +QEMUFileSocket *s = opaque; +ssize_t len; + +do { +len = send(s-fd, (void *)buf, size, 0); +} while (len == -1 socket_error() == EINTR); + +if (len == -1) +len = -socket_error(); + +return len; +} + static int socket_close(void *opaque) { QEMUFileSocket *s = opaque; @@ -212,6 +235,70 @@ static int socket_close(void *opaque) return 0; } +static int socket_trans_get_buffer(void *opaque, uint8_t *buf, int64_t pos, size_t size) +{ +QEMUFileSocketTrans *t = opaque; +QEMUFileSocket *s = t-s; +ssize_t len; + +len = socket_get_buffer(s, buf, pos, size); + +return len; +} + +static ssize_t socket_trans_put_buffer(void *opaque, const void *buf, size_t size) +{ +QEMUFileSocketTrans *t = opaque; + +return socket_put_buffer(t-s, buf, size); +} + + +static int socket_trans_get_ready(void *opaque) +{ +QEMUFileSocketTrans *t = opaque; +QEMUFileSocket *s = t-s; +QEMUFile *f = s-file; +int ret = 0; + +ret = qemu_loadvm_state(f, 1); +if (ret 0) { +fprintf(stderr, +socket_trans_get_ready: error while loading vmstate\n); +} + +return ret; +} + +static int socket_trans_close(void *opaque) +{ +QEMUFileSocketTrans *t = opaque; +QEMUFileSocket *s = t-s; + +qemu_set_fd_handler2(s-fd, NULL, NULL, NULL, NULL); +qemu_set_fd_handler2(t-fd, NULL, NULL, NULL, NULL); +qemu_del_vm_change_state_handler(t-e); +close(s-fd); +close(t-fd); +qemu_free(s); +qemu_free(t); + +return 0; +} + +static void socket_trans_resume(void *opaque, int running, int reason) +{ +QEMUFileSocketTrans *t = opaque; +QEMUFileSocket *s = t-s; + +if (!running) { +return; +} + +qemu_announce_self(); +qemu_fclose(s-file); +} + static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) { QEMUFileStdio *s = opaque; @@ -334,6 +421,26 @@ QEMUFile *qemu_fopen_socket(int fd) return s-file; } +QEMUFile *qemu_fopen_ft_trans(int s_fd, int c_fd) +{ +QEMUFileSocketTrans *t = qemu_mallocz(sizeof(QEMUFileSocketTrans)); +QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket)); + +t-s = s; +t-fd = s_fd; +t-e = qemu_add_vm_change_state_handler(socket_trans_resume, t); + +s-fd = c_fd; +s-file = qemu_fopen_ops_ft_trans(t, socket_trans_put_buffer, + socket_trans_get_buffer, NULL, + socket_trans_get_ready, + migrate_fd_wait_for_unfreeze, + socket_trans_close, 0); +
[Qemu-devel] Re: [PATCH 6/8] x86_64 config: fix compile for CONFIG_VGA_ISA=n
On 01/13/11 10:02, Paolo Bonzini wrote: On 01/13/2011 07:34 AM, David Ahern wrote: Signed-off-by: David Aherndaah...@cisco.com --- hw/pc.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index e7514fd..11b570f 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1087,8 +1087,10 @@ void pc_vga_init(PCIBus *pci_bus) } else if (std_vga_enabled) { if (pci_bus) { pci_vga_init(pci_bus); +#ifdef CONFIG_VGA_ISA } else { isa_vga_init(); +#endif Should this be an abort for #ifndef CONFIG_VGA_ISA? And maybe the isapc machine should be disabled altogether? Paolo If that's desired I can change that to: #ifdef CONFIG_VGA_ISA } else { isa_vga_init(); #else abort(); #endif David