[Qemu-devel] [Bug 1652011] Re: VM shuts down due to error in qemu block.c
Please do not report distribution specific bugs (since you're using qemu-kvm 2.0.0+dfsg-2ubuntu1.27) against the QEMU project bugtracker - use the distribution's bugtracker instead. ** Project changed: qemu => qemu (Ubuntu) -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1652011 Title: VM shuts down due to error in qemu block.c Status in qemu package in Ubuntu: New Bug description: On a Trusty KVM host one of the guest VMs shut down without any user interaction. The system is running: $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=14.04 DISTRIB_CODENAME=trusty DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS" $ dpkg -l libvirt0 qemu-kvm qemu-system-common qemu-system-x86 Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) ||/ Name Version ArchitectureDescription +++--===-===-== ii libvirt0 1.2.2-0ubuntu13.1.17amd64 library for interfacing with different virtualization systems ii qemu-kvm 2.0.0+dfsg-2ubuntu1.27 amd64 QEMU Full virtualization ii qemu-system-common 2.0.0+dfsg-2ubuntu1.27 amd64 QEMU full system emulation binaries (common files) ii qemu-system-x86 2.0.0+dfsg-2ubuntu1.27 amd64 QEMU full system emulation binaries (x86) In the VMs log in /var/lib/libvirt/qemu/hostname we see: 2016-11-17 09:18:42.603+: starting up LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin QEMU_AUDIO_DRV=none /usr/bin/kvm -name hostname,process=qemu:hostname -S -machine pc-i440fx-trusty,accel=kvm,usb=off -m 12697 -realtime mlock=off -smp 4,sockets=4,cores=1,threads=1 -uuid 51766564-ed8e-41aa-91b5-574220af4ac3 -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/hostname.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -boot strict=on -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/dev/disk1/hostname,if=none,id=drive-virtio-disk0,format=raw -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -drive file=/dev/disk2/hostname_mnt_data,if=none,id=drive-virtio-disk1,format=raw -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk1,id=virtio-disk1 -drive file=/dev/disk1/hostname_tmp,if=none,id=drive-virtio-disk2,format=raw -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x8,drive=drive-virtio-disk2,id=virtio-disk2 -netdev tap,fd=24,id=hostnet0,vhost=on,vhostfd=30 -device virtio-net-pci,tx=bh,netdev=hostnet0,id=net0,mac=52:54:00:45:e7:d9,bus=pci.0,addr=0x6 -netdev tap,fd=31,id=hostnet1,vhost=on,vhostfd=32 -device virtio-net-pci,tx=bh,netdev=hostnet1,id=net1,mac=52:54:00:f6:6c:77,bus=pci.0,addr=0x7 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -device usb-tablet,id=input0 -vnc 0.0.0.0:5 -device VGA,id=video0,bus=pci.0,addr=0x2 -device AC97,id=sound0,bus=pci.0,addr=0x3 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x9 char device redirected to /dev/pts/6 (label charserial0) qemu-system-x86_64: /build/qemu-PVxDqC/qemu-2.0.0+dfsg/block.c:3491: bdrv_error_action: Assertion `error >= 0' failed. 2016-12-22 09:49:49.392+: shutting down In /var/lib/libvirt/libvirtd.log we see: 2016-12-22 09:49:49.298+: 6946: error : qemuMonitorIO:656 : internal error: End of file from monitor We investigated to see if this is a known issue and came across a bug report for Fedora (https://bugzilla.redhat.com/show_bug.cgi?id=1147398), but nothing references changes upstream that fix this. The guest OS is Ubuntu Precise (12.04.5) running kernel linux- image-3.2.0-101-virtual 3.2.0-101.141. There wasn't any significant load (CPU or IO) on the guest at the time that it shut down and there wasn't any appreciable disk IO on the KVM host either. The disks for the guest are on the KVM host box. To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1652011/+subscriptions
Re: [Qemu-devel] virus in colibriOS QEMU iso?
On 22.12.2016 18:37, vilca...@gmail.com wrote: > Hi, just letting you know that Avira found some crypto-locker virus in > ColibriOS iso that you featured in QEMU Advent Calendar 2016. Maybe you > should look into that. I am not sure if it’s a false positive or not.. You > can check the attachment for a screenshot of the result. That sounds ugly ... I think we just packaged the .iso from the official KolibriOS website here (Kashyap, can you confirm?), so if this is not just a false positive, the problem very likely comes from there. If you've got some spare minutes, could you maybe check the download from http://kolibrios.org/en/download , too? As far as I can see, there should not be any real danger here unless you put the .iso file onto a real CD-ROM or USB stick and start the .exe files in there (which is of course not necessary for starting a VM with the .iso file). But anyway, this needs some closer investigation, to see whether it's a false positive or not, so I've disabled that download for now. We'll let you know when we know more ... Thanks for reporting the issue! Thomas
Re: [Qemu-devel] [RFC PATCH 00/11] Stubs cleanup
Paolo Bonzini writes: > On 22/12/2016 18:42, Eduardo Habkost wrote: >> On Thu, Dec 22, 2016 at 06:32:24PM +0100, Paolo Bonzini wrote: >>> >>> >>> On 22/12/2016 18:30, Peter Maydell wrote: On 22 December 2016 at 15:59, Paolo Bonzini wrote: > This moves out of libqemustub.a those functions which can be handled > simply by $(call lnot), like we already do for pci-stub.c or kvm-stub.c. > libqemustub.a keep the more complex cases where a small part of the > executables we build needs an implementation of a small subset of an API. So why is doing it this way round better? (I don't have a strong opinion here, but you don't really give a rationale for this change.) >>> >>> I don't really have a strong opinion here either, hence the RFC. >>> However, one advantage is that it keeps things visible to the right >>> maintainer. >> >> Can't we just move the files to subdirectories where they are >> visible to the maintainers, but keep using stub-obj-y/libqemustub >> to build/link them? >> >> I find libqemustub/stub-obj-y much easier to use than manually >> setting obj-$(call lnot ...). > > Yes, that would work too. It's a pity that we cannot just use weak > symbols, as that would work fine with obj-y. Can you explain again why we can't use weak symbols? [...]
Re: [Qemu-devel] [RFC PATCH 00/11] Stubs cleanup
- Original Message - > From: "Markus Armbruster" > To: "Paolo Bonzini" > Cc: "Eduardo Habkost" , "Peter Maydell" > , "Fam Zheng" > , "QEMU Developers" > Sent: Friday, December 23, 2016 10:02:33 AM > Subject: Re: [Qemu-devel] [RFC PATCH 00/11] Stubs cleanup > > Paolo Bonzini writes: > > > On 22/12/2016 18:42, Eduardo Habkost wrote: > >> On Thu, Dec 22, 2016 at 06:32:24PM +0100, Paolo Bonzini wrote: > >>> > >>> > >>> On 22/12/2016 18:30, Peter Maydell wrote: > On 22 December 2016 at 15:59, Paolo Bonzini wrote: > > This moves out of libqemustub.a those functions which can be handled > > simply by $(call lnot), like we already do for pci-stub.c or > > kvm-stub.c. > > libqemustub.a keep the more complex cases where a small part of the > > executables we build needs an implementation of a small subset of an > > API. > > So why is doing it this way round better? (I don't have a strong > opinion here, but you don't really give a rationale for this change.) > >>> > >>> I don't really have a strong opinion here either, hence the RFC. > >>> However, one advantage is that it keeps things visible to the right > >>> maintainer. > >> > >> Can't we just move the files to subdirectories where they are > >> visible to the maintainers, but keep using stub-obj-y/libqemustub > >> to build/link them? > >> > >> I find libqemustub/stub-obj-y much easier to use than manually > >> setting obj-$(call lnot ...). > > > > Yes, that would work too. It's a pity that we cannot just use weak > > symbols, as that would work fine with obj-y. > > Can you explain again why we can't use weak symbols? Because Windows and OS X don't have full support for weak symbols. At least as I understand it, OS X only supports "weak import" of a symbol from a library, where if a symbol is missing _in the library_ it resolves to NULL in the program. It doesn't support replacing a weak definition of a function with a strong definition of the same, and that's why we use a static library. Paolo
Re: [Qemu-devel] virus in colibriOS QEMU iso?
[...] > On 22.12.2016 18:37, vilca...@gmail.com wrote: > > Hi, just letting you know that Avira found some crypto-locker virus in > > ColibriOS iso that you featured in QEMU Advent Calendar 2016. Maybe you > > should look into that. I am not sure if it’s a false positive or not.. You > > can check the attachment for a screenshot of the result. > > That sounds ugly ... That sounds super ugly indeed :-( > I think we just packaged the .iso from the official > KolibriOS website here (Kashyap, can you confirm?), Yes, I can confirm that I have downloaded the ISO from the official website -- it's a nightly build of their SVN revision 6766. These are local notes on preparing sources from the day I made the image (where the SVN revision was at 6766): $ svn checkout svn://kolibrios.org -r 6766 $ svn log | head -5 r6766 | IgorA | 2016-11-26 23:57:24 +0100 (Sat, 26 Nov 2016) | 1 line fix bugs $ du -sh ../sources-kolibrios/ 1.4G../sources-kolibrios/ $ du -sh .svn/ 662M.svn/ $ rm -rf .svn $ du -sh ../sources-kolibrios-rev-6766/ 691M../sources-kolibrios-rev-6766/ $ tar -cJf sources-kolibrios-rev-6766.tar.xz sources-kolibrios-rev-6766/ $ du -sh sources-kolibrios-rev-6766.tar.xz 93M sources-kolibrios-rev-6766.tar.xz > so if this is not > just a false positive, the problem very likely comes from there. Indeed. > If you've got some spare minutes, could you maybe check the download > from http://kolibrios.org/en/download , too? > > As far as I can see, there should not be any real danger here unless you > put the .iso file onto a real CD-ROM or USB stick and start the .exe > files in there (which is of course not necessary for starting a VM with > the .iso file). Yes, exactly, but still this incident is not nice to hear. > But anyway, this needs some closer investigation, to see > whether it's a false positive or not, so I've disabled that download for > now. We'll let you know when we know more ... Thanks for reporting the > issue! Yes, thanks for bringing it up. I'm afraid, I'm a little short on time, but will try to investigate later today. Regards, Kashyap
Re: [Qemu-devel] [PATCH v6 00/17] qapi doc generation (whole version, squashed)
Marc-André Lureau writes: > Add a qapi2texi script to generate the documentation from the qapi > schemas. > > The SQUASHED patch in this series is a squashed version of the > documentation move from qmp-commands.txt to the schemas. The whole > version (not sent on the ML to avoid spamming) is in the following git > branch: https://github.com/elmarco/qemu/commits/qapi-doc > > PDF preview: > https://fedorapeople.org/~elmarco/qemu-qmp-ref.pdf > > v6: > - rebased on top of armbru/qapi-next branch > - add a few patches to improve Exception subclasses and usage in > qapi.py as suggested during review > - parser and generator fixes and improvements after v5 review: > - various union improvements, hopefully with a better syntax > - improve error messages > - improve docs/qapi-code-gen.txt documentation section > - do not allow interleaved body documentation between sections > - more tests for new cases > - make expression documentation mandatory, fix the tests > - replace bad usage of @var{} with @t{} in texi, fix texi2pod to > handle it > - renaming, reordering etc.. > - add docs/qapi-syntax.texi to describe the API syntax used in the > texi documentation > - fix interleaved body and section documentation > - improve documentation sections name > - many build-sys improvements after review > - fix and improve commit messages, update R-b tags There's quite some new material in v6. How can we converge on something mergable quickly? Let me review my review. PATCH 01-04,06,12-16 are ready with minor tweaks here and there. PATCH 17 "build-sys: add qapi doc generation targets" is almost ready: one a simple question left. PATCH 07 should be dropped. The idea it implements is mine, but it's a bad one %-) PATCH 09 "texi2pod: learn quotation, deftp and deftypefn" still needs review, but is probably just fine, so let's not worry about it. PATCH 10 "json: reorder documentation body" looks problematic. Can we postpone it? PATCH 11 "(SQUASHED) move doc to schema" could use double-checking, but only when we're ready to commit it. Let's not worry about it. PATCH 05 "docs: add master qapi texi files" has major documentation improvements since v5, which are not ready. Besides issues with the documentation, there are issues with what's being documented. To converge on this one, we also need to converge on PATCH 08. PATCH 08 "qapi: add qapi2texi script" is the core of the matter. I proposed a bunch of FIXME comments, minor tweaks and fixes. A few more issues are still open, but we should be able to address them with only minor churn. There's one feature that I feel takes us in the wrong direction: the invention of a formal language to describe QAPI definitions from the user's point of view. I doubt this language is necessary. Both the language and its documentation in PATCH 05 have numerous issues, and this is a major reason for PATCH 05 not being ready. I'm proposing to rip out this part for now, along with all of the new documentation (revert to PATCH 05 v5). Not ideal, because the series then regresses QMP documentation (JSON type information lost), and leaves the new, doc comment requirements and features undocumented. So add suitable FIXMEs, and make updating the documentation a priority. Once that's done, we can discuss how to add back type information, and what to do about the proposed formal language. Does this sound like a sensible plan?
Re: [Qemu-devel] virus in colibriOS QEMU iso?
On 23.12.2016 10:20, Kashyap Chamarthy wrote: > [...] > >> On 22.12.2016 18:37, vilca...@gmail.com wrote: >>> Hi, just letting you know that Avira found some crypto-locker virus in >>> ColibriOS iso that you featured in QEMU Advent Calendar 2016. Maybe you >>> should look into that. I am not sure if it’s a false positive or not.. You >>> can check the attachment for a screenshot of the result. >> >> That sounds ugly ... > > That sounds super ugly indeed :-( > >> I think we just packaged the .iso from the official >> KolibriOS website here (Kashyap, can you confirm?), > > Yes, I can confirm that I have downloaded the ISO from the > official website -- it's a nightly build of their > SVN revision 6766. OK, as far as I can see, the issue comes from the setmbr.exe that is contained in the iso for writing the KolibriOS to an USB stick. According to http://board.kolibrios.org/viewtopic.php?t=2295 the report from Avira is a false positive (likely caused because the program tries to write to the MBR - which is also what some viruses / trojans are doing). Anyway, since these Windows tools are not required for running KolibriOS in a VM, I've now removed them from the iso image and uploaded a new version to avoid future confusion: http://www.qemu-advent-calendar.org/2016/download/day09-v2.tar.xz If you've got some spare minutes, it would be great if you could give that new version another try to see whether the warning from Avira is now properly gone (I don't have a Windows here to test this on my own). Thanks, Thomas
[Qemu-devel] [Bug 1649040] Re: Ubuntu 16.04.1 Grub Splash Doesn't Appear
It's the same in 2.8.0 but I will test it again when I get some time for vmware. I used vmware because it offers better resolution. After posting this issue I have learned a little about virtio and for a few times I was able to boot it with -vag virtio and this was really nice. I was able to resize and qemu will fill the screen to fit. But now when I boot with -vga virtio it just sits there and won't start Ubuntu. These are the options I'm using; qemu-system-x86_64 -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=ubuntu.img,index=0 \ -object iothread,id=iothread0 \ -machine type=q35,accel=kvm,kernel_irqchip=on \ -device virtio-blk-pci,drive=drive0,scsi=off,config-wce=off,iothread=iothread0 \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga virtio \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime I do not understand how QEMU boots options just fine for a few times, then another time you go back and try and nothing works... -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1649040 Title: Ubuntu 16.04.1 Grub Splash Doesn't Appear Status in QEMU: New Bug description: My Specs: Slackware 14.2 x86_64 > Host QEMU 2.7.0 Ubuntu 16.04.1 x86_64 > Guest Start options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 I've started Ubuntu around 6-8 times, and I have only see the Grub Boot Splash appear twice, so pretty much without fail it typically boots past the grub splash and automatically boots... These are the /etc/default/grub settings; (I only changed these options GRUB_TIMEOUT=15 and GRUB_GFXMODE=1440x900) # If you change this file, run 'update-grub' afterwards to update # /boot/grub/grub.cfg. # For full documentation of the options in this file, see: # info -f grub -n 'Simple configuration' GRUB_DEFAULT=0 GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT_QUIET=true GRUB_TIMEOUT=15 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDLINE_LINUX="" # Uncomment to enable BadRAM filtering, modify to suit your needs # This works with Linux (no patch required) and with any kernel that obtains # the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...) #GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef" # Uncomment to disable graphical terminal (grub-pc only) #GRUB_TERMINAL=console # The resolution used on graphical terminal # note that you can use only modes which your graphic card supports via VBE # you can see them in real GRUB with the command `vbeinfo' GRUB_GFXMODE=1440x900 # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux #GRUB_DISABLE_LINUX_UUID=true # Uncomment to disable generation of recovery mode menu entries #GRUB_DISABLE_RECOVERY="true" # Uncomment to get a beep at grub start #GRUB_INIT_TUNE="480 440 1" To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1649040/+subscriptions
Re: [Qemu-devel] [PULL 00/25] First round of misc patches for QEMU 2.9
On 22 December 2016 at 15:22, Paolo Bonzini wrote: > The following changes since commit d1e8e8ecc3d2a1a72504912d671f1cbbac1b06e5: > > Merge remote-tracking branch 'remotes/huth/tags/target-dirs-20161220' into > staging (2016-12-21 21:11:48 +) > > are available in the git repository at: > > git://github.com/bonzini/qemu.git tags/for-upstream > > for you to fetch changes up to 6c7c3c21f95dd9af8a0691c0dd29b07247984122: > > x86: implement la57 paging mode (2016-12-22 16:01:04 +0100) > > > * core support for MemoryRegionCache from myself > * rules.mak speedup and cleanups from myself and Marc-Adnré > * multiboot command line fix from Vlad > * SCSI fixes from myself > * small qemu-timer speedup from myself > * x86 debugging improvements from Doug > * configurable Q35 devices from Chao > * x86 5-level paging support from Kirill > * x86 SHA_NI support for KVM from Yi Sun > * improved kvmclock migration logic from Marcelo > * bugfixes and doc fixes from others Applied, thanks. (Nice to see that git is smart enough to be able to merge this on top of the earlier target-* rename.) -- PMM
[Qemu-devel] [Bug 1649040] Re: Ubuntu 16.04.1 Grub Splash Doesn't Appear
I switched to boot scsi and when I start it, the screen is just blank... qemu-system-x86_64 -drive if=none,id=hd,cache=none,aio=threads,format=raw,file=ubuntu.img,index=0 \ -object iothread,id=iothread0 \ -machine type=q35,accel=kvm,kernel_irqchip=on \ -device virtio-scsi-pci,iothread=iothread0,id=scsi -device scsi-hd,drive=hd \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga virtio \ -soundhw hda \ -usbdevice tablet \ -rtc base=localtime Sometimes when I restart it, I'll get the grub menu and I boot it, then it just sits at the console login, for me to log in with a username and pass, it doesn't go to the DM. I get this message, not sure if it's related; intel_rapl no valid rapl domains found in package 0 -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1649040 Title: Ubuntu 16.04.1 Grub Splash Doesn't Appear Status in QEMU: New Bug description: My Specs: Slackware 14.2 x86_64 > Host QEMU 2.7.0 Ubuntu 16.04.1 x86_64 > Guest Start options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 I've started Ubuntu around 6-8 times, and I have only see the Grub Boot Splash appear twice, so pretty much without fail it typically boots past the grub splash and automatically boots... These are the /etc/default/grub settings; (I only changed these options GRUB_TIMEOUT=15 and GRUB_GFXMODE=1440x900) # If you change this file, run 'update-grub' afterwards to update # /boot/grub/grub.cfg. # For full documentation of the options in this file, see: # info -f grub -n 'Simple configuration' GRUB_DEFAULT=0 GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT_QUIET=true GRUB_TIMEOUT=15 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDLINE_LINUX="" # Uncomment to enable BadRAM filtering, modify to suit your needs # This works with Linux (no patch required) and with any kernel that obtains # the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...) #GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef" # Uncomment to disable graphical terminal (grub-pc only) #GRUB_TERMINAL=console # The resolution used on graphical terminal # note that you can use only modes which your graphic card supports via VBE # you can see them in real GRUB with the command `vbeinfo' GRUB_GFXMODE=1440x900 # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux #GRUB_DISABLE_LINUX_UUID=true # Uncomment to disable generation of recovery mode menu entries #GRUB_DISABLE_RECOVERY="true" # Uncomment to get a beep at grub start #GRUB_INIT_TUNE="480 440 1" To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1649040/+subscriptions
Re: [Qemu-devel] A question about PCI device address spaces
On 22 December 2016 at 09:42, Peter Xu wrote: > Hello, > > Since this is a general topic, I picked it out from the VT-d > discussion and put it here, just want to be more clear of it. > > The issue is, whether we have exposed too much address spaces for > emulated PCI devices? > > Now for each PCI device, we are having PCIDevice::bus_master_as for > the device visible address space, which derived from > pci_device_iommu_address_space(): > > AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) > { > PCIBus *bus = PCI_BUS(dev->bus); > PCIBus *iommu_bus = bus; > > while(iommu_bus && !iommu_bus->iommu_fn && iommu_bus->parent_dev) { > iommu_bus = PCI_BUS(iommu_bus->parent_dev->bus); > } > if (iommu_bus && iommu_bus->iommu_fn) { > return iommu_bus->iommu_fn(bus, iommu_bus->iommu_opaque, dev->devfn); > } > return &address_space_memory; > } > > By default (for no-iommu case), it's pointed to system memory space, > which includes MMIO, and looks wrong - PCI device should not be able to > write to MMIO regions. This is just legacy, I think, ie a combination of "this used to be system memory space so let's not break things" and "PC works mostly like this". It should be possible for the PCI host bridge emulation to set things up so that the device's visible address space is whatever it feels like. The PCI APIs we have for doing this have "iommu" in the name but they work just as well even if the host bridge doesn't actually have an iommu and is just setting up a fixed or slightly configurable mapping. I think it just hasn't been implemented because for guests which aren't misbehaving it doesn't make any difference. thanks -- PMM
[Qemu-devel] [Bug 1649042] Re: Ubuntu 16.04.1 LightDM Resolution Not Correct
Hi I'll just post to here for both issues; https://bugs.launchpad.net/qemu/+bug/1649042 -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1649042 Title: Ubuntu 16.04.1 LightDM Resolution Not Correct Status in QEMU: New Bug description: My Specs: Slackware 14.2 x86_64 > Host Nvidia GPU GTX660M nvidia-driver-352.63 QEMU 2.7.0 Ubuntu 16.04.1 x86_64 > Guest Unity Xorg nouveau - 1:1.0.12-1build2 These are the startup options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 Unity desktop resolution set for 1440x900. I noticed when I come to the login screen to enter my password the LightDM resolution fills my entire desktop. I searched online and found this solution; cp ~/.config/monitor.xml /var/lib/lightdm/.config For now I'm assuming this step should not be needed and the resolution should be correctly detected and set? To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1649042/+subscriptions
[Qemu-devel] [Bug 1649042] Re: Ubuntu 16.04.1 LightDM Resolution Not Correct
LOL TYPO here; https://bugs.launchpad.net/qemu/+bug/1649040 -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1649042 Title: Ubuntu 16.04.1 LightDM Resolution Not Correct Status in QEMU: New Bug description: My Specs: Slackware 14.2 x86_64 > Host Nvidia GPU GTX660M nvidia-driver-352.63 QEMU 2.7.0 Ubuntu 16.04.1 x86_64 > Guest Unity Xorg nouveau - 1:1.0.12-1build2 These are the startup options for Ubuntu: qemu-system-x86_64 -drive format=raw,file=ubuntu.img \ -cpu host \ --enable-kvm \ -smp 2 \ -m 4096 \ -vga vmware \ -soundhw ac97 \ -usbdevice tablet \ -rtc base=localtime \ -usbdevice host:0781:5575 Unity desktop resolution set for 1440x900. I noticed when I come to the login screen to enter my password the LightDM resolution fills my entire desktop. I searched online and found this solution; cp ~/.config/monitor.xml /var/lib/lightdm/.config For now I'm assuming this step should not be needed and the resolution should be correctly detected and set? To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1649042/+subscriptions
[Qemu-devel] [Bug 1652286] [NEW] man qemu 2.8.0
Public bug reported: I noticed when I ran 'man qemu' for version 2.8.0 I am getting this back at the terminal; :1674: warning [p 1, 188.5i, div `an-div', 0.2i]: can't break line :1677: warning [p 1, 188.8i, div `an-div', 0.2i]: can't break line ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1652286 Title: man qemu 2.8.0 Status in QEMU: New Bug description: I noticed when I ran 'man qemu' for version 2.8.0 I am getting this back at the terminal; :1674: warning [p 1, 188.5i, div `an-div', 0.2i]: can't break line :1677: warning [p 1, 188.8i, div `an-div', 0.2i]: can't break line To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1652286/+subscriptions
Re: [Qemu-devel] [PULL 00/25] First round of misc patches for QEMU 2.9
On 23/12/2016 12:15, Peter Maydell wrote: >> * core support for MemoryRegionCache from myself >> * rules.mak speedup and cleanups from myself and Marc-Adnré >> * multiboot command line fix from Vlad >> * SCSI fixes from myself >> * small qemu-timer speedup from myself >> * x86 debugging improvements from Doug >> * configurable Q35 devices from Chao >> * x86 5-level paging support from Kirill >> * x86 SHA_NI support for KVM from Yi Sun >> * improved kvmclock migration logic from Marcelo >> * bugfixes and doc fixes from others > Applied, thanks. (Nice to see that git is smart enough to > be able to merge this on top of the earlier target-* rename.) Actually I did the rebase myself. But yes, I also hardly noticed the rename. Paolo
Re: [Qemu-devel] [PULL 00/25] First round of misc patches for QEMU 2.9
On 23 December 2016 at 12:12, Paolo Bonzini wrote: > On 23/12/2016 12:15, Peter Maydell wrote: >> Applied, thanks. (Nice to see that git is smart enough to >> be able to merge this on top of the earlier target-* rename.) > > Actually I did the rebase myself. Oops, so you did; I was confused, clearly. -- PMM
[Qemu-devel] [Resolved -- false positive] Re: virus in colibriOS QEMU iso?
On Fri, Dec 23, 2016 at 11:25:18AM +0100, Thomas Huth wrote: > On 23.12.2016 10:20, Kashyap Chamarthy wrote: [...] > > Yes, I can confirm that I have downloaded the ISO from the > > official website -- it's a nightly build of their > > SVN revision 6766. > > OK, as far as I can see, the issue comes from the setmbr.exe that is > contained in the iso for writing the KolibriOS to an USB stick. > According to http://board.kolibrios.org/viewtopic.php?t=2295 the report > from Avira is a false positive (likely caused because the program tries > to write to the MBR - which is also what some viruses / trojans are doing). Phew, indeed it's a false positive. To quote verbatim from the above thread, for the record: "The program setmbr.exe modifies MBR of USB flash drives or (optionally) hard disks, to allow them load KolibriOS. Usually programs that modify MBR are viruses - that's why your [Avast] antivirus reported it." > Anyway, since these Windows tools are not required for running > KolibriOS in a VM, I've now removed them from the iso image and > uploaded a new version to avoid future confusion: > > http://www.qemu-advent-calendar.org/2016/download/day09-v2.tar.xz Thanks, Thomas, for the swift response while I was AFK. Glad that we're two people coordinating this. > If you've got some spare minutes, it would be great if you could give > that new version another try to see whether the warning from Avira is > now properly gone (I don't have a Windows here to test this on my own). Yeah, I don't have Windows either to test. But good that this is just a false positive from an overly-paranoid tool. -- /kashyap
[Qemu-devel] [PATCH] ps2: Fix lost scancodes by recent changes
With "ps2: use QEMU qcodes instead of scancodes", key handling was changed to qcode base. But all scancodes are not converted to new one. This adds some missing qcodes what I found in using. Signed-off-by: OGAWA Hirofumi --- hw/input/ps2.c|3 +++ qapi-schema.json |3 ++- ui/input-keymap.c |3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff -puN hw/input/ps2.c~fix-ps2-scancode hw/input/ps2.c --- qemu/hw/input/ps2.c~fix-ps2-scancode2016-12-23 21:14:59.837729450 +0900 +++ qemu-hirofumi/hw/input/ps2.c2016-12-23 21:14:59.840729469 +0900 @@ -394,6 +394,9 @@ static const uint16_t qcode_to_keycode_s [Q_KEY_CODE_LESS] = 0x61, [Q_KEY_CODE_SYSRQ] = 0x7f, [Q_KEY_CODE_RO] = 0x51, +[Q_KEY_CODE_HIRAGANA] = 0x13, +[Q_KEY_CODE_HENKAN] = 0x64, +[Q_KEY_CODE_YEN] = 0x6a, [Q_KEY_CODE_KP_COMMA] = 0x6d, }; diff -puN qapi-schema.json~fix-ps2-scancode qapi-schema.json --- qemu/qapi-schema.json~fix-ps2-scancode 2016-12-23 21:14:59.838729456 +0900 +++ qemu-hirofumi/qapi-schema.json 2016-12-23 21:14:59.840729469 +0900 @@ -3642,7 +3642,8 @@ 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end', 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', -'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', 'ro', +'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', +'ro', 'hiragana', 'henkan', 'yen', 'kp_comma', 'kp_equals', 'power' ] } ## diff -puN ui/input-keymap.c~fix-ps2-scancode ui/input-keymap.c --- qemu/ui/input-keymap.c~fix-ps2-scancode 2016-12-23 21:14:59.839729463 +0900 +++ qemu-hirofumi/ui/input-keymap.c 2016-12-23 21:14:59.840729469 +0900 @@ -131,6 +131,9 @@ static const int qcode_to_number[] = { [Q_KEY_CODE_DELETE] = 0xd3, [Q_KEY_CODE_RO] = 0x73, +[Q_KEY_CODE_HIRAGANA] = 0x70, +[Q_KEY_CODE_HENKAN] = 0x79, +[Q_KEY_CODE_YEN] = 0x7d, [Q_KEY_CODE_KP_COMMA] = 0x7e, [Q_KEY_CODE__MAX] = 0, _ -- OGAWA Hirofumi
[Qemu-devel] [PATCH v3] ipmi: Fix macro issues
From: Corey Minyard Macro parameters should almost always have () around them when used. llvm reported an error on this. Remove redundant parenthesis and put parenthesis around the entire macros with assignments in case they are used in an expression. Remove some unused macros. Reported in https://bugs.launchpad.net/bugs/1651167 Signed-off-by: Corey Minyard Reviewed-by: Eric Blake --- hw/ipmi/isa_ipmi_bt.c | 34 -- 1 file changed, 12 insertions(+), 22 deletions(-) Changed in v3: * Add Eric's reviewed-by. Thanks! Changes in v2: * Put parenthesis around macros that had assignment in them. * Removed some redundant parenthesis. * Removed some macros that were not used. diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c index f036617..68bf5cd 100644 --- a/hw/ipmi/isa_ipmi_bt.c +++ b/hw/ipmi/isa_ipmi_bt.c @@ -37,40 +37,30 @@ #define IPMI_BT_HBUSY_BIT 6 #define IPMI_BT_BBUSY_BIT 7 -#define IPMI_BT_CLR_WR_MASK(1 << IPMI_BT_CLR_WR_BIT) #define IPMI_BT_GET_CLR_WR(d) (((d) >> IPMI_BT_CLR_WR_BIT) & 0x1) -#define IPMI_BT_SET_CLR_WR(d, v) (d) = (((d) & ~IPMI_BT_CLR_WR_MASK) | \ - (((v & 1) << IPMI_BT_CLR_WR_BIT))) -#define IPMI_BT_CLR_RD_MASK(1 << IPMI_BT_CLR_RD_BIT) #define IPMI_BT_GET_CLR_RD(d) (((d) >> IPMI_BT_CLR_RD_BIT) & 0x1) -#define IPMI_BT_SET_CLR_RD(d, v) (d) = (((d) & ~IPMI_BT_CLR_RD_MASK) | \ - (((v & 1) << IPMI_BT_CLR_RD_BIT))) -#define IPMI_BT_H2B_ATN_MASK (1 << IPMI_BT_H2B_ATN_BIT) #define IPMI_BT_GET_H2B_ATN(d) (((d) >> IPMI_BT_H2B_ATN_BIT) & 0x1) -#define IPMI_BT_SET_H2B_ATN(d, v) (d) = (((d) & ~IPMI_BT_H2B_ATN_MASK) | \ -(((v & 1) << IPMI_BT_H2B_ATN_BIT))) #define IPMI_BT_B2H_ATN_MASK (1 << IPMI_BT_B2H_ATN_BIT) #define IPMI_BT_GET_B2H_ATN(d) (((d) >> IPMI_BT_B2H_ATN_BIT) & 0x1) -#define IPMI_BT_SET_B2H_ATN(d, v) (d) = (((d) & ~IPMI_BT_B2H_ATN_MASK) | \ -(((v & 1) << IPMI_BT_B2H_ATN_BIT))) +#define IPMI_BT_SET_B2H_ATN(d, v) ((d) = (((d) & ~IPMI_BT_B2H_ATN_MASK) | \ +(((v) & 1) << IPMI_BT_B2H_ATN_BIT))) #define IPMI_BT_SMS_ATN_MASK (1 << IPMI_BT_SMS_ATN_BIT) #define IPMI_BT_GET_SMS_ATN(d) (((d) >> IPMI_BT_SMS_ATN_BIT) & 0x1) -#define IPMI_BT_SET_SMS_ATN(d, v) (d) = (((d) & ~IPMI_BT_SMS_ATN_MASK) | \ -(((v & 1) << IPMI_BT_SMS_ATN_BIT))) +#define IPMI_BT_SET_SMS_ATN(d, v) ((d) = (((d) & ~IPMI_BT_SMS_ATN_MASK) | \ +(((v) & 1) << IPMI_BT_SMS_ATN_BIT))) #define IPMI_BT_HBUSY_MASK (1 << IPMI_BT_HBUSY_BIT) #define IPMI_BT_GET_HBUSY(d) (((d) >> IPMI_BT_HBUSY_BIT) & 0x1) -#define IPMI_BT_SET_HBUSY(d, v)(d) = (((d) & ~IPMI_BT_HBUSY_MASK) | \ - (((v & 1) << IPMI_BT_HBUSY_BIT))) +#define IPMI_BT_SET_HBUSY(d, v)((d) = (((d) & ~IPMI_BT_HBUSY_MASK) | \ + (((v) & 1) << IPMI_BT_HBUSY_BIT))) #define IPMI_BT_BBUSY_MASK (1 << IPMI_BT_BBUSY_BIT) -#define IPMI_BT_GET_BBUSY(d) (((d) >> IPMI_BT_BBUSY_BIT) & 0x1) -#define IPMI_BT_SET_BBUSY(d, v)(d) = (((d) & ~IPMI_BT_BBUSY_MASK) | \ - (((v & 1) << IPMI_BT_BBUSY_BIT))) +#define IPMI_BT_SET_BBUSY(d, v)((d) = (((d) & ~IPMI_BT_BBUSY_MASK) | \ + (((v) & 1) << IPMI_BT_BBUSY_BIT))) /* Mask register */ @@ -79,13 +69,13 @@ #define IPMI_BT_B2H_IRQ_EN_MASK (1 << IPMI_BT_B2H_IRQ_EN_BIT) #define IPMI_BT_GET_B2H_IRQ_EN(d)(((d) >> IPMI_BT_B2H_IRQ_EN_BIT) & 0x1) -#define IPMI_BT_SET_B2H_IRQ_EN(d, v) (d) = (((d) & ~IPMI_BT_B2H_IRQ_EN_MASK) | \ -(((v & 1) << IPMI_BT_B2H_IRQ_EN_BIT))) +#define IPMI_BT_SET_B2H_IRQ_EN(d, v) ((d) = (((d) & ~IPMI_BT_B2H_IRQ_EN_MASK) |\ +(((v) & 1) << IPMI_BT_B2H_IRQ_EN_BIT))) #define IPMI_BT_B2H_IRQ_MASK (1 << IPMI_BT_B2H_IRQ_BIT) #define IPMI_BT_GET_B2H_IRQ(d) (((d) >> IPMI_BT_B2H_IRQ_BIT) & 0x1) -#define IPMI_BT_SET_B2H_IRQ(d, v)(d) = (((d) & ~IPMI_BT_B2H_IRQ_MASK) | \ -(((v & 1) << IPMI_BT_B2H_IRQ_BIT))) +#define IPMI_BT_SET_B2H_IRQ(d, v)((d) = (((d) & ~IPMI_BT_B2H_IRQ_MASK) | \ +(((v) & 1) << IPMI_BT_B2H_IRQ_BIT))) typedef struct IPMIBT { IPMIBmc *bmc; -- 2.7.4
[Qemu-devel] Proposal for 2.9 release schedule
Considering that Easter is on April 16th, we'd probably want to have the release before that date even in case of a slip. On the other hand, the Christmas / New Year break here means that we'll have to make the development time 1-2 week shorter in practice. 2016-02-21 2.9 soft freeze 2016-03-07 hard freeze / rc0 2016-03-28 rc3 (+3 weeks) 2016-04-04 rc4 or release 2016-04-11 release (if rc4) One possibility is to make soft freeze happen a few days later. Peter/Stefan, how did the experiment go with the new rules for soft freeze? Is it worth repeating it for 2.9 and would it make sense to shorten soft freeze given the new rules? Thanks, Paolo
[Qemu-devel] [PATCH] ui/gtk: Fix mouse wheel on 3.4.0 or later
On 3.4.0 or later, send GDK_SCROLL_SMOOTH event, instead of GDK_SCROLL_UP/DOWN. This fixes it by converting any smooth scroll to up/down. (I.e. without smooth support) Signed-off-by: OGAWA Hirofumi --- ui/gtk.c | 10 ++ 1 file changed, 10 insertions(+) diff -puN ui/gtk.c~mouse-wheel-fix ui/gtk.c --- qemu/ui/gtk.c~mouse-wheel-fix 2016-12-23 23:39:24.419659012 +0900 +++ qemu-hirofumi/ui/gtk.c 2016-12-23 23:39:37.540735673 +0900 @@ -1015,6 +1015,16 @@ static gboolean gd_scroll_event(GtkWidge btn = INPUT_BUTTON_WHEEL_UP; } else if (scroll->direction == GDK_SCROLL_DOWN) { btn = INPUT_BUTTON_WHEEL_DOWN; +#if GTK_CHECK_VERSION(3, 4, 0) +} else if (scroll->direction == GDK_SCROLL_SMOOTH) { +gdouble delta_x, delta_y; +if (!gdk_event_get_scroll_deltas((GdkEvent*)scroll, &delta_x, &delta_y)) +return TRUE; +if (delta_y > 0) +btn = INPUT_BUTTON_WHEEL_DOWN; +else +btn = INPUT_BUTTON_WHEEL_UP; +#endif } else { return TRUE; } _ -- OGAWA Hirofumi
[Qemu-devel] [RFC PATCH] Fix pasting into serial console in GTK ui
This copies the timer hack from ui/console.c kbd_send_chars to ui/gtk.c gd_vc_in. There is no fd-like object to peek repatedly so the paste data is saved in a free-floating buffer only submitted to gtk_timeout_add. Multiple pastes can potentially interleave if qemu blocks for long or the user pastes fast. Signed-off-by: Michal Suchanek --- ui/gtk.c | 57 + 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index a216216..b3810c7 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1715,11 +1715,15 @@ static CharDriverState *gd_vc_handler(ChardevVC *vc, Error **errp) return chr; } -static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size, - gpointer user_data) -{ -VirtualConsole *vc = user_data; +struct vc_in_buffer { +VirtualConsole *vc; +gchar *text; +guint size; +guint sent; +}; +static gboolean do_gd_vc_in(VirtualConsole *vc, gchar *text, guint size) +{ if (vc->vte.echo) { VteTerminal *term = VTE_TERMINAL(vc->vte.terminal); int i; @@ -1742,6 +1746,51 @@ static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size, return TRUE; } +static gint gd_vc_in_timer(gpointer data) +{ +struct vc_in_buffer *inbuf = data; +VirtualConsole *vc = inbuf->vc; +int len = qemu_chr_be_can_write(vc->vte.chr); +int size = inbuf->size - inbuf->sent; +if ( size > len) { +size = len; +} +do_gd_vc_in(vc, inbuf->text + inbuf->sent, size); + +inbuf->sent += size; +if (inbuf->sent < inbuf->size) +return TRUE; +else { +g_clear_pointer(&inbuf->text, g_free); +g_free(inbuf); +return FALSE; +} +} + +static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size, + gpointer user_data) +{ +VirtualConsole *vc = user_data; +int len = qemu_chr_be_can_write(vc->vte.chr); + +if (size > len) { +struct vc_in_buffer *inbuf = g_try_new0(struct vc_in_buffer, 1); +if (!inbuf) +return FALSE; +inbuf->text = g_strndup(text, size); +if (!inbuf->text) { +g_free(inbuf); +return FALSE; +} +inbuf->vc = vc; +inbuf->size = size; +inbuf->sent = len; +size = len; +g_timeout_add(1, gd_vc_in_timer, inbuf); +} +return do_gd_vc_in(vc, text, size); +} + static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc, CharDriverState *chr, int idx, GSList *group, GtkWidget *view_menu) -- 2.10.2
Re: [Qemu-devel] [RFC PATCH] Fix pasting into serial console in GTK ui
Hi, Your series seems to have some coding style problems. See output below for more information: Type: series Message-id: 20161223151253.21338-1-msucha...@suse.de Subject: [Qemu-devel] [RFC PATCH] Fix pasting into serial console in GTK ui === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 # Useful git options git config --local diff.renamelimit 0 git config --local diff.renames True commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..." if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then failed=1 echo fi n=$((n+1)) done exit $failed === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu * [new tag] patchew/20161223151253.21338-1-msucha...@suse.de -> patchew/20161223151253.21338-1-msucha...@suse.de Switched to a new branch 'test' 74e9646 Fix pasting into serial console in GTK ui === OUTPUT BEGIN === Checking PATCH 1/1: Fix pasting into serial console in GTK ui... ERROR: space prohibited after that open parenthesis '(' #51: FILE: ui/gtk.c:1755: +if ( size > len) { ERROR: braces {} are necessary for all arms of this statement #57: FILE: ui/gtk.c:1761: +if (inbuf->sent < inbuf->size) [...] +else { [...] ERROR: braces {} are necessary for all arms of this statement #74: FILE: ui/gtk.c:1778: +if (!inbuf) [...] total: 3 errors, 0 warnings, 70 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. === OUTPUT END === Test command exited with code: 1 --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-de...@freelists.org
[Qemu-devel] [PATCH 20/21] backup: move bitmap handling from backup_do_cow to get_work
Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 30 ++ 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/block/backup.c b/block/backup.c index 900bbd3..b79a481 100644 --- a/block/backup.c +++ b/block/backup.c @@ -383,19 +383,24 @@ static inline int64_t backup_get_work(BackupBlockJob *job) } cluster = next_notif_cluster(job); -if (cluster != -1) { -return cluster; -} +if (cluster == -1) { +if (block_job_should_pause(&job->common) || +job->sync_mode == MIRROR_SYNC_MODE_NONE || check_delay(job)) +{ +return BACKUP_WORKER_PAUSE; +} -if (block_job_should_pause(&job->common) || -job->sync_mode == MIRROR_SYNC_MODE_NONE || check_delay(job)) -{ -return BACKUP_WORKER_PAUSE; +cluster = hbitmap_iter_next(&job->linear_hbi); +if (cluster == -1) { +return BACKUP_WORKER_STOP; +} } -cluster = hbitmap_iter_next(&job->linear_hbi); +assert(hbitmap_get(job->copy_bitmap, cluster)); +hbitmap_reset(job->copy_bitmap, cluster, 1); +set_bit(cluster, job->notif_wait_bitmap); -return cluster == -1 ? BACKUP_WORKER_STOP : cluster; +return cluster; } static void coroutine_fn backup_worker_co(void *opaque) @@ -583,13 +588,6 @@ static void coroutine_fn backup_do_cow(BackupBlockJob *job, int64_t cluster) trace_backup_do_cow_enter(job, qemu_coroutine_self(), cluster); -if (!hbitmap_get(job->copy_bitmap, cluster)) { -trace_backup_do_cow_skip(job, cluster); -return; /* already copied */ -} -hbitmap_reset(job->copy_bitmap, cluster, 1); -set_bit(cluster, job->notif_wait_bitmap); - bounce_buffer = blk_blockalign(blk, job->cluster_size); backup_copy_cluster(job, cluster, bounce_buffer); qemu_vfree(bounce_buffer); -- 1.8.3.1
[Qemu-devel] [PATCH 21/21] backup: refactor: remove backup_do_cow()
Call backup_copy_cluster directly from backup_worker_co. Move io buffer allocation to backup_worker_co (and do not reallocate it for each cluster). Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 28 +--- block/trace-events | 6 ++ 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/block/backup.c b/block/backup.c index b79a481..4a3a874 100644 --- a/block/backup.c +++ b/block/backup.c @@ -222,8 +222,6 @@ static void release_pending_notifiers(BackupBlockJob *job) } } -static void coroutine_fn backup_do_cow(BackupBlockJob *job, int64_t cluster); - /* Size of a cluster in sectors, instead of bytes. */ static inline int64_t cluster_size_sectors(BackupBlockJob *job) { @@ -403,9 +401,14 @@ static inline int64_t backup_get_work(BackupBlockJob *job) return cluster; } +static void coroutine_fn backup_copy_cluster(BackupBlockJob *job, +int64_t cluster, +void *bounce_buffer); + static void coroutine_fn backup_worker_co(void *opaque) { BackupBlockJob *job = opaque; +void *io_buf = blk_blockalign(job->common.blk, job->cluster_size); job->running_workers++; job->nb_busy_workers++; @@ -424,12 +427,13 @@ static void coroutine_fn backup_worker_co(void *opaque) trace_backup_worker_stop(qemu_coroutine_self(), job->nb_busy_workers, job->running_workers, job->waiting_for_workers); +qemu_vfree(io_buf); return; case BACKUP_WORKER_PAUSE: backup_worker_pause(job); break; default: -backup_do_cow(job, cluster); +backup_copy_cluster(job, cluster, io_buf); } } } @@ -546,8 +550,7 @@ static void coroutine_fn backup_copy_cluster(BackupBlockJob *job, int64_t sectors_per_cluster = cluster_size_sectors(job); int64_t offset = cluster * job->cluster_size; -trace_backup_do_cow_process(job, cluster); - +trace_backup_copy_cluster_enter(job, qemu_coroutine_self(), cluster); n = MIN(sectors_per_cluster, job->common.len / BDRV_SECTOR_SIZE - cluster * sectors_per_cluster); @@ -579,20 +582,7 @@ static void coroutine_fn backup_copy_cluster(BackupBlockJob *job, */ job->sectors_read += n; job->common.offset += n * BDRV_SECTOR_SIZE; -} - -static void coroutine_fn backup_do_cow(BackupBlockJob *job, int64_t cluster) -{ -BlockBackend *blk = job->common.blk; -void *bounce_buffer; - -trace_backup_do_cow_enter(job, qemu_coroutine_self(), cluster); - -bounce_buffer = blk_blockalign(blk, job->cluster_size); -backup_copy_cluster(job, cluster, bounce_buffer); -qemu_vfree(bounce_buffer); - -trace_backup_do_cow_return(job, qemu_coroutine_self(), cluster); +trace_backup_copy_cluster_success(job, qemu_coroutine_self(), cluster); } static int coroutine_fn backup_before_write_notify( diff --git a/block/trace-events b/block/trace-events index 54cde28..770b407 100644 --- a/block/trace-events +++ b/block/trace-events @@ -40,10 +40,8 @@ mirror_yield_buf_busy(void *s, int nb_chunks, int in_flight) "s %p requested chu mirror_break_buf_busy(void *s, int nb_chunks, int in_flight) "s %p requested chunks %d in_flight %d" # block/backup.c -backup_do_cow_enter(void *job, void *self, int64_t cluster) "job %p self %p cluster %"PRId64 -backup_do_cow_return(void *job, void *self, int64_t cluster) "job %p self %p cluster %"PRId64 -backup_do_cow_skip(void *job, int64_t cluster) "job %p cluster %"PRId64 -backup_do_cow_process(void *job, int64_t cluster) "job %p cluster %"PRId64 +backup_copy_cluster_enter(void *job, void *self, int64_t cluster) "job %p self %p cluster %"PRId64 +backup_copy_cluster_success(void *job, void *self, int64_t cluster) "job %p self %p cluster %"PRId64 backup_do_read_fail(void *job, void *self, int64_t offset, unsigned bytes, int ret) "job %p self %p offset %"PRId64" bytes %u ret %d" backup_do_write_fail(void *job, void *self, int64_t offset, unsigned bytes, int ret) "job %p self %p offset %"PRId64" bytes %u ret %d" backup_job_wait_workers_start(void) "" -- 1.8.3.1
[Qemu-devel] [RFC PATCH] Fix pasting into serial console in GTK ui
This copies the timer hack from ui/console.c kbd_send_chars to ui/gtk.c gd_vc_in. There is no fd-like object to peek repatedly so the paste data is saved in a free-floating buffer only submitted to gtk_timeout_add. Multiple pastes can potentially interleave if qemu blocks for long or the user pastes fast. Signed-off-by: Michal Suchanek --- ui/gtk.c | 58 ++ 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index a216216..58e97ab 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1715,11 +1715,15 @@ static CharDriverState *gd_vc_handler(ChardevVC *vc, Error **errp) return chr; } -static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size, - gpointer user_data) -{ -VirtualConsole *vc = user_data; +struct vc_in_buffer { +VirtualConsole *vc; +gchar *text; +guint size; +guint sent; +}; +static gboolean do_gd_vc_in(VirtualConsole *vc, gchar *text, guint size) +{ if (vc->vte.echo) { VteTerminal *term = VTE_TERMINAL(vc->vte.terminal); int i; @@ -1742,6 +1746,52 @@ static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size, return TRUE; } +static gint gd_vc_in_timer(gpointer data) +{ +struct vc_in_buffer *inbuf = data; +VirtualConsole *vc = inbuf->vc; +int len = qemu_chr_be_can_write(vc->vte.chr); +int size = inbuf->size - inbuf->sent; +if (size > len) { +size = len; +} +do_gd_vc_in(vc, inbuf->text + inbuf->sent, size); + +inbuf->sent += size; +if (inbuf->sent < inbuf->size) { +return TRUE; +} else { +g_clear_pointer(&inbuf->text, g_free); +g_free(inbuf); +return FALSE; +} +} + +static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size, + gpointer user_data) +{ +VirtualConsole *vc = user_data; +int len = qemu_chr_be_can_write(vc->vte.chr); + +if (size > len) { +struct vc_in_buffer *inbuf = g_try_new0(struct vc_in_buffer, 1); +if (!inbuf) { +return FALSE; +} +inbuf->text = g_strndup(text, size); +if (!inbuf->text) { +g_free(inbuf); +return FALSE; +} +inbuf->vc = vc; +inbuf->size = size; +inbuf->sent = len; +size = len; +g_timeout_add(1, gd_vc_in_timer, inbuf); +} +return do_gd_vc_in(vc, text, size); +} + static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc, CharDriverState *chr, int idx, GSList *group, GtkWidget *view_menu) -- 2.10.2
[Qemu-devel] [Bug 1652333] Re: TCG mode fails to boot Linux kernel with qemu 2.6.0 and libvirt 2.0.0
The Cirros image has a 3.2.0 kernel, in case it helps. -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1652333 Title: TCG mode fails to boot Linux kernel with qemu 2.6.0 and libvirt 2.0.0 Status in QEMU: New Bug description: Trying to boot a Cirros (minimal Linux) VM with qemu 2.6.0 and libvirt 2.0.0 in TCG mode fails for me. The VM gets stuck in "Starting up ..." and never moves on. The command line used to boot the VM was: LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin QEMU_AUDIO_DRV=none /usr/libexec/qemu-kvm -name guest=instance-0002,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-instance-0002 /master-key.aes -machine pc-i440fx-rhel7.3.0,accel=tcg,usb=off -cpu SandyBridge,+osxsave,+hypervisor,+xsaveopt -m 512 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c -smbios 'type=1,manufacturer=Red Hat,product=OpenStack Compute,version=14.0.2-7.el7ost,serial=edd3a67d- 6ce5-4c36-8f20-085d1097abb7,uuid=ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c,family=Virtual Machine' -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-1-instance-0002/monitor.sock,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no- shutdown -boot strict=on -device piix3-usb- uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/var/lib/nova/instances/ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c/disk,format=qcow2,if=none,id=drive-virtio- disk0,cache=none -device virtio-blk- pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio- disk0,bootindex=1 -netdev tap,fd=28,id=hostnet0 -device virtio-net- pci,netdev=hostnet0,id=net0,mac=fa:16:3e:c1:27:73,bus=pci.0,addr=0x3 -add-fd set=1,fd=31 -chardev file,id=charserial0,path=/dev/fdset/1,append=on -device isa- serial,chardev=charserial0,id=serial0 -chardev pty,id=charserial1 -device isa-serial,chardev=charserial1,id=serial1 -device usb- tablet,id=input0,bus=usb.0,port=1 -vnc 0.0.0.0:0 -k en-us -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon- pci,id=balloon0,bus=pci.0,addr=0x5 -msg timestamp=on A qcow2 image can be downloaded from http://download.cirros- cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img to reproduce the issue. I've seen a similar failure with a CentOS 7.2 image. I am also attaching the libvirt log from the failed VM. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1652333/+subscriptions
[Qemu-devel] [Bug 1652333] [NEW] TCG mode fails to boot Linux kernel with qemu 2.6.0 and libvirt 2.0.0
Public bug reported: Trying to boot a Cirros (minimal Linux) VM with qemu 2.6.0 and libvirt 2.0.0 in TCG mode fails for me. The VM gets stuck in "Starting up ..." and never moves on. The command line used to boot the VM was: LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin QEMU_AUDIO_DRV=none /usr/libexec/qemu-kvm -name guest=instance-0002 ,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-instance-0002 /master-key.aes -machine pc-i440fx-rhel7.3.0,accel=tcg,usb=off -cpu SandyBridge,+osxsave,+hypervisor,+xsaveopt -m 512 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c -smbios 'type=1,manufacturer=Red Hat,product=OpenStack Compute,version=14.0.2-7.el7ost,serial=edd3a67d- 6ce5-4c36-8f20-085d1097abb7,uuid=ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c,family=Virtual Machine' -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-1-instance-0002/monitor.sock,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no- shutdown -boot strict=on -device piix3-usb- uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/var/lib/nova/instances/ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c/disk,format=qcow2,if=none,id=drive-virtio- disk0,cache=none -device virtio-blk- pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio- disk0,bootindex=1 -netdev tap,fd=28,id=hostnet0 -device virtio-net- pci,netdev=hostnet0,id=net0,mac=fa:16:3e:c1:27:73,bus=pci.0,addr=0x3 -add-fd set=1,fd=31 -chardev file,id=charserial0,path=/dev/fdset/1,append=on -device isa- serial,chardev=charserial0,id=serial0 -chardev pty,id=charserial1 -device isa-serial,chardev=charserial1,id=serial1 -device usb- tablet,id=input0,bus=usb.0,port=1 -vnc 0.0.0.0:0 -k en-us -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon- pci,id=balloon0,bus=pci.0,addr=0x5 -msg timestamp=on A qcow2 image can be downloaded from http://download.cirros- cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img to reproduce the issue. I've seen a similar failure with a CentOS 7.2 image. I am also attaching the libvirt log from the failed VM. ** Affects: qemu Importance: Undecided Status: New ** Attachment added: "Libvirt log from failed VM" https://bugs.launchpad.net/bugs/1652333/+attachment/4795733/+files/instance-0002.log -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1652333 Title: TCG mode fails to boot Linux kernel with qemu 2.6.0 and libvirt 2.0.0 Status in QEMU: New Bug description: Trying to boot a Cirros (minimal Linux) VM with qemu 2.6.0 and libvirt 2.0.0 in TCG mode fails for me. The VM gets stuck in "Starting up ..." and never moves on. The command line used to boot the VM was: LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin QEMU_AUDIO_DRV=none /usr/libexec/qemu-kvm -name guest=instance-0002,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-instance-0002 /master-key.aes -machine pc-i440fx-rhel7.3.0,accel=tcg,usb=off -cpu SandyBridge,+osxsave,+hypervisor,+xsaveopt -m 512 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c -smbios 'type=1,manufacturer=Red Hat,product=OpenStack Compute,version=14.0.2-7.el7ost,serial=edd3a67d- 6ce5-4c36-8f20-085d1097abb7,uuid=ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c,family=Virtual Machine' -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-1-instance-0002/monitor.sock,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no- shutdown -boot strict=on -device piix3-usb- uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/var/lib/nova/instances/ae38b0e1-b3ae-41ec- 8e50-c89669a2ec1c/disk,format=qcow2,if=none,id=drive-virtio- disk0,cache=none -device virtio-blk- pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio- disk0,bootindex=1 -netdev tap,fd=28,id=hostnet0 -device virtio-net- pci,netdev=hostnet0,id=net0,mac=fa:16:3e:c1:27:73,bus=pci.0,addr=0x3 -add-fd set=1,fd=31 -chardev file,id=charserial0,path=/dev/fdset/1,append=on -device isa- serial,chardev=charserial0,id=serial0 -chardev pty,id=charserial1 -device isa-serial,chardev=charserial1,id=serial1 -device usb- tablet,id=input0,bus=usb.0,port=1 -vnc 0.0.0.0:0 -k en-us -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon- pci,id=balloon0,bus=pci.0,addr=0x5 -msg timestamp=on A qcow2 image can be downloaded from http://download.cirros- cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img to reproduce the issue. I've seen a similar failure with a CentOS 7.2 image. I am also attaching the libvirt log from the failed VM. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1652333/+subsc
[Qemu-devel] [PATCH 01/21] backup: move from done_bitmap to copy_bitmap
Use HBitmap copy_bitmap instead of done_bitmap. This is needed to unify backup loop for full/incremental modes in future patches. We reset bit of the copy_bitmap immediately after checking it in backup_do_cow(). It is safe, because all other intersecting requests will wait for our request finish anyway. The other difference is that in case of error we will have zeroed bit in copy_bitmap, when in done_bitmap we have not set bit. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 17 ++--- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/block/backup.c b/block/backup.c index ea38733..6b27e55 100644 --- a/block/backup.c +++ b/block/backup.c @@ -39,11 +39,12 @@ typedef struct BackupBlockJob { BlockdevOnError on_target_error; CoRwlock flush_rwlock; uint64_t sectors_read; -unsigned long *done_bitmap; int64_t cluster_size; bool compress; NotifierWithReturn before_write; QLIST_HEAD(, CowRequest) inflight_reqs; + +HBitmap *copy_bitmap; } BackupBlockJob; /* Size of a cluster in sectors, instead of bytes. */ @@ -115,10 +116,11 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job, cow_request_begin(&cow_request, job, start, end); for (; start < end; start++) { -if (test_bit(start, job->done_bitmap)) { +if (!hbitmap_get(job->copy_bitmap, start)) { trace_backup_do_cow_skip(job, start); continue; /* already copied */ } +hbitmap_reset(job->copy_bitmap, start, 1); trace_backup_do_cow_process(job, start); @@ -141,6 +143,7 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job, if (error_is_read) { *error_is_read = true; } +hbitmap_set(job->copy_bitmap, start, 1); goto out; } @@ -157,11 +160,10 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job, if (error_is_read) { *error_is_read = false; } +hbitmap_set(job->copy_bitmap, start, 1); goto out; } -set_bit(start, job->done_bitmap); - /* Publish progress, guest I/O counts as progress too. Note that the * offset field is an opaque progress value, it is not a disk offset. */ @@ -271,7 +273,7 @@ void backup_do_checkpoint(BlockJob *job, Error **errp) } len = DIV_ROUND_UP(backup_job->common.len, backup_job->cluster_size); -bitmap_zero(backup_job->done_bitmap, len); +hbitmap_set(backup_job->copy_bitmap, 0, len); } void backup_wait_for_overlapping_requests(BlockJob *job, int64_t sector_num, @@ -450,7 +452,8 @@ static void coroutine_fn backup_run(void *opaque) start = 0; end = DIV_ROUND_UP(job->common.len, job->cluster_size); -job->done_bitmap = bitmap_new(end); +job->copy_bitmap = hbitmap_alloc(end, 0); +hbitmap_set(job->copy_bitmap, 0, end); job->before_write.notify = backup_before_write_notify; bdrv_add_before_write_notifier(bs, &job->before_write); @@ -524,7 +527,7 @@ static void coroutine_fn backup_run(void *opaque) /* wait until pending backup_do_cow() calls have completed */ qemu_co_rwlock_wrlock(&job->flush_rwlock); qemu_co_rwlock_unlock(&job->flush_rwlock); -g_free(job->done_bitmap); +hbitmap_free(job->copy_bitmap); data = g_malloc(sizeof(*data)); data->ret = ret; -- 1.8.3.1
[Qemu-devel] [PATCH 05/21] hbitmap: improve dirty iter
Make dirty iter resistant to resetting bits in corresponding HBitmap. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/qemu/hbitmap.h | 24 ++-- util/hbitmap.c | 23 ++- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h index eb46475..2873a46 100644 --- a/include/qemu/hbitmap.h +++ b/include/qemu/hbitmap.h @@ -243,10 +243,7 @@ void hbitmap_free(HBitmap *hb); * the lowest-numbered bit that is set in @hb, starting at @first. * * Concurrent setting of bits is acceptable, and will at worst cause the - * iteration to miss some of those bits. Resetting bits before the current - * position of the iterator is also okay. However, concurrent resetting of - * bits can lead to unexpected behavior if the iterator has not yet reached - * those bits. + * iteration to miss some of those bits. Resetting bits is also okay. */ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first); @@ -285,24 +282,7 @@ void hbitmap_free_meta(HBitmap *hb); * Return the next bit that is set in @hbi's associated HBitmap, * or -1 if all remaining bits are zero. */ -static inline int64_t hbitmap_iter_next(HBitmapIter *hbi) -{ -unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1]; -int64_t item; - -if (cur == 0) { -cur = hbitmap_iter_skip_words(hbi); -if (cur == 0) { -return -1; -} -} - -/* The next call will resume work from the next bit. */ -hbi->cur[HBITMAP_LEVELS - 1] = cur & (cur - 1); -item = ((uint64_t)hbi->pos << BITS_PER_LEVEL) + ctzl(cur); - -return item << hbi->granularity; -} +int64_t hbitmap_iter_next(HBitmapIter *hbi); /** * hbitmap_iter_next_word: diff --git a/util/hbitmap.c b/util/hbitmap.c index 5d1a21c..48d8b2d 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -106,8 +106,9 @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi) unsigned long cur; do { -cur = hbi->cur[--i]; +i--; pos >>= BITS_PER_LEVEL; +cur = hbi->cur[i] & hb->levels[i][pos]; } while (cur == 0); /* Check for end of iteration. We always use fewer than BITS_PER_LONG @@ -139,6 +140,26 @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi) return cur; } +int64_t hbitmap_iter_next(HBitmapIter *hbi) +{ +unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1] & +hbi->hb->levels[HBITMAP_LEVELS - 1][hbi->pos]; +int64_t item; + +if (cur == 0) { +cur = hbitmap_iter_skip_words(hbi); +if (cur == 0) { +return -1; +} +} + +/* The next call will resume work from the next bit. */ +hbi->cur[HBITMAP_LEVELS - 1] = cur & (cur - 1); +item = ((uint64_t)hbi->pos << BITS_PER_LEVEL) + ctzl(cur); + +return item << hbi->granularity; +} + void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first) { unsigned i, bit; -- 1.8.3.1
[Qemu-devel] [PATCH 18/21] backup: new async architecture
New async scheme: all copying is done by worker coroutines. Main block-job coroutine serves initial skipping of unallocated clusters, and also all pauses, error handling, throttling. Notifiers just mark clusters as awaited (by adding NotifierRequest to the list) and wait for some time (5 sec) for these clusters. Because of the imporvements (async, fast, skipping unallocated) some tests failed, so they are fixed here too. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 641 --- block/trace-events | 31 ++- blockjob.c | 29 ++- include/block/blockjob.h | 15 +- tests/qemu-iotests/055 | 2 +- tests/qemu-iotests/129 | 6 +- 6 files changed, 569 insertions(+), 155 deletions(-) diff --git a/block/backup.c b/block/backup.c index c2f7665..558b871 100644 --- a/block/backup.c +++ b/block/backup.c @@ -27,6 +27,18 @@ #define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16) #define SLICE_TIME 1ULL /* ns */ +#define BACKUP_LOOP_DELAY 1ULL /* ns */ +#define WRITE_NOTIFY_TIMEOUT_NS 50LL + +#define NB_WORKERS 24 + +typedef struct NotifierRequest { +int64_t start; /* in clusters */ +int64_t end; /* in clusters */ +int nb_wait; /* awaited clusters */ +Coroutine *notif; +QSIMPLEQ_ENTRY(NotifierRequest) list; +} NotifierRequest; typedef struct BackupBlockJob { BlockJob common; @@ -37,7 +49,6 @@ typedef struct BackupBlockJob { RateLimit limit; BlockdevOnError on_source_error; BlockdevOnError on_target_error; -CoRwlock flush_rwlock; uint64_t sectors_read; int64_t cluster_size; bool compress; @@ -45,19 +56,26 @@ typedef struct BackupBlockJob { QLIST_HEAD(, CowRequest) inflight_reqs; HBitmap *copy_bitmap; +HBitmapIter linear_hbi; + +CoQueue paused_workers; +int running_workers; +int nb_busy_workers; + +bool delayed; +bool waiting_for_workers; +bool error_exit; +bool has_errors; +BlockErrorAction error_action; +int main_error; +bool main_error_is_read; + +unsigned long *notif_wait_bitmap; +QSIMPLEQ_HEAD(, NotifierRequest) notifier_reqs; +NotifierRequest *current_notif; +HBitmapIter current_notif_hbi; } BackupBlockJob; -/* Size of a cluster in sectors, instead of bytes. */ -static inline int64_t cluster_size_sectors(BackupBlockJob *job) -{ - return job->cluster_size / BDRV_SECTOR_SIZE; -} - -static inline int64_t max_query_sectors(BackupBlockJob *job) -{ -return (INT_MAX & ~(job->cluster_size - 1)) >> BDRV_SECTOR_BITS; -} - /* See if in-flight requests overlap and wait for them to complete */ static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job, int64_t start, @@ -95,6 +113,129 @@ static void cow_request_end(CowRequest *req) qemu_co_queue_restart_all(&req->wait_queue); } +static inline void set_notif_cur(BackupBlockJob *job, NotifierRequest *nr) +{ +if (nr != NULL) { +hbitmap_iter_init(&job->current_notif_hbi, job->copy_bitmap, nr->start); +} +job->current_notif = nr; +} + +/* NULL result means that request is already done */ +static NotifierRequest *add_notif_req(BackupBlockJob *job, + int64_t start, int64_t end, + Coroutine *notif) +{ +NotifierRequest *nr; +int nb_wait = bitmap_count_between(job->notif_wait_bitmap, start, end) + + hbitmap_count_between(job->copy_bitmap, start, end); + +if (nb_wait == 0) { +return NULL; +} + +nr = g_new0(NotifierRequest, 1); + +nr->start = start; +nr->end = end; +nr->notif = notif; +nr->nb_wait = nb_wait; + +QSIMPLEQ_INSERT_TAIL(&job->notifier_reqs, nr, list); +if (job->current_notif == NULL) { +set_notif_cur(job, nr); +} + +return nr; +} + +static void detach_notif_req(BackupBlockJob *job, NotifierRequest *req) +{ +assert(req); + +if (job->current_notif == req) { +set_notif_cur(job, QSIMPLEQ_NEXT(req, list)); +} + +QSIMPLEQ_REMOVE(&job->notifier_reqs, req, NotifierRequest, list); +} + +static int64_t next_notif_cluster(BackupBlockJob *job) +{ +while (job->current_notif != NULL) { +int64_t cluster = hbitmap_iter_next(&job->current_notif_hbi); +if (cluster != -1 && cluster < job->current_notif->end) { +return cluster; +} + +/* nothing to do for current notifier */ +set_notif_cur(job, QSIMPLEQ_NEXT(job->current_notif, list)); +} + +/* nothing to do for notifiers */ +return -1; +} + +static void finish_cluster_for_notif(BackupBlockJob *job, int64_t cluster) +{ +NotifierRequest *req, *next; +QSIMPLEQ_HEAD(, NotifierRequest) finished_reqs; +QSIMPLEQ_INIT(&finished_reqs); + +trace_backup_finish_cluster_for_notif(job, cluster); + +clear_bit(cluster, job->notif_wait_bitma
Re: [Qemu-devel] [RFC PATCH] Fix pasting into serial console in GTK ui
On 23/12/2016 16:12, Michal Suchanek wrote: > This copies the timer hack from ui/console.c kbd_send_chars to ui/gtk.c > gd_vc_in. > > There is no fd-like object to peek repatedly so the paste data is saved > in a free-floating buffer only submitted to gtk_timeout_add. Multiple > pastes can potentially interleave if qemu blocks for long or the user > pastes fast. Do not use a timer, instead set chr->chr_accept_input in gd_vc_handler. The callback can do basically what you are doing in gd_vc_in_timer. The buffer can be just a GString plus a "head" pointer, in VirtualConsole. Once the head catches up with the tail, you can free the GString. Paolo
[Qemu-devel] [PATCH 17/21] backup: make all reads not serializing
To simplify things make all reads not serializing, not only from notifiers. This is needed because after the following patch, there would not be strong division between reads from notifiers or not - they all would be called from one place. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 20 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/block/backup.c b/block/backup.c index 442e6da..c2f7665 100644 --- a/block/backup.c +++ b/block/backup.c @@ -134,14 +134,13 @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job) static int coroutine_fn backup_do_read(BackupBlockJob *job, int64_t offset, unsigned int bytes, - QEMUIOVector *qiov, - bool is_write_notifier) + QEMUIOVector *qiov) { int ret; -BdrvRequestFlags flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0; retry: -ret = blk_co_preadv(job->common.blk, offset, bytes, qiov, flags); +ret = blk_co_preadv(job->common.blk, offset, bytes, qiov, +BDRV_REQ_NO_SERIALISING); if (ret < 0) { trace_backup_do_read_fail(job, offset, bytes, ret); @@ -190,7 +189,6 @@ retry: static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, int64_t cluster, -bool is_write_notifier, void *bounce_buffer) { int n; @@ -210,8 +208,7 @@ static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, iov.iov_len = n * BDRV_SECTOR_SIZE; qemu_iovec_init_external(&bounce_qiov, &iov, 1); -ret = backup_do_read(job, offset, bounce_qiov.size, &bounce_qiov, - is_write_notifier); +ret = backup_do_read(job, offset, bounce_qiov.size, &bounce_qiov); if (ret < 0) { return ret; } @@ -231,8 +228,7 @@ static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, } static int coroutine_fn backup_do_cow(BackupBlockJob *job, - int64_t sector_num, int nb_sectors, - bool is_write_notifier) + int64_t sector_num, int nb_sectors) { BlockBackend *blk = job->common.blk; CowRequest cow_request; @@ -262,7 +258,7 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job, bounce_buffer = blk_blockalign(blk, job->cluster_size); } -ret = backup_copy_cluster(job, start, is_write_notifier, bounce_buffer); +ret = backup_copy_cluster(job, start, bounce_buffer); if (ret < 0) { hbitmap_set(job->copy_bitmap, start, 1); goto out; @@ -296,7 +292,7 @@ static int coroutine_fn backup_before_write_notify( assert((req->offset & (BDRV_SECTOR_SIZE - 1)) == 0); assert((req->bytes & (BDRV_SECTOR_SIZE - 1)) == 0); -return backup_do_cow(job, sector_num, nb_sectors, true); +return backup_do_cow(job, sector_num, nb_sectors); } static void backup_set_speed(BlockJob *job, int64_t speed, Error **errp) @@ -544,7 +540,7 @@ static int coroutine_fn backup_loop(BackupBlockJob *job) } ret = backup_do_cow(job, cluster * sectors_per_cluster, -sectors_per_cluster, false); +sectors_per_cluster); if (ret < 0) { return ret; } -- 1.8.3.1
[Qemu-devel] [PATCH 16/21] hbitmap: add hbitmap_count_between() function
Add this function only for HBitmap's with greanularity = 0. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Pavel Butsykin --- include/qemu/hbitmap.h | 2 ++ util/hbitmap.c | 9 + 2 files changed, 11 insertions(+) diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h index 2873a46..1967e13 100644 --- a/include/qemu/hbitmap.h +++ b/include/qemu/hbitmap.h @@ -314,4 +314,6 @@ static inline size_t hbitmap_iter_next_word(HBitmapIter *hbi, unsigned long *p_c } +uint64_t hbitmap_count_between(HBitmap *hb, uint64_t start, uint64_t end); + #endif diff --git a/util/hbitmap.c b/util/hbitmap.c index 48d8b2d..d06bfa3 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -232,6 +232,15 @@ static uint64_t hb_count_between(HBitmap *hb, uint64_t start, uint64_t last) return count; } +/* hbitmap_count_between() is only for HBitmap's with granularity = 0 */ +uint64_t hbitmap_count_between(HBitmap *hb, uint64_t start, uint64_t end) +{ +assert(hb->granularity == 0); +assert(start < end); + +return hb_count_between(hb, start, end - 1); +} + /* Setting starts at the last layer and propagates up if an element * changes. */ -- 1.8.3.1
[Qemu-devel] [PATCH 15/21] bitmap: add bitmap_count_between() function
Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Pavel Butsykin --- include/qemu/bitmap.h | 4 util/bitmap.c | 27 +++ 2 files changed, 31 insertions(+) diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h index 63ea2d0..3bfc33e 100644 --- a/include/qemu/bitmap.h +++ b/include/qemu/bitmap.h @@ -216,6 +216,10 @@ static inline int bitmap_intersects(const unsigned long *src1, } } +unsigned long bitmap_count_between(const unsigned long *src, + unsigned long start, + unsigned long end); + void bitmap_set(unsigned long *map, long i, long len); void bitmap_set_atomic(unsigned long *map, long i, long len); void bitmap_clear(unsigned long *map, long start, long nr); diff --git a/util/bitmap.c b/util/bitmap.c index 43ed011..e5aaa1c 100644 --- a/util/bitmap.c +++ b/util/bitmap.c @@ -336,3 +336,30 @@ int slow_bitmap_intersects(const unsigned long *bitmap1, } return 0; } + +unsigned long bitmap_count_between(const unsigned long *src, + unsigned long start, + unsigned long end) +{ +unsigned long first = start / BITS_PER_LONG; +unsigned long lim = end / BITS_PER_LONG; +unsigned long sum, i; + +assert(start < end); + +sum = ctpopl(src[first] & BITMAP_FIRST_WORD_MASK(start)); + +for (i = first + 1; i < lim; ++i) { +sum += ctpopl(src[i]); +} + +if (end % BITS_PER_LONG) { +if (first == lim) { +sum -= ctpopl(src[first] & BITMAP_FIRST_WORD_MASK(end)); +} else { +sum += ctpopl(src[i] & BITMAP_LAST_WORD_MASK(end)); +} +} + +return sum; +} -- 1.8.3.1
[Qemu-devel] [PATCH 03/21] backup: improve non-dirty bits progress processing
Set fake progress for non-dirty clusters in copy_bitmap initialization, to: 1. set progress in the same place where corresponding clusters are consumed from copy_bitmap (or not initialized, as here) 2. earlier progress information for user 3. simplify the code Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 18 +++--- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/block/backup.c b/block/backup.c index 621b1c0..f1f87f6 100644 --- a/block/backup.c +++ b/block/backup.c @@ -383,7 +383,6 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job) int64_t sector; int64_t cluster; int64_t end; -int64_t last_cluster = -1; int64_t sectors_per_cluster = cluster_size_sectors(job); BdrvDirtyBitmapIter *dbi; @@ -395,12 +394,6 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job) while ((sector = bdrv_dirty_iter_next(dbi)) != -1) { cluster = sector / sectors_per_cluster; -/* Fake progress updates for any clusters we skipped */ -if (cluster != last_cluster + 1) { -job->common.offset += ((cluster - last_cluster - 1) * - job->cluster_size); -} - for (end = cluster + clusters_per_iter; cluster < end; cluster++) { do { if (yield_and_check(job)) { @@ -422,14 +415,6 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job) if (granularity < job->cluster_size) { bdrv_set_dirty_iter(dbi, cluster * sectors_per_cluster); } - -last_cluster = cluster - 1; -} - -/* Play some final catchup with the progress meter */ -end = DIV_ROUND_UP(job->common.len, job->cluster_size); -if (last_cluster + 1 < end) { -job->common.offset += ((end - last_cluster - 1) * job->cluster_size); } out: @@ -462,6 +447,9 @@ static void backup_incremental_init_copy_bitmap(BackupBlockJob *job) bdrv_set_dirty_iter(dbi, (cluster + cl_gran) * sectors_per_cluster); } +job->common.offset = job->common.len - + hbitmap_count(job->copy_bitmap) * job->cluster_size; + bdrv_dirty_iter_free(dbi); } -- 1.8.3.1
[Qemu-devel] [PATCH 04/21] backup: use copy_bitmap in incremental backup
We can use copy_bitmap instead of sync_bitmap. copy_bitmap is initialized from sync_bitmap and it is more informative: we will not try to process data, that is already in progress (by write notifier). Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 58 +++--- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/block/backup.c b/block/backup.c index f1f87f6..938b7df 100644 --- a/block/backup.c +++ b/block/backup.c @@ -376,50 +376,30 @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job) static int coroutine_fn backup_run_incremental(BackupBlockJob *job) { +int ret; bool error_is_read; -int ret = 0; -int clusters_per_iter; -uint32_t granularity; -int64_t sector; -int64_t cluster; -int64_t end; int64_t sectors_per_cluster = cluster_size_sectors(job); -BdrvDirtyBitmapIter *dbi; - -granularity = bdrv_dirty_bitmap_granularity(job->sync_bitmap); -clusters_per_iter = MAX((granularity / job->cluster_size), 1); -dbi = bdrv_dirty_iter_new(job->sync_bitmap, 0); - -/* Find the next dirty sector(s) */ -while ((sector = bdrv_dirty_iter_next(dbi)) != -1) { -cluster = sector / sectors_per_cluster; - -for (end = cluster + clusters_per_iter; cluster < end; cluster++) { -do { -if (yield_and_check(job)) { -goto out; -} -ret = backup_do_cow(job, cluster * sectors_per_cluster, -sectors_per_cluster, &error_is_read, -false); -if ((ret < 0) && -backup_error_action(job, error_is_read, -ret) == -BLOCK_ERROR_ACTION_REPORT) { -goto out; -} -} while (ret < 0); -} +int64_t cluster; +HBitmapIter hbi; -/* If the bitmap granularity is smaller than the backup granularity, - * we need to advance the iterator pointer to the next cluster. */ -if (granularity < job->cluster_size) { -bdrv_set_dirty_iter(dbi, cluster * sectors_per_cluster); -} +hbitmap_iter_init(&hbi, job->copy_bitmap, 0); +while ((cluster = hbitmap_iter_next(&hbi)) != -1) { +do { +if (yield_and_check(job)) { +return 0; +} +ret = backup_do_cow(job, cluster * sectors_per_cluster, +sectors_per_cluster, &error_is_read, +false); +if ((ret < 0) && +backup_error_action(job, error_is_read, -ret) == +BLOCK_ERROR_ACTION_REPORT) { +return ret; +} +} while (ret < 0); } -out: -bdrv_dirty_iter_free(dbi); -return ret; +return 0; } /* init copy_bitmap from sync_bitmap */ -- 1.8.3.1
[Qemu-devel] [PATCH 06/21] backup: rewrite top mode cluster skipping
TOP backup mode skips not allocated clusters. This patch mark skipped clusters in copy_bitmap to prevent their writing in write notifier (however, they may be written before skipping, but that is not critical). Also, update job->common.offset appropriately, to come eventually to job->common.len. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 135 - 1 file changed, 104 insertions(+), 31 deletions(-) diff --git a/block/backup.c b/block/backup.c index 938b7df..e2b944a 100644 --- a/block/backup.c +++ b/block/backup.c @@ -53,6 +53,11 @@ static inline int64_t cluster_size_sectors(BackupBlockJob *job) return job->cluster_size / BDRV_SECTOR_SIZE; } +static inline int64_t max_query_sectors(BackupBlockJob *job) +{ +return (INT_MAX & ~(job->cluster_size - 1)) >> BDRV_SECTOR_BITS; +} + /* See if in-flight requests overlap and wait for them to complete */ static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job, int64_t start, @@ -374,6 +379,101 @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job) return false; } +static void backup_skip_clusters(BackupBlockJob *job, + int64_t start, int64_t end) +{ +CowRequest cow_request; + +wait_for_overlapping_requests(job, start, end); +cow_request_begin(&cow_request, job, start, end); + +if (end * job->cluster_size > job->common.len) { +int64_t n; +end--; +n = job->common.len - end * job->cluster_size; +assert(n > 0); + +if (hbitmap_get(job->copy_bitmap, end)) { +hbitmap_reset(job->copy_bitmap, end, 1); +job->common.offset += n; +} +} + +for ( ; start < end; start++) { +if (!hbitmap_get(job->copy_bitmap, start)) { +continue; +} + +hbitmap_reset(job->copy_bitmap, start, 1); +job->common.offset += job->cluster_size; +} + +cow_request_end(&cow_request); +} + +static int backup_skip_unallocated_clusters(BackupBlockJob *job, +BlockDriverState *base, +int64_t start, int *n) +{ +int ret; +int64_t sectors_per_cluster = cluster_size_sectors(job); +BlockDriverState *bs = blk_bs(job->common.blk); +int64_t sector_end = job->common.len >> BDRV_SECTOR_BITS; +int64_t sector = start * sectors_per_cluster; +int max_sectors = MIN(max_query_sectors(job), sector_end - sector); +int n_sectors = 0; + +ret = bdrv_is_allocated_above(bs, base, sector, max_sectors, &n_sectors); +if (ret < 0) { +return ret; +} + +if (sector + n_sectors == sector_end || ret == 1) { +*n = DIV_ROUND_UP(n_sectors, sectors_per_cluster); +} else if (n_sectors < sectors_per_cluster) { +*n = 1; +ret = 1; +} else { +*n = n_sectors / sectors_per_cluster; +} + +if (ret == 0) { +backup_skip_clusters(job, start, start + *n); +} + +return 0; +} + +static void backup_skip_loop(BackupBlockJob *job, BlockDriverState *base) +{ +HBitmapIter hbi; +int64_t cluster; +int64_t end = DIV_ROUND_UP(job->common.len, job->cluster_size); + +hbitmap_iter_init(&hbi, job->copy_bitmap, 0); +while ((cluster = hbitmap_iter_next(&hbi)) != -1) { +int n, ret; + +if (yield_and_check(job)) { +return; +} + +ret = backup_skip_unallocated_clusters(job, base, cluster, &n); +if (ret < 0) { +n = 1; +} + +cluster += n; +if (cluster >= end) { +return; +} + +if (n > 1) { +hbitmap_iter_init(&hbi, job->copy_bitmap, cluster); +} +} +} + static int coroutine_fn backup_run_incremental(BackupBlockJob *job) { int ret; @@ -465,6 +565,10 @@ static void coroutine_fn backup_run(void *opaque) ret = backup_run_incremental(job); } else { hbitmap_set(job->copy_bitmap, 0, end); +if (job->sync_mode == MIRROR_SYNC_MODE_TOP) { +backup_skip_loop(job, backing_bs(blk_bs(job->common.blk))); +} + /* Both FULL and TOP SYNC_MODE's require copying.. */ for (; start < end; start++) { bool error_is_read; @@ -472,37 +576,6 @@ static void coroutine_fn backup_run(void *opaque) break; } -if (job->sync_mode == MIRROR_SYNC_MODE_TOP) { -int i, n; -int alloced = 0; - -/* Check to see if these blocks are already in the - * backing file. */ - -for (i = 0; i < sectors_per_cluster;) { -/* bdrv_is_allocated() only returns true/false based - * on the first set of sectors it comes across that - * are are all in the same state. -
[Qemu-devel] [ANNOUNCE] QEMU 2.7.1 Stable released
Hi everyone, I am pleased to announce that the QEMU v2.7.1 stable release is now available: http://wiki.qemu.org/download/qemu-2.7.1.tar.bz2 v2.7.1 is now tagged in the official qemu.git repository, and the stable-2.7 branch has been updated accordingly: http://git.qemu.org/?p=qemu.git;a=shortlog;h=refs/heads/stable-2.7 This update fixes a number of issues relating to migration for both x86 and pseries guests, and addresses a broad range of bugs. Users should upgrade accordingly. Thank you to everyone involved! CHANGELOG: 0d83fcc: Update version for 2.7.1 release (Michael Roth) 4dde694: ide: Fix memory leak in ide_register_restart_cb() (Ashijeet Acharya) 7d17d68: portio: keep references on portio (Marc-André Lureau) 345f1cd: block-backend: Always notify on blk_eject (John Snow) 8d5f2a7: dma-helpers: explicitly pass alignment into DMA helpers (Mark Cave-Ayland) 5f20161: atapi: classify read_cd as conditionally returning data (John Snow) 05838b4: ui/gtk: fix "Copy" menu item segfault (Stefan Hajnoczi) 223d1a2: vfio/pci: Fix vfio_rtl8168_quirk_data_read address offset (Thorsten Kohfeldt) 7f7ac21: msmouse: Fix segfault caused by free the chr before chardev cleanup. (Lin Ma) db1604c: Revert "megasas: remove useless check for cmd->frame" (Paolo Bonzini) cc1fd25: vl: Delay initialization of memory backends (Eduardo Habkost) ee99e42: vhost-user-test: Use libqos instead of pxe-virtio.rom (Eduardo Habkost) 0ef167c: intel_iommu: fix incorrect device invalidate (Peter Xu) 248a780: rules.mak: Use -r instead of -Wl, -r to fix building when PIE is default (Adrian Bunk) 80f630b: pci-assign: sync MSI/MSI-X cap and table with PCIDevice (Peter Xu) 353801c: ivshmem: Fix 64 bit memory bar configuration (Zhuang Yanying) c8a3159: vhost: drop legacy vring layout bits (Greg Kurz) 48fdfeb: block/curl: Do not wait for data beyond EOF (Max Reitz) 6eb194d: block/curl: Remember all sockets (Max Reitz) 7e278ef: block/curl: Fix return value from curl_read_cb (Max Reitz) 6a5ea68: block/curl: Use BDRV_SECTOR_SIZE (Max Reitz) 31454eb: block: Pass unaligned discard requests to drivers (Eric Blake) 5e4eb85: block: Return -ENOTSUP rather than assert on unaligned discards (Eric Blake) dd11d33: block: Let write zeroes fallback work even with small max_transfer (Eric Blake) c4bf37e: qcow2: Inform block layer about discard boundaries (Eric Blake) e9dbd28: slirp: Fix access to freed memory (Samuel Thibault) 92230a5: vhost: adapt vhost_verify_ring_mappings() to virtio 1 ring layout (Greg Kurz) 48b3aa2: block: Don't mark node clean after failed flush (Kevin Wolf) f1372d6: virtio-net: mark VIRTIO_NET_F_GSO as legacy (Michael S. Tsirkin) 63087cd: virtio: allow per-device-class legacy features (Michael S. Tsirkin) 9df69dc: target-ppc: Fix CPU migration from qemu-2.6 <-> later versions (David Gibson) 95a0638: net: fix sending of data with -net socket, listen backend (Daniel P. Berrange) 1790a9d: acpi/ipmi: Initialize the fwinfo before fetching it (Corey Minyard) 1b16ded: memory: Don't use memcpy for ram_device regions (Alex Williamson) ca83f87: memory: Replace skip_dump flag with "ram_device" (Alex Williamson) 2817466: net: rtl8139: limit processing of ring descriptors (Prasad J Pandit) e389e44: qemu-iotests: Test I/O in a single drive from a throttling group (Alberto Garcia) b1fdc94: throttle: Correct access to wrong BlockBackendPublic structures (Alberto Garcia) 6178198: ppc/kvm: Mark 64kB page size support as disabled if not available (Thomas Huth) 857efec: rbd: shift byte count as a 64-bit value (Paolo Bonzini) 99837b0: tests/test-qmp-input-strict: Cover missing struct members (Markus Armbruster) b34c7bd: qapi: Fix crash when 'any' or 'null' parameter is missing (Marc-André Lureau) f3467f5: qmp: fix object-add assert() without props (Marc-André Lureau) 5be5335: char: fix missing return in error path for chardev TLS init (Daniel P. Berrange) af29bd3: qht: fix unlock-after-free segfault upon resizing (Emilio G. Cota) f72ca1a: qht: simplify qht_reset_size (Emilio G. Cota) 4d45fe1: migrate: Fix cpu-throttle-increment regression in HMP (Eric Blake) 4a25ab2: block-backend: remove blk_flush_all (John Snow) 95200eb: qemu: use bdrv_flush_all for vm_stop et al (John Snow) 8e94512: block: reintroduce bdrv_flush_all (John Snow) d40d148: iscsi: Fix divide-by-zero regression on raw SG devices (Eric Blake) f985602: qcow2: fix encryption during cow of sectors (Daniel P. Berrange) a3a2545: vfio/pci: Fix regression in MSI routing configuration (David Gibson) 533dedf: s390x/css: handle cssid 255 correctly (Cornelia Huck) 54c26b7: ahci: clear aiocb in ncq_cb (John Snow) f5436d1: virtio-scsi: Don't abort when media is ejected (Fam Zheng) 3550eea: scsi-disk: Cleaning up around tray open state (Fam Zheng) 316c2c9: iothread: Stop threads before main() quits (Fam Zheng) 98b4465: crypto: ensure XTS is only used with ciphers with 16 byte blocks (Daniel P. Berrange) 8342e12: scsi: mptconfig: fix misuse of MPTSAS_CONFIG_PACK (Paolo Bonzini) 0b6ab25: s
[Qemu-devel] [PATCH 02/21] backup: init copy_bitmap from sync_bitmap for incremental
We should not copy non-dirty clusters in write notifiers. So, initialize copy_bitmap from sync_bitmap. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 32 +++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/block/backup.c b/block/backup.c index 6b27e55..621b1c0 100644 --- a/block/backup.c +++ b/block/backup.c @@ -437,6 +437,34 @@ out: return ret; } +/* init copy_bitmap from sync_bitmap */ +static void backup_incremental_init_copy_bitmap(BackupBlockJob *job) +{ +int64_t sector; +BdrvDirtyBitmapIter *dbi; +uint32_t sect_gran = +bdrv_dirty_bitmap_granularity(job->sync_bitmap) >> BDRV_SECTOR_BITS; +int64_t sz = bdrv_dirty_bitmap_size(job->sync_bitmap); +int64_t sectors_per_cluster = cluster_size_sectors(job); +uint32_t cl_gran = MAX(1, sect_gran / sectors_per_cluster); + +dbi = bdrv_dirty_iter_new(job->sync_bitmap, 0); +while ((sector = bdrv_dirty_iter_next(dbi)) != -1) { +int64_t cluster = sector / sectors_per_cluster; +int64_t next_sector = (cluster + cl_gran) * sectors_per_cluster; + +hbitmap_set(job->copy_bitmap, cluster, cl_gran); + +if (next_sector >= sz) { +break; +} + +bdrv_set_dirty_iter(dbi, (cluster + cl_gran) * sectors_per_cluster); +} + +bdrv_dirty_iter_free(dbi); +} + static void coroutine_fn backup_run(void *opaque) { BackupBlockJob *job = opaque; @@ -453,20 +481,22 @@ static void coroutine_fn backup_run(void *opaque) end = DIV_ROUND_UP(job->common.len, job->cluster_size); job->copy_bitmap = hbitmap_alloc(end, 0); -hbitmap_set(job->copy_bitmap, 0, end); job->before_write.notify = backup_before_write_notify; bdrv_add_before_write_notifier(bs, &job->before_write); if (job->sync_mode == MIRROR_SYNC_MODE_NONE) { +hbitmap_set(job->copy_bitmap, 0, end); while (!block_job_is_cancelled(&job->common)) { /* Yield until the job is cancelled. We just let our before_write * notify callback service CoW requests. */ block_job_yield(&job->common); } } else if (job->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { +backup_incremental_init_copy_bitmap(job); ret = backup_run_incremental(job); } else { +hbitmap_set(job->copy_bitmap, 0, end); /* Both FULL and TOP SYNC_MODE's require copying.. */ for (; start < end; start++) { bool error_is_read; -- 1.8.3.1
[Qemu-devel] [PATCH 07/21] backup: refactor: merge top/full/incremental backup code
Merge top/full/incremental modes backup into one backup_loop. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 41 + 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/block/backup.c b/block/backup.c index e2b944a..2afd1b6 100644 --- a/block/backup.c +++ b/block/backup.c @@ -474,7 +474,7 @@ static void backup_skip_loop(BackupBlockJob *job, BlockDriverState *base) } } -static int coroutine_fn backup_run_incremental(BackupBlockJob *job) +static int coroutine_fn backup_loop(BackupBlockJob *job) { int ret; bool error_is_read; @@ -538,14 +538,12 @@ static void coroutine_fn backup_run(void *opaque) BackupBlockJob *job = opaque; BackupCompleteData *data; BlockDriverState *bs = blk_bs(job->common.blk); -int64_t start, end; -int64_t sectors_per_cluster = cluster_size_sectors(job); +int64_t end; int ret = 0; QLIST_INIT(&job->inflight_reqs); qemu_co_rwlock_init(&job->flush_rwlock); -start = 0; end = DIV_ROUND_UP(job->common.len, job->cluster_size); job->copy_bitmap = hbitmap_alloc(end, 0); @@ -560,37 +558,16 @@ static void coroutine_fn backup_run(void *opaque) * notify callback service CoW requests. */ block_job_yield(&job->common); } -} else if (job->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { -backup_incremental_init_copy_bitmap(job); -ret = backup_run_incremental(job); } else { -hbitmap_set(job->copy_bitmap, 0, end); -if (job->sync_mode == MIRROR_SYNC_MODE_TOP) { -backup_skip_loop(job, backing_bs(blk_bs(job->common.blk))); -} - -/* Both FULL and TOP SYNC_MODE's require copying.. */ -for (; start < end; start++) { -bool error_is_read; -if (yield_and_check(job)) { -break; -} - -/* FULL sync mode we copy the whole drive. */ -ret = backup_do_cow(job, start * sectors_per_cluster, -sectors_per_cluster, &error_is_read, false); -if (ret < 0) { -/* Depending on error action, fail now or retry cluster */ -BlockErrorAction action = -backup_error_action(job, error_is_read, -ret); -if (action == BLOCK_ERROR_ACTION_REPORT) { -break; -} else { -start--; -continue; -} +if (job->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { +backup_incremental_init_copy_bitmap(job); +} else { +hbitmap_set(job->copy_bitmap, 0, end); +if (job->sync_mode == MIRROR_SYNC_MODE_TOP) { +backup_skip_loop(job, backing_bs(blk_bs(job->common.blk))); } } +ret = backup_loop(job); } notifier_with_return_remove(&job->before_write); -- 1.8.3.1
[Qemu-devel] [PATCH 12/21] iotests: add supported_cache_modes to main function
Signed-off-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/iotests.py | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index bec8eb4..a5ef9c3 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -348,6 +348,10 @@ def verify_platform(supported_oses=['linux']): if True not in [sys.platform.startswith(x) for x in supported_oses]: notrun('not suitable for this OS: %s' % sys.platform) +def verify_cache_mode(supported_cache_modes=[]): +if supported_cache_modes and (cachemode not in supported_cache_modes): +notrun('not suitable for this cache mode: %s' % cachemode) + def supports_quorum(): return 'quorum' in qemu_img_pipe('--help') @@ -356,7 +360,7 @@ def verify_quorum(): if not supports_quorum(): notrun('quorum support missing') -def main(supported_fmts=[], supported_oses=['linux']): +def main(supported_fmts=[], supported_oses=['linux'], supported_cache_modes=[]): '''Run tests''' global debug @@ -373,6 +377,7 @@ def main(supported_fmts=[], supported_oses=['linux']): verbosity = 1 verify_image_format(supported_fmts) verify_platform(supported_oses) +verify_cache_mode(supported_cache_modes) # We need to filter out the time taken from the output so that qemu-iotest # can reliably diff the results against master output. -- 1.8.3.1
[Qemu-devel] [PATCH 10/21] backup: refactor backup_copy_cluster()
Split out read and write functions. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 53 +++-- block/trace-events | 4 ++-- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/block/backup.c b/block/backup.c index 2c8b7ba..5c31607 100644 --- a/block/backup.c +++ b/block/backup.c @@ -95,18 +95,53 @@ static void cow_request_end(CowRequest *req) qemu_co_queue_restart_all(&req->wait_queue); } +static int coroutine_fn backup_do_read(BackupBlockJob *job, + int64_t offset, unsigned int bytes, + QEMUIOVector *qiov, + bool is_write_notifier) +{ +int ret = blk_co_preadv(job->common.blk, offset, bytes, qiov, +is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0); +if (ret < 0) { +trace_backup_do_read_fail(job, offset, bytes, ret); +} + +return ret; +} + +static int coroutine_fn backup_do_write(BackupBlockJob *job, +int64_t offset, unsigned int bytes, +QEMUIOVector *qiov) +{ +int ret; +assert(qiov->niov == 1); + +if (buffer_is_zero(qiov->iov->iov_base, qiov->iov->iov_len)) { +ret = blk_co_pwrite_zeroes(job->target, offset, bytes, + BDRV_REQ_MAY_UNMAP); +} else { +ret = blk_co_pwritev(job->target, offset, bytes, qiov, + job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0); +} +if (ret < 0) { +trace_backup_do_write_fail(job, offset, bytes, ret); +} + +return ret; +} + static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, int64_t cluster, bool *error_is_read, bool is_write_notifier, void *bounce_buffer) { -BlockBackend *blk = job->common.blk; int n; struct iovec iov; QEMUIOVector bounce_qiov; int ret = 0; int64_t sectors_per_cluster = cluster_size_sectors(job); +int64_t offset = cluster * job->cluster_size; trace_backup_do_cow_process(job, cluster); @@ -118,27 +153,17 @@ static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, iov.iov_len = n * BDRV_SECTOR_SIZE; qemu_iovec_init_external(&bounce_qiov, &iov, 1); -ret = blk_co_preadv(blk, cluster * job->cluster_size, -bounce_qiov.size, &bounce_qiov, -is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0); +ret = backup_do_read(job, offset, bounce_qiov.size, &bounce_qiov, + is_write_notifier); if (ret < 0) { -trace_backup_do_cow_read_fail(job, cluster, ret); if (error_is_read) { *error_is_read = true; } return ret; } -if (buffer_is_zero(iov.iov_base, iov.iov_len)) { -ret = blk_co_pwrite_zeroes(job->target, cluster * job->cluster_size, - bounce_qiov.size, BDRV_REQ_MAY_UNMAP); -} else { -ret = blk_co_pwritev(job->target, cluster * job->cluster_size, - bounce_qiov.size, &bounce_qiov, - job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0); -} +ret = backup_do_write(job, offset, bounce_qiov.size, &bounce_qiov); if (ret < 0) { -trace_backup_do_cow_write_fail(job, cluster, ret); if (error_is_read) { *error_is_read = false; } diff --git a/block/trace-events b/block/trace-events index cfc05f2..832e8ed 100644 --- a/block/trace-events +++ b/block/trace-events @@ -43,8 +43,8 @@ backup_do_cow_enter(void *job, int64_t start, int64_t sector_num, int nb_sectors backup_do_cow_return(void *job, int64_t sector_num, int nb_sectors, int ret) "job %p sector_num %"PRId64" nb_sectors %d ret %d" backup_do_cow_skip(void *job, int64_t start) "job %p start %"PRId64 backup_do_cow_process(void *job, int64_t start) "job %p start %"PRId64 -backup_do_cow_read_fail(void *job, int64_t start, int ret) "job %p start %"PRId64" ret %d" -backup_do_cow_write_fail(void *job, int64_t start, int ret) "job %p start %"PRId64" ret %d" +backup_do_read_fail(void *job, int64_t offset, unsigned bytes, int ret) "job %p offset %"PRId64" bytes %u ret %d" +backup_do_write_fail(void *job, int64_t offset, unsigned bytes, int ret) "job %p offset %"PRId64" bytes %u ret %d" # blockdev.c qmp_block_job_cancel(void *job) "job %p" -- 1.8.3.1
Re: [Qemu-devel] [PATCH v3 0/6] trace: [tcg] Optimize per-vCPU tracing states with separate TB caches
On 12/22/2016 10:35 AM, Lluís Vilanova wrote: > To handle both issues, this series replicates the shared physical TB cache, > creating a separate physical TB cache for every combination of event states > (those with the 'vcpu' and 'tcg' properties). Then, all vCPUs tracing the same > events will use the same physical TB cache. Why do we need to "split the physical TB cache" as opposed to simply including the trace state into the TB hash function? r~
[Qemu-devel] [PATCH 14/21] block: add trace point on bdrv_close_all
Signed-off-by: Vladimir Sementsov-Ogievskiy --- block.c| 1 + block/trace-events | 1 + 2 files changed, 2 insertions(+) diff --git a/block.c b/block.c index 39ddea3..3aa433b 100644 --- a/block.c +++ b/block.c @@ -2372,6 +2372,7 @@ static void bdrv_close(BlockDriverState *bs) void bdrv_close_all(void) { +trace_bdrv_close_all(); block_job_cancel_sync_all(); nbd_export_close_all(); diff --git a/block/trace-events b/block/trace-events index 832e8ed..e7a7372 100644 --- a/block/trace-events +++ b/block/trace-events @@ -3,6 +3,7 @@ # block.c bdrv_open_common(void *bs, const char *filename, int flags, const char *format_name) "bs %p filename \"%s\" flags %#x format_name \"%s\"" bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d" +bdrv_close_all(void) "" # block/block-backend.c blk_co_preadv(void *blk, void *bs, int64_t offset, unsigned int bytes, int flags) "blk %p bs %p offset %"PRId64" bytes %u flags %x" -- 1.8.3.1
Re: [Qemu-devel] [PATCH 07/10] aio-posix: remove walking_handlers, protecting AioHandler list with list_lock
On 21/12/2016 15:03, Paolo Bonzini wrote: > Signed-off-by: Paolo Bonzini > --- > aio-posix.c | 64 > - > 1 file changed, 38 insertions(+), 26 deletions(-) > > diff --git a/aio-posix.c b/aio-posix.c > index f83b7af..9b13182 100644 > --- a/aio-posix.c > +++ b/aio-posix.c > @@ -16,7 +16,7 @@ > #include "qemu/osdep.h" > #include "qemu-common.h" > #include "block/block.h" > -#include "qemu/queue.h" > +#include "qemu/rcu_queue.h" > #include "qemu/sockets.h" > #include "qemu/cutils.h" > #include "trace.h" > @@ -66,7 +66,7 @@ static bool aio_epoll_try_enable(AioContext *ctx) > AioHandler *node; > struct epoll_event event; > > -QLIST_FOREACH(node, &ctx->aio_handlers, node) { > +QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { > int r; > if (node->deleted || !node->pfd.events) { > continue; > @@ -212,6 +212,8 @@ void aio_set_fd_handler(AioContext *ctx, > bool is_new = false; > bool deleted = false; > > +qemu_lockcnt_lock(&ctx->list_lock); > + > node = find_aio_handler(ctx, fd); > > /* Are we deleting the fd handler? */ Oops, there's a return between this hunks that doesn't release the lock. Will resend. Paolo > @@ -223,13 +225,13 @@ void aio_set_fd_handler(AioContext *ctx, > g_source_remove_poll(&ctx->source, &node->pfd); > > /* If the lock is held, just mark the node as deleted */ > -if (ctx->walking_handlers) { > +if (qemu_lockcnt_count(&ctx->list_lock)) { > node->deleted = 1; > node->pfd.revents = 0; > } else { > /* Otherwise, delete it for real. We can't just mark it as > - * deleted because deleted nodes are only cleaned up after > - * releasing the walking_handlers lock. > + * deleted because deleted nodes are only cleaned up while > + * no one is walking the handlers list. > */ > QLIST_REMOVE(node, node); > deleted = true; > @@ -243,7 +245,7 @@ void aio_set_fd_handler(AioContext *ctx, > /* Alloc and insert if it's not already there */ > node = g_new0(AioHandler, 1); > node->pfd.fd = fd; > -QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); > +QLIST_INSERT_HEAD_RCU(&ctx->aio_handlers, node, node); > > g_source_add_poll(&ctx->source, &node->pfd); > is_new = true; > @@ -265,6 +267,7 @@ void aio_set_fd_handler(AioContext *ctx, > } > > aio_epoll_update(ctx, node, is_new); > +qemu_lockcnt_unlock(&ctx->list_lock); > aio_notify(ctx); > > if (deleted) { > @@ -316,8 +319,8 @@ static void poll_set_started(AioContext *ctx, bool > started) > > ctx->poll_started = started; > > -ctx->walking_handlers++; > -QLIST_FOREACH(node, &ctx->aio_handlers, node) { > +qemu_lockcnt_inc(&ctx->list_lock); > +QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { > IOHandler *fn; > > if (node->deleted) { > @@ -334,7 +337,7 @@ static void poll_set_started(AioContext *ctx, bool > started) > fn(node->opaque); > } > } > -ctx->walking_handlers--; > +qemu_lockcnt_dec(&ctx->list_lock); > } > > > @@ -349,22 +352,32 @@ bool aio_prepare(AioContext *ctx) > bool aio_pending(AioContext *ctx) > { > AioHandler *node; > +bool result = false; > > -QLIST_FOREACH(node, &ctx->aio_handlers, node) { > +/* > + * We have to walk very carefully in case aio_set_fd_handler is > + * called while we're walking. > + */ > +qemu_lockcnt_inc(&ctx->list_lock); > + > +QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { > int revents; > > revents = node->pfd.revents & node->pfd.events; > if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read && > aio_node_check(ctx, node->is_external)) { > -return true; > +result = true; > +break; > } > if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write && > aio_node_check(ctx, node->is_external)) { > -return true; > +result = true; > +break; > } > } > +qemu_lockcnt_dec(&ctx->list_lock); > > -return false; > +return result; > } > > static bool aio_dispatch_handlers(AioContext *ctx) > @@ -376,9 +389,9 @@ static bool aio_dispatch_handlers(AioContext *ctx) > * We have to walk very carefully in case aio_set_fd_handler is > * called while we're walking. > */ > -ctx->walking_handlers++; > +qemu_lockcnt_inc(&ctx->list_lock); > > -QLIST_FOREACH_SAFE(node, &ctx->aio_handlers, node, tmp) { > +QLIST_FOREACH_SAFE_RCU(node, &ctx->aio_handlers, node, tmp) { > int revents; > > revents = node->pfd.revents & node->pfd.events; > @@ -404,16 +417,15 @@ stati
[Qemu-devel] [PATCH 3/3] nbd: do not block on partial reply header reads
Read the replies from a coroutine. qio_channel_yield is used so that the right coroutine is restarted automatically, eliminating the need for send_coroutine in NBDClientSession. Signed-off-by: Paolo Bonzini --- block/nbd-client.c | 108 + 1 file changed, 42 insertions(+), 66 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 06f1532..a3c2c19 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -33,8 +33,9 @@ #define HANDLE_TO_INDEX(bs, handle) ((handle) ^ ((uint64_t)(intptr_t)bs)) #define INDEX_TO_HANDLE(bs, index) ((index) ^ ((uint64_t)(intptr_t)bs)) -static void nbd_recv_coroutines_enter_all(NBDClientSession *s) +static void nbd_recv_coroutines_enter_all(BlockDriverState *bs) { +NBDClientSession *s = nbd_get_client_session(bs); int i; for (i = 0; i < MAX_NBD_REQUESTS; i++) { @@ -42,6 +43,7 @@ static void nbd_recv_coroutines_enter_all(NBDClientSession *s) qemu_coroutine_enter(s->recv_coroutine[i]); } } +BDRV_POLL_WHILE(bs, s->read_reply_co); } static void nbd_teardown_connection(BlockDriverState *bs) @@ -56,7 +58,7 @@ static void nbd_teardown_connection(BlockDriverState *bs) qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); -nbd_recv_coroutines_enter_all(client); +nbd_recv_coroutines_enter_all(bs); nbd_client_detach_aio_context(bs); object_unref(OBJECT(client->sioc)); @@ -65,54 +67,34 @@ static void nbd_teardown_connection(BlockDriverState *bs) client->ioc = NULL; } -static void nbd_reply_ready(void *opaque) +static void nbd_read_reply_entry(void *opaque) { -BlockDriverState *bs = opaque; -NBDClientSession *s = nbd_get_client_session(bs); +NBDClientSession *s = opaque; uint64_t i; int ret; -if (!s->ioc) { /* Already closed */ -return; -} - -if (s->reply.handle == 0) { -/* No reply already in flight. Fetch a header. It is possible - * that another thread has done the same thing in parallel, so - * the socket is not readable anymore. - */ +for (;;) { +assert(s->reply.handle == 0); ret = nbd_receive_reply(s->ioc, &s->reply); -if (ret == -EAGAIN) { -return; -} if (ret < 0) { -s->reply.handle = 0; -goto fail; +break; } -} - -/* There's no need for a mutex on the receive side, because the - * handler acts as a synchronization point and ensures that only - * one coroutine is called until the reply finishes. */ -i = HANDLE_TO_INDEX(s, s->reply.handle); -if (i >= MAX_NBD_REQUESTS) { -goto fail; -} -if (s->recv_coroutine[i]) { -qemu_coroutine_enter(s->recv_coroutine[i]); -return; -} - -fail: -nbd_teardown_connection(bs); -} +/* There's no need for a mutex on the receive side, because the + * handler acts as a synchronization point and ensures that only + * one coroutine is called until the reply finishes. + */ +i = HANDLE_TO_INDEX(s, s->reply.handle); +if (i >= MAX_NBD_REQUESTS || !s->recv_coroutine[i]) { +break; +} -static void nbd_restart_write(void *opaque) -{ -BlockDriverState *bs = opaque; +aio_co_wake(s->recv_coroutine[i]); -qemu_coroutine_enter(nbd_get_client_session(bs)->send_coroutine); +/* We're woken up by the recv_coroutine itself. */ +qemu_coroutine_yield(); +} +s->read_reply_co = NULL; } static int nbd_co_send_request(BlockDriverState *bs, @@ -120,7 +102,6 @@ static int nbd_co_send_request(BlockDriverState *bs, QEMUIOVector *qiov) { NBDClientSession *s = nbd_get_client_session(bs); -AioContext *aio_context; int rc, ret, i; qemu_co_mutex_lock(&s->send_mutex); @@ -141,11 +122,6 @@ static int nbd_co_send_request(BlockDriverState *bs, return -EPIPE; } -s->send_coroutine = qemu_coroutine_self(); -aio_context = bdrv_get_aio_context(bs); - -aio_set_fd_handler(aio_context, s->sioc->fd, false, - nbd_reply_ready, nbd_restart_write, NULL, bs); if (qiov) { qio_channel_set_cork(s->ioc, true); rc = nbd_send_request(s->ioc, request); @@ -160,9 +136,6 @@ static int nbd_co_send_request(BlockDriverState *bs, } else { rc = nbd_send_request(s->ioc, request); } -aio_set_fd_handler(aio_context, s->sioc->fd, false, - nbd_reply_ready, NULL, NULL, bs); -s->send_coroutine = NULL; qemu_co_mutex_unlock(&s->send_mutex); return rc; } @@ -174,8 +147,7 @@ static void nbd_co_receive_reply(NBDClientSession *s, { int ret; -/* Wait until we're woken up by the read handler. TODO: perhaps - * peek at the next reply and avoid yielding if i
[Qemu-devel] [RFC PATCH 0/3] io/nbd: AioContext support
This is RFC because the APIs it uses (aio_co_schedule/aio_co_wake) do not exist yet in master, but it should be enough for a first review of the QIOChannel API concepts and to give an idea of their usage. It makes qio_channel_yield aware of AioContexts by adding a new API qio_channel_set_aio_context, and it lets separate coroutines use qio_channel_yield for reading vs. writing. The last patch rewrites the NBD client's I/O management to use the new infrastructure (and I think the logic here was first proposed years ago by Stefan). The benefit is that the new version does not block if the server writes a partial reply header, and is also a bit smaller. Paolo Paolo Bonzini (3): io: add methods to set I/O handlers on AioContext io: make qio_channel_yield aware of AioContexts nbd: do not block on partial reply header reads block/nbd-client.c | 108 --- include/io/channel.h | 41 +++ io/channel-socket.c | 16 +--- io/channel-tls.c | 12 ++ io/channel-watch.c | 6 +++ io/channel.c | 87 +++-- 6 files changed, 178 insertions(+), 92 deletions(-) -- 2.9.3
[Qemu-devel] [PATCH 2/3] io: make qio_channel_yield aware of AioContexts
Support separate coroutines for reading and writing, and restart the coroutine on the AioContext where it was suspended on. Signed-off-by: Paolo Bonzini --- include/io/channel.h | 7 +++--- io/channel-socket.c | 12 +- io/channel.c | 62 ++-- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/include/io/channel.h b/include/io/channel.h index 248bc76..3030fdb 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -23,6 +23,7 @@ #include "qemu-common.h" #include "qom/object.h" +#include "qemu/coroutine.h" #include "block/aio.h" #define TYPE_QIO_CHANNEL "qio-channel" @@ -59,8 +60,6 @@ typedef gboolean (*QIOChannelFunc)(QIOChannel *ioc, GIOCondition condition, gpointer data); -typedef struct QIOChannelRestart QIOChannelRestart; - /** * QIOChannel: * @@ -84,8 +83,8 @@ struct QIOChannel { unsigned int features; /* bitmask of QIOChannelFeatures */ char *name; AioContext *ctx; -QIOChannelRestart *read_coroutine; -QIOChannelRestart *write_coroutine; +Coroutine *read_coroutine; +Coroutine *write_coroutine; #ifdef _WIN32 HANDLE event; /* For use with GSource on Win32 */ #endif diff --git a/io/channel-socket.c b/io/channel-socket.c index 4d5f180..732ba20 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -740,14 +740,14 @@ qio_channel_socket_shutdown(QIOChannel *ioc, return 0; } -static GSource *qio_channel_socket_set_fd_handler(QIOChannel *ioc, - AioContext *ctx, - IOHandler *io_read, - IOHandler *io_write, - void *opaque) +static void qio_channel_socket_set_fd_handler(QIOChannel *ioc, + AioContext *ctx, + IOHandler *io_read, + IOHandler *io_write, + void *opaque) { QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); -aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, opaque); +aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, NULL, opaque); } static GSource *qio_channel_socket_create_watch(QIOChannel *ioc, diff --git a/io/channel.c b/io/channel.c index 9ef683c..d4b3a5a3 100644 --- a/io/channel.c +++ b/io/channel.c @@ -21,7 +21,7 @@ #include "qemu/osdep.h" #include "io/channel.h" #include "qapi/error.h" -#include "qemu/coroutine.h" +#include "qemu/main-loop.h" bool qio_channel_has_feature(QIOChannel *ioc, QIOChannelFeature feature) @@ -238,22 +238,43 @@ off_t qio_channel_io_seek(QIOChannel *ioc, } -typedef struct QIOChannelYieldData QIOChannelYieldData; -struct QIOChannelYieldData { -QIOChannel *ioc; -Coroutine *co; -}; +static void qio_channel_set_fd_handlers(QIOChannel *ioc); + +static void qio_channel_restart_read(void *opaque) +{ +QIOChannel *ioc = opaque; +Coroutine *co = ioc->read_coroutine; +ioc->read_coroutine = NULL; +qio_channel_set_fd_handlers(ioc); +aio_co_wake(co); +} -static gboolean qio_channel_yield_enter(QIOChannel *ioc, -GIOCondition condition, -gpointer opaque) +static void qio_channel_restart_write(void *opaque) { -QIOChannelYieldData *data = opaque; -qemu_coroutine_enter(data->co); -return FALSE; +QIOChannel *ioc = opaque; +Coroutine *co = ioc->write_coroutine; + +ioc->write_coroutine = NULL; +qio_channel_set_fd_handlers(ioc); +aio_co_wake(co); } +static void qio_channel_set_fd_handlers(QIOChannel *ioc) +{ +IOHandler *rd_handler = NULL, *wr_handler = NULL; + +if (ioc->read_coroutine) { + rd_handler = qio_channel_restart_read; +} +if (ioc->write_coroutine) { + rd_handler = qio_channel_restart_write; +} + +qio_channel_set_fd_handler(ioc, + ioc->ctx ? ioc->ctx : iohandler_get_aio_context(), + rd_handler, wr_handler, ioc); +} void qio_channel_set_aio_context(QIOChannel *ioc, AioContext *ctx) @@ -272,16 +293,15 @@ void qio_channel_set_aio_context(QIOChannel *ioc, void coroutine_fn qio_channel_yield(QIOChannel *ioc, GIOCondition condition) { -QIOChannelYieldData data; - assert(qemu_in_coroutine()); -data.ioc = ioc; -data.co = qemu_coroutine_self(); -qio_channel_add_watch(ioc, - condition, - qio_channel_yield_enter, - &data, - NULL); +if (condition == G_IO_IN) { +ioc->read_coroutine
[Qemu-devel] [PATCH 1/3] io: add methods to set I/O handlers on AioContext
This is in preparation for making qio_channel_yield work on AioContexts other than the main one. Signed-off-by: Paolo Bonzini --- include/io/channel.h | 42 ++ io/channel-socket.c | 16 +++- io/channel-tls.c | 12 io/channel-watch.c | 6 ++ io/channel.c | 25 + 5 files changed, 96 insertions(+), 5 deletions(-) diff --git a/include/io/channel.h b/include/io/channel.h index 32a9470..248bc76 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -23,6 +23,7 @@ #include "qemu-common.h" #include "qom/object.h" +#include "block/aio.h" #define TYPE_QIO_CHANNEL "qio-channel" #define QIO_CHANNEL(obj)\ @@ -58,6 +59,8 @@ typedef gboolean (*QIOChannelFunc)(QIOChannel *ioc, GIOCondition condition, gpointer data); +typedef struct QIOChannelRestart QIOChannelRestart; + /** * QIOChannel: * @@ -80,6 +83,9 @@ struct QIOChannel { Object parent; unsigned int features; /* bitmask of QIOChannelFeatures */ char *name; +AioContext *ctx; +QIOChannelRestart *read_coroutine; +QIOChannelRestart *write_coroutine; #ifdef _WIN32 HANDLE event; /* For use with GSource on Win32 */ #endif @@ -132,6 +138,11 @@ struct QIOChannelClass { off_t offset, int whence, Error **errp); +void (*io_set_fd_handler)(QIOChannel *ioc, + AioContext *ctx, + IOHandler *io_read, + IOHandler *io_write, + void *opaque); }; /* General I/O handling functions */ @@ -497,6 +508,18 @@ guint qio_channel_add_watch(QIOChannel *ioc, /** + * qio_channel_set_aio_context: + * @ioc: the channel object + * @ctx: the #AioContext to set the handlers on + * + * Request that qio_channel_yield() sets I/O handlers on + * the given #AioContext. If @ctx is %NULL, qio_channel_yield() + * uses QEMU's main thread event loop. + */ +void qio_channel_set_aio_context(QIOChannel *ioc, + AioContext *ctx); + +/** * qio_channel_yield: * @ioc: the channel object * @condition: the I/O condition to wait for @@ -525,4 +548,23 @@ void qio_channel_yield(QIOChannel *ioc, void qio_channel_wait(QIOChannel *ioc, GIOCondition condition); +/** + * qio_channel_set_fd_handler: + * @ioc: the channel object + * @ctx: the AioContext to set the handlers on + * @io_read: the read handler + * @io_write: the write handler + * @opaque: the opaque value passed to the handler + * + * This is used internally by qio_channel_yield(). It can + * be used by channel implementations to forward the handlers + * to another channel (e.g. from #QIOChannelTLS to the + * underlying socket). + */ +void qio_channel_set_fd_handler(QIOChannel *ioc, +AioContext *ctx, +IOHandler *io_read, +IOHandler *io_write, +void *opaque); + #endif /* QIO_CHANNEL_H */ diff --git a/io/channel-socket.c b/io/channel-socket.c index d7e03f6..4d5f180 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -661,11 +661,6 @@ qio_channel_socket_set_blocking(QIOChannel *ioc, qemu_set_block(sioc->fd); } else { qemu_set_nonblock(sioc->fd); -#ifdef WIN32 -WSAEventSelect(sioc->fd, ioc->event, - FD_READ | FD_ACCEPT | FD_CLOSE | - FD_CONNECT | FD_WRITE | FD_OOB); -#endif } return 0; } @@ -745,6 +740,16 @@ qio_channel_socket_shutdown(QIOChannel *ioc, return 0; } +static GSource *qio_channel_socket_set_fd_handler(QIOChannel *ioc, + AioContext *ctx, + IOHandler *io_read, + IOHandler *io_write, + void *opaque) +{ +QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); +aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, opaque); +} + static GSource *qio_channel_socket_create_watch(QIOChannel *ioc, GIOCondition condition) { @@ -767,6 +772,7 @@ static void qio_channel_socket_class_init(ObjectClass *klass, ioc_klass->io_set_cork = qio_channel_socket_set_cork; ioc_klass->io_set_delay = qio_channel_socket_set_delay; ioc_klass->io_create_watch = qio_channel_socket_create_watch; +ioc_klass->io_set_fd_handler = qio_channel_socket_set_fd_handler; } static const TypeInfo qio_channel_socket_info = { diff --git a/io/channel-tls.c b/io/channel-tls.c index d24dc8c..bd2239c 100644 --- a/io/channel-tls.c +++ b/io/channel-tls.c @@ -349,6 +349,17 @@ static in
Re: [Qemu-devel] [PATCH v3 0/6] trace: [tcg] Optimize per-vCPU tracing states with separate TB caches
Richard Henderson writes: > On 12/22/2016 10:35 AM, Lluís Vilanova wrote: >> To handle both issues, this series replicates the shared physical TB cache, >> creating a separate physical TB cache for every combination of event states >> (those with the 'vcpu' and 'tcg' properties). Then, all vCPUs tracing the >> same >> events will use the same physical TB cache. > Why do we need to "split the physical TB cache" as opposed to simply including > the trace state into the TB hash function? Mmmm, that's an interesting alternative I did not consider. Are you aiming at minimizing the changes, or do you also think it would be more efficient? The dynamic tracing state would then be an arbitrarily long bitmap (defined by the number of events with the 'vcpu' property), so I'm not sure how to fit it into the hashing function with minimal collisions (the bitmap is now limited to an unsigned long to use it as an index to the TB cache "matrix"). The other drawback I see is that then it would also take longer to compute the hashing function, instead of the simpler array indexing. As a benefit, workloads with a high frequency of TB-flushing operations might be a bit faster (there would be a single QHT). If someone can provide me the code for the modified hash lookup function to account for the trace dstate bitmap contents, I will integrate it and measure if there is any important change in performance. Cheers, Lluis
[Qemu-devel] [PATCH 09/21] backup: separate copy function
Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 103 ++--- 1 file changed, 61 insertions(+), 42 deletions(-) diff --git a/block/backup.c b/block/backup.c index 4ef8daf..2c8b7ba 100644 --- a/block/backup.c +++ b/block/backup.c @@ -95,6 +95,65 @@ static void cow_request_end(CowRequest *req) qemu_co_queue_restart_all(&req->wait_queue); } +static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, +int64_t cluster, +bool *error_is_read, +bool is_write_notifier, +void *bounce_buffer) +{ +BlockBackend *blk = job->common.blk; +int n; +struct iovec iov; +QEMUIOVector bounce_qiov; +int ret = 0; +int64_t sectors_per_cluster = cluster_size_sectors(job); + +trace_backup_do_cow_process(job, cluster); + +n = MIN(sectors_per_cluster, +job->common.len / BDRV_SECTOR_SIZE - +cluster * sectors_per_cluster); + +iov.iov_base = bounce_buffer; +iov.iov_len = n * BDRV_SECTOR_SIZE; +qemu_iovec_init_external(&bounce_qiov, &iov, 1); + +ret = blk_co_preadv(blk, cluster * job->cluster_size, +bounce_qiov.size, &bounce_qiov, +is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0); +if (ret < 0) { +trace_backup_do_cow_read_fail(job, cluster, ret); +if (error_is_read) { +*error_is_read = true; +} +return ret; +} + +if (buffer_is_zero(iov.iov_base, iov.iov_len)) { +ret = blk_co_pwrite_zeroes(job->target, cluster * job->cluster_size, + bounce_qiov.size, BDRV_REQ_MAY_UNMAP); +} else { +ret = blk_co_pwritev(job->target, cluster * job->cluster_size, + bounce_qiov.size, &bounce_qiov, + job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0); +} +if (ret < 0) { +trace_backup_do_cow_write_fail(job, cluster, ret); +if (error_is_read) { +*error_is_read = false; +} +return ret; +} + +/* Publish progress, guest I/O counts as progress too. Note that the + * offset field is an opaque progress value, it is not a disk offset. + */ +job->sectors_read += n; +job->common.offset += n * BDRV_SECTOR_SIZE; + +return 0; +} + static int coroutine_fn backup_do_cow(BackupBlockJob *job, int64_t sector_num, int nb_sectors, bool *error_is_read, @@ -102,13 +161,10 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job, { BlockBackend *blk = job->common.blk; CowRequest cow_request; -struct iovec iov; -QEMUIOVector bounce_qiov; void *bounce_buffer = NULL; int ret = 0; int64_t sectors_per_cluster = cluster_size_sectors(job); int64_t start, end; -int n; qemu_co_rwlock_rdlock(&job->flush_rwlock); @@ -127,53 +183,16 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job, } hbitmap_reset(job->copy_bitmap, start, 1); -trace_backup_do_cow_process(job, start); - -n = MIN(sectors_per_cluster, -job->common.len / BDRV_SECTOR_SIZE - -start * sectors_per_cluster); - if (!bounce_buffer) { bounce_buffer = blk_blockalign(blk, job->cluster_size); } -iov.iov_base = bounce_buffer; -iov.iov_len = n * BDRV_SECTOR_SIZE; -qemu_iovec_init_external(&bounce_qiov, &iov, 1); -ret = blk_co_preadv(blk, start * job->cluster_size, -bounce_qiov.size, &bounce_qiov, -is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0); +ret = backup_copy_cluster(job, start, error_is_read, is_write_notifier, + bounce_buffer); if (ret < 0) { -trace_backup_do_cow_read_fail(job, start, ret); -if (error_is_read) { -*error_is_read = true; -} -hbitmap_set(job->copy_bitmap, start, 1); -goto out; -} - -if (buffer_is_zero(iov.iov_base, iov.iov_len)) { -ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size, - bounce_qiov.size, BDRV_REQ_MAY_UNMAP); -} else { -ret = blk_co_pwritev(job->target, start * job->cluster_size, - bounce_qiov.size, &bounce_qiov, - job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0); -} -if (ret < 0) { -trace_backup_do_cow_write_fail(job, start, ret); -if (error_is_read) { -*error_is_read = false; -} hbitmap_set(job->copy_bitmap
[Qemu-devel] [Bug 1652373] [NEW] User-mode QEMU is not deterministic
Public bug reported: QEMU in user-mode (linux-user or bsd-user) has no way to get the equivalent of the "-icount" argument found in softmmu mode. It is true that some system calls in user-mode can prevent deterministic execution, but it would be very simple to patch time-related syscalls to return a number based on icount when in deterministic mode. Putting both changes together (icount + time-related syscalls) would cover the needs for deterministic execution of most benchmarks (i.e., those not interacting with the network or other programs in the system). ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1652373 Title: User-mode QEMU is not deterministic Status in QEMU: New Bug description: QEMU in user-mode (linux-user or bsd-user) has no way to get the equivalent of the "-icount" argument found in softmmu mode. It is true that some system calls in user-mode can prevent deterministic execution, but it would be very simple to patch time- related syscalls to return a number based on icount when in deterministic mode. Putting both changes together (icount + time-related syscalls) would cover the needs for deterministic execution of most benchmarks (i.e., those not interacting with the network or other programs in the system). To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1652373/+subscriptions
Re: [Qemu-devel] [PULL 24/25] target-i386: Fix eflags.TF/#DB handling of syscall/sysret insns
Paolo Bonzini writes: > From: Doug Evans > > The syscall and sysret instructions behave a bit differently: > TF is checked after the instruction completes. > This allows the o/s to disable #DB at a syscall by adding TF to FMASK. > And then when the sysret is executed the #DB is taken "as if" the > syscall insn just completed. > > Signed-off-by: Doug Evans > Message-Id: <94eb2c0bfa1c6a9fec0543057...@google.com> > Signed-off-by: Paolo Bonzini > --- > target/i386/bpt_helper.c | 7 +++ > target/i386/helper.h | 1 + > target/i386/translate.c | 29 - > 3 files changed, 32 insertions(+), 5 deletions(-) > > ... > diff --git a/target/i386/translate.c b/target/i386/translate.c > index 324103c..59e11fc 100644 > --- a/target/i386/translate.c > +++ b/target/i386/translate.c > @@ -6423,7 +6435,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, >tcg_const_i32(s->pc - s->cs_base)); > set_cc_op(s, CC_OP_EFLAGS); > } > -gen_eob(s); > +/* TF handling for the syscall insn is different. The TF bit is checked > + after the syscall insn completes. This allows #DB to not be > + generated after one has entered CPL0 if TF is set in FMASK. */ > +gen_eob_worker(s, false, true); > break; > case 0xe8: /* call im */ > { > @@ -7115,7 +7130,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, > if (s->lma) { > set_cc_op(s, CC_OP_EFLAGS); > } > -gen_eob(s); > +/* TF handling for the sysret insn is different. The TF bit is > + checked after the sysret insn completes. This allows #DB to be > + generated "as if" the syscall insn in userspace has just > + completed. */ > +gen_eob_worker(s, false, true); > } > break; > #endif Hi. Just a heads up that this patch got applied wrong (patch does that some times). The change to the "syscall" insn got applied to the "iret" instruction instead. Working on a fix.
[Qemu-devel] [PATCH 08/21] backup: skip unallocated clusters for full mode
In case of full backup we can skip unallocated clusters if the target disk is already zero-initialized. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 8 ++-- tests/qemu-iotests/055 | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/block/backup.c b/block/backup.c index 2afd1b6..4ef8daf 100644 --- a/block/backup.c +++ b/block/backup.c @@ -562,9 +562,13 @@ static void coroutine_fn backup_run(void *opaque) if (job->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { backup_incremental_init_copy_bitmap(job); } else { +/* top or full mode */ +bool is_top = job->sync_mode == MIRROR_SYNC_MODE_TOP; +BlockDriverState *base = +is_top ? backing_bs(blk_bs(job->common.blk)) : NULL; hbitmap_set(job->copy_bitmap, 0, end); -if (job->sync_mode == MIRROR_SYNC_MODE_TOP) { -backup_skip_loop(job, backing_bs(blk_bs(job->common.blk))); +if (is_top || bdrv_has_zero_init(blk_bs(job->target))) { +backup_skip_loop(job, base); } } ret = backup_loop(job); diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 index 1d3fd04..388b7b2 100755 --- a/tests/qemu-iotests/055 +++ b/tests/qemu-iotests/055 @@ -30,6 +30,7 @@ target_img = os.path.join(iotests.test_dir, 'target.img') blockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img') image_len = 64 * 1024 * 1024 # MB +pause_write = '3M' def setUpModule(): qemu_img('create', '-f', iotests.imgfmt, test_img, str(image_len)) @@ -39,6 +40,7 @@ def setUpModule(): qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img) +qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 40M ' + pause_write, test_img) def tearDownModule(): os.remove(test_img) -- 1.8.3.1
[Qemu-devel] [PATCH 00/21] new backup architecture
Hi all. This is a new architecture for backup. It solves some current problems: 1. intersecting requests: for now at request start we wait for all intersecting requests, which means that a. we may wait even for unrelated to our request clusters b. not full async: if we are going to copy clusters 1,2,3,4, when 2 and 4 are in flight, why should we wait for 2 and 4 to be fully copied? Why not to start 1 and 3 in parallel with 2 and 4? 2. notifier request is internally synchronous: if notifier starts copying clusters 1,2,3,4, they will be copied one by one in synchronous loop. 3. notifier wait full copying of corresponding clusters (when actually it may wait only for _read_ operations to be finished) In short, what is done: 1. full async scheme 4. no intersecting requests 3. notifiers can wait only for read, not for write 4. notifiers wait only for corresponding clusters 5. time limit for notifiers 5. skip unallocated clusters for full mode 6. use HBitmap as main backup bitmap and just init it from dirty bitmap for incremental case 7. retrying: do not reread on write fail # Intro Instead of sync-copying + async-notifiers as in old backup, or aio requests like in mirror, this scheme just start 24 workers - separate coroutines, each of them copying clusters synchronously. Copying is only done by one cluster, there are no large requests. The only difference for clusters, awaited by write notifiers, is larger priority. So, notifiers do not start io requests, they just mark some clusters as awaited and yield. Then, when some worker completes read of last cluster, awaited by this notifier it will enter it. # Some data structures Instead of done_bitmap - copy_bitmap, like in mirror. HBitmap copy_bitmap Exactly, what should be copied: 0 - may mean one of three things: - this cluster should not be copied at all - this cluster is in flight - this cluster is already copied 1 - means that cluster should be copied, but not touched yet (no async io exists for it) New bitmap: notif_wait_bitmap - not HBitmap, just Bitmap. Exactly, in flight clusters, waiting for read operation: 0 - may mean one of three things: - this cluster should not be copied at all - this cluster is in flight and it is _already_ read to memory - this cluster is already copied 1 - means that cluster is in flight, but read operation have not finished yet The only exception is none-mode: in this case 1 means in flight: in io read or write. This is needed for image fleecing. Cluster states (copy_bitmap, notif_wait_bitmap) 0, 0 - Ignored (should not be copied at all) or In flight (read done) or Copied 0, 1 - In flight, read operation not finished (or write op. - for none-mode) 1, 0 - Should be copied, but not touched yet 1, 1 - Impossible state NotifierRequest - request from notifier, it changes sequence of cluster copying by workers. NotifierRequest { int64_t start; int64_t end; int nb_wait; // nb clusters (in specified range) that should be copied but not already read, i.e. clusters awaited by this notifier Coroutine *notif; // corresponding notifier coroutine } notifier_reqs - list of notifier requests # More info At backup start copy_bitmap is inited to sync_bitmap for incremental backup. For top/full backup it is inited to all ones, but in parallel with workers main coroutine skips not allocated clusters. Worker coroutines are copying clusters, preferable awaited by notifiers (for which NotifierRequest exists in the list). Function get_work helps them. Workers will copy clusters, awaited by notifiers even if block-job is paused - it is the same behaviour as in old architecture. Old backup fails guest-write if notifier fails to backup corresponding clusters. In the new scheme there is a little difference: notifier just wait for 5s and if backup can't copy all corresponding clusters in this time - guest-write fails. Error scenarios was considered on list, the final solution was to provide user a possibility to chose what should be failed: backup or guest-write. I'll add this later. Worker can exit (no more clusters to copy or fatal error) or pause (error or user pause or throttling). When last worker goes to pause it rings up main block-job coroutine, which will handle user pause or errors. We need to handle errors in main coroutine because of nature of block_job_error_action, which may yield. There also is a bonus: new io-retrying scheme: if there is an error on read or write, worker just yield in the retrying loop and if it will be resumed (with job->error_exit = false) it will continue from the same place, so if we have failed write after successful read we will not reread. Vladimir Sementsov-Ogievskiy (21): backup: move from done_bitmap to copy_bitmap backup: init copy_bitmap from sync_bitmap for incremental backup: improve non-dirty bits progress processing backup: use copy_bitmap in i
[Qemu-devel] [PATCH 13/21] coroutine: add qemu_coroutine_add_next
Simple add coroutine to self->co_queue_wakeup. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/qemu/coroutine.h | 2 ++ util/qemu-coroutine.c| 7 +++ 2 files changed, 9 insertions(+) diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index e6a60d5..6e87c87 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -226,4 +226,6 @@ void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type, */ void coroutine_fn yield_until_fd_readable(int fd); +void qemu_coroutine_add_next(Coroutine *next); + #endif /* QEMU_COROUTINE_H */ diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c index 737bffa..300b96d 100644 --- a/util/qemu-coroutine.c +++ b/util/qemu-coroutine.c @@ -151,3 +151,10 @@ bool qemu_coroutine_entered(Coroutine *co) { return co->caller; } + +void qemu_coroutine_add_next(Coroutine *next) +{ +Coroutine *self = qemu_coroutine_self(); +QSIMPLEQ_INSERT_TAIL(&self->co_queue_wakeup, next, co_queue_next); +trace_qemu_co_queue_next(next); +} -- 1.8.3.1
Re: [Qemu-devel] [PATCH v3 0/6] trace: [tcg] Optimize per-vCPU tracing states with separate TB caches
On 12/23/2016 10:51 AM, Lluís Vilanova wrote: >> On 12/22/2016 10:35 AM, Lluís Vilanova wrote: >>> To handle both issues, this series replicates the shared physical TB cache, >>> creating a separate physical TB cache for every combination of event states >>> (those with the 'vcpu' and 'tcg' properties). Then, all vCPUs tracing the >>> same >>> events will use the same physical TB cache. > >> Why do we need to "split the physical TB cache" as opposed to simply >> including >> the trace state into the TB hash function? > > Mmmm, that's an interesting alternative I did not consider. Are you aiming at > minimizing the changes, or do you also think it would be more efficient? I suspect that it will be more efficient. > The dynamic tracing state would then be an arbitrarily long bitmap (defined by > the number of events with the 'vcpu' property), so I'm not sure how to fit it > into the hashing function with minimal collisions (the bitmap is now limited > to > an unsigned long to use it as an index to the TB cache "matrix"). You could consider that index a unique identifier for the tracing state, and then only compare and hash that integer. > The other drawback I see is that then it would also take longer to compute the > hashing function, instead of the simpler array indexing. As a benefit, > workloads > with a high frequency of TB-flushing operations might be a bit faster (there > would be a single QHT). I don't see adding one more integer to the hashing function to be significant at all. Certainly not the 15% that you describe in your cover letter. > If someone can provide me the code for the modified hash lookup function to > account for the trace dstate bitmap contents, I will integrate it and measure > if > there is any important change in performance. Something like the following should do it. There are two /* cpu->??? */ markers that would need to be filled in. If you can reduce the tracing identifier to 8 bits, that would be excellent. I've been wanting to make some other changes to TB hashing, and that would fit in well with a second "flags" value. r~ diff --git a/cpu-exec.c b/cpu-exec.c index 4188fed..3b54317 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -261,6 +261,7 @@ struct tb_desc { CPUArchState *env; tb_page_addr_t phys_page1; uint32_t flags; +uint32_t traceid; }; static bool tb_cmp(const void *p, const void *d) @@ -272,6 +273,7 @@ static bool tb_cmp(const void *p, const void *d) tb->page_addr[0] == desc->phys_page1 && tb->cs_base == desc->cs_base && tb->flags == desc->flags && +tb->traceid == desc->traceid && !atomic_read(&tb->invalid)) { /* check next page if needed */ if (tb->page_addr[1] == -1) { @@ -293,7 +295,8 @@ static bool tb_cmp(const void *p, const void *d) static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, target_ulong cs_base, - uint32_t flags) + uint32_t flags, + uint32_t traceid) { tb_page_addr_t phys_pc; struct tb_desc desc; @@ -302,10 +305,11 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, desc.env = (CPUArchState *)cpu->env_ptr; desc.cs_base = cs_base; desc.flags = flags; +desc.traceid = traceid; desc.pc = pc; phys_pc = get_page_addr_code(desc.env, pc); desc.phys_page1 = phys_pc & TARGET_PAGE_MASK; -h = tb_hash_func(phys_pc, pc, flags); +h = tb_hash_func(phys_pc, pc, flags, traceid); return qht_lookup(&tcg_ctx.tb_ctx.htable, tb_cmp, &desc, h); } @@ -317,6 +321,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu, TranslationBlock *tb; target_ulong cs_base, pc; uint32_t flags; +uint32_t traceid = 0 /* cpu->??? */; bool have_tb_lock = false; /* we record a subset of the CPU state. It will @@ -325,8 +330,8 @@ static inline TranslationBlock *tb_find(CPUState *cpu, cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); tb = atomic_rcu_read(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]); if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || - tb->flags != flags)) { -tb = tb_htable_lookup(cpu, pc, cs_base, flags); + tb->flags != flags || tb->traceid != traceid)) { +tb = tb_htable_lookup(cpu, pc, cs_base, flags, traceid); if (!tb) { /* mmap_lock is needed by tb_gen_code, and mmap_lock must be @@ -340,7 +345,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu, /* There's a chance that our desired tb has been translated while * taking the locks so we check again inside the lock. */ -tb = tb_htable_lookup(cpu, pc, cs_base, flags); +tb = tb_htable_lookup(cpu, pc, cs_base, flags, traceid);
Re: [Qemu-devel] [PATCH] ps2: Fix lost scancodes by recent changes
Le 23/12/2016 à 14:00, OGAWA Hirofumi a écrit : With "ps2: use QEMU qcodes instead of scancodes", key handling was changed to qcode base. But all scancodes are not converted to new one. This adds some missing qcodes what I found in using. Signed-off-by: OGAWA Hirofumi --- hw/input/ps2.c|3 +++ qapi-schema.json |3 ++- ui/input-keymap.c |3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff -puN hw/input/ps2.c~fix-ps2-scancode hw/input/ps2.c --- qemu/hw/input/ps2.c~fix-ps2-scancode2016-12-23 21:14:59.837729450 +0900 +++ qemu-hirofumi/hw/input/ps2.c2016-12-23 21:14:59.840729469 +0900 @@ -394,6 +394,9 @@ static const uint16_t qcode_to_keycode_s [Q_KEY_CODE_LESS] = 0x61, [Q_KEY_CODE_SYSRQ] = 0x7f, [Q_KEY_CODE_RO] = 0x51, +[Q_KEY_CODE_HIRAGANA] = 0x13, +[Q_KEY_CODE_HENKAN] = 0x64, +[Q_KEY_CODE_YEN] = 0x6a, [Q_KEY_CODE_KP_COMMA] = 0x6d, }; diff -puN qapi-schema.json~fix-ps2-scancode qapi-schema.json --- qemu/qapi-schema.json~fix-ps2-scancode 2016-12-23 21:14:59.838729456 +0900 +++ qemu-hirofumi/qapi-schema.json 2016-12-23 21:14:59.840729469 +0900 @@ -3642,7 +3642,8 @@ 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end', 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', -'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', 'ro', +'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', +'ro', 'hiragana', 'henkan', 'yen', 'kp_comma', 'kp_equals', 'power' ] } ## diff -puN ui/input-keymap.c~fix-ps2-scancode ui/input-keymap.c --- qemu/ui/input-keymap.c~fix-ps2-scancode 2016-12-23 21:14:59.839729463 +0900 +++ qemu-hirofumi/ui/input-keymap.c 2016-12-23 21:14:59.840729469 +0900 @@ -131,6 +131,9 @@ static const int qcode_to_number[] = { [Q_KEY_CODE_DELETE] = 0xd3, [Q_KEY_CODE_RO] = 0x73, +[Q_KEY_CODE_HIRAGANA] = 0x70, +[Q_KEY_CODE_HENKAN] = 0x79, +[Q_KEY_CODE_YEN] = 0x7d, [Q_KEY_CODE_KP_COMMA] = 0x7e, [Q_KEY_CODE__MAX] = 0, Can you also add the keycodes for scancode set 1: +[Q_KEY_CODE_HIRAGANA] = 0x70, +[Q_KEY_CODE_HENKAN] = 0x79, +[Q_KEY_CODE_YEN] = 0x7d, and scancode set 3: +[Q_KEY_CODE_HIRAGANA] = 0x87, +[Q_KEY_CODE_HENKAN] = 0x86, +[Q_KEY_CODE_YEN] = 0x51, Hervé
Re: [Qemu-devel] [PATCH] ps2: Fix lost scancodes by recent changes
On 12/23/2016 07:00 AM, OGAWA Hirofumi wrote: > > With "ps2: use QEMU qcodes instead of scancodes", key handling was > changed to qcode base. But all scancodes are not converted to new one. > > This adds some missing qcodes what I found in using. > > Signed-off-by: OGAWA Hirofumi > --- > > +++ qemu-hirofumi/qapi-schema.json2016-12-23 21:14:59.840729469 +0900 > @@ -3642,7 +3642,8 @@ > 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', > 'end', > 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', > 'again', > 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', > -'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', 'ro', > +'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', > +'ro', 'hiragana', 'henkan', 'yen', > 'kp_comma', 'kp_equals', 'power' ] } Missing documentation (including a 'since 2.9' designation) for the new enum members. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: [Qemu-devel] [PATCH] ps2: Fix lost scancodes by recent changes
Hi, Hervé Poussineau writes: >> [Q_KEY_CODE_RO] = 0x73, >> +[Q_KEY_CODE_HIRAGANA] = 0x70, >> +[Q_KEY_CODE_HENKAN] = 0x79, >> +[Q_KEY_CODE_YEN] = 0x7d, >> [Q_KEY_CODE_KP_COMMA] = 0x7e, >> >> [Q_KEY_CODE__MAX] = 0, > > Can you also add the keycodes for scancode set 1: > +[Q_KEY_CODE_HIRAGANA] = 0x70, > +[Q_KEY_CODE_HENKAN] = 0x79, > +[Q_KEY_CODE_YEN] = 0x7d, Current linux can't use set1, so untested. > and scancode set 3: > +[Q_KEY_CODE_HIRAGANA] = 0x87, > +[Q_KEY_CODE_HENKAN] = 0x86, > +[Q_KEY_CODE_YEN] = 0x51, Boot with "i8042.direct=1", then set set3. # echo 3 > /sys/devices/platform/i8042/serio0/set # cat /sys/devices/platform/i8042/serio0/set 3 HENKAN, HIRAGANA seems to be working, but YEN is not working. I'm not sure if it is your patch, testing, or kernel problem. Can you point what is problem? # lsinput [...] /dev/input/event4 bustype : BUS_I8042 vendor : 0x1 product : 0x3 version : 43907 name: "AT Raw Set 3 keyboard" phys: "isa0060/serio0/input0" bits ev : EV_SYN EV_KEY EV_MSC EV_LED EV_REP # input-event /dev/input/event4 bustype : BUS_I8042 vendor : 0x1 product : 0x3 version : 43907 name: "AT Raw Set 3 keyboard" phys: "isa0060/serio0/input0" bits ev : EV_SYN EV_KEY EV_MSC EV_LED EV_REP waiting for events [... on qemu monitor "sendkey henkan" ...] 06:49:58.061932: EV_KEY KEY_HENKAN (0x5c) pressed 06:49:58.061932: EV_SYN code=0 value=0 06:49:58.149812: EV_MSC MSC_SCAN 134 06:49:58.149812: EV_KEY KEY_HENKAN (0x5c) released 06:49:58.149812: EV_SYN code=0 value=0 06:49:58.333876: EV_MSC MSC_SCAN 135 [... on qemu monitor "sendkey hiragana" ...] 06:49:58.333876: EV_KEY KEY_KATAKANAHIRAGANA (0x5d) pressed 06:49:58.333876: EV_SYN code=0 value=0 06:49:58.421889: EV_MSC MSC_SCAN 135 06:49:58.421889: EV_KEY KEY_KATAKANAHIRAGANA (0x5d) released 06:49:58.421889: EV_SYN code=0 value=0 06:49:58.893893: EV_MSC MSC_SCAN 81 [... on qemu monitor "sendkey yen" ...] 06:49:58.893893: EV_KEY KEY_VOLUMEDOWN (0x72) pressed 06:49:58.893893: EV_SYN code=0 value=0 06:49:58.973841: EV_MSC MSC_SCAN 81 06:49:58.973841: EV_KEY KEY_VOLUMEDOWN (0x72) released 06:49:58.973841: EV_SYN code=0 value=0 timeout, quitting -- OGAWA Hirofumi
Re: [Qemu-devel] [libvirt] Cannot add iothreads label in libvirt xml configuration file
On Thu, Dec 22, 2016 at 5:01 PM, John Ferlan wrote: > > > On 12/21/2016 12:11 PM, Weiwei Jia wrote: >> Hi, >> >> I cannot add iothreads >> (https://libvirt.org/formatdomain.html#elementsIOThreadsAllocation) in >> the libvirt xml configuration file. Once I add >> "4" and other related config for IOthreads into >> the libvirt xml configuration file with virsh command and save it, >> these iothreads related configuration will disappear after I open >> libvirt xml configuration file again for double-check. >> >> The current libvirt xml configuration file is like following. >> > > If I try to just cut-n-paste the following xml into a buffer, then run > virsh define kvm1.xml, I get: > > error: Failed to define domain from kvm1.xml > error: Cannot check QEMU binary /usr/bin/kvm-spice: No such file or > directory > > In order to support iothreads, it requires an "-object iothread"... The > "shortest" command line using qemu-kvm would be "qemu-kvm -object > iothread,id=xxx1", so you could try the same with that > /usr/bin/kvm-spice image and see what you get. > > You could try to figure out from the > /var/cach/libvirt/qemu/capabilities/*.xml files whether or not the > "iothread" object exists... I would think though that the reason why > this is failing for you is that the kvm-spice emulator doesn't have the > required capability (I forget if there's a magic incantation to ask the > emulator image what it supports, especially for objects). Thanks for your suggestions. I have tried your way and the results tell me there are some problems with my libvirt xml configuration file. I think I need to fix it with correct libvirt xml configuration file. Thanks, Weiwei Jia
Re: [Qemu-devel] [PATCH] ps2: Fix lost scancodes by recent changes
Eric Blake writes: > On 12/23/2016 07:00 AM, OGAWA Hirofumi wrote: >> >> With "ps2: use QEMU qcodes instead of scancodes", key handling was >> changed to qcode base. But all scancodes are not converted to new one. >> >> This adds some missing qcodes what I found in using. >> >> Signed-off-by: OGAWA Hirofumi >> --- >> > >> +++ qemu-hirofumi/qapi-schema.json 2016-12-23 21:14:59.840729469 +0900 >> @@ -3642,7 +3642,8 @@ >> 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', >> 'end', >> 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', >> 'again', >> 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', >> 'cut', >> -'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', 'ro', >> +'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', >> +'ro', 'hiragana', 'henkan', 'yen', >> 'kp_comma', 'kp_equals', 'power' ] } > > Missing documentation (including a 'since 2.9' designation) for the new > enum members. Thanks for pointing out. -- OGAWA Hirofumi
[Qemu-devel] [PATCH v2] ps2: Fix lost scancodes by recent changes
With "ps2: use QEMU qcodes instead of scancodes", key handling was changed to qcode base. But all scancodes are not converted to new one. This adds some missing qcodes/scancodes what I found in using. [set1 and set2 are still missing, but I'm not sure what is right values yet.] Signed-off-by: OGAWA Hirofumi --- hw/input/ps2.c|3 +++ qapi-schema.json |6 +- ui/input-keymap.c |3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff -puN hw/input/ps2.c~fix-ps2-scancode hw/input/ps2.c --- qemu/hw/input/ps2.c~fix-ps2-scancode2016-12-23 23:51:44.324955949 +0900 +++ qemu-hirofumi/hw/input/ps2.c2016-12-24 08:30:12.426540795 +0900 @@ -394,6 +394,9 @@ static const uint16_t qcode_to_keycode_s [Q_KEY_CODE_LESS] = 0x61, [Q_KEY_CODE_SYSRQ] = 0x7f, [Q_KEY_CODE_RO] = 0x51, +[Q_KEY_CODE_HIRAGANA] = 0x13, +[Q_KEY_CODE_HENKAN] = 0x64, +[Q_KEY_CODE_YEN] = 0x6a, [Q_KEY_CODE_KP_COMMA] = 0x6d, }; diff -puN qapi-schema.json~fix-ps2-scancode qapi-schema.json --- qemu/qapi-schema.json~fix-ps2-scancode 2016-12-23 23:51:44.324955949 +0900 +++ qemu-hirofumi/qapi-schema.json 2016-12-24 08:32:46.658549598 +0900 @@ -3618,6 +3618,9 @@ # @kp_comma: since 2.4 # @kp_equals: since 2.6 # @power: since 2.6 +# @hiragana: since 2.9 +# @henkan: since 2.9 +# @yen: since 2.9 # # An enumeration of key name. # @@ -3642,7 +3645,8 @@ 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end', 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', -'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', 'ro', +'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', +'ro', 'hiragana', 'henkan', 'yen', 'kp_comma', 'kp_equals', 'power' ] } ## diff -puN ui/input-keymap.c~fix-ps2-scancode ui/input-keymap.c --- qemu/ui/input-keymap.c~fix-ps2-scancode 2016-12-23 23:51:44.325955954 +0900 +++ qemu-hirofumi/ui/input-keymap.c 2016-12-23 23:51:44.327955966 +0900 @@ -131,6 +131,9 @@ static const int qcode_to_number[] = { [Q_KEY_CODE_DELETE] = 0xd3, [Q_KEY_CODE_RO] = 0x73, +[Q_KEY_CODE_HIRAGANA] = 0x70, +[Q_KEY_CODE_HENKAN] = 0x79, +[Q_KEY_CODE_YEN] = 0x7d, [Q_KEY_CODE_KP_COMMA] = 0x7e, [Q_KEY_CODE__MAX] = 0, _ -- OGAWA Hirofumi
[Qemu-devel] [PATCH 11/21] backup: move r/w error handling code to r/w functions
It simplifies code: we do not need error_is_read parameter and retrying in backup_loop. Also, retrying for read and write are separate, so we will not reread if write failed after successfull read. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/backup.c | 141 ++--- 1 file changed, 74 insertions(+), 67 deletions(-) diff --git a/block/backup.c b/block/backup.c index 5c31607..442e6da 100644 --- a/block/backup.c +++ b/block/backup.c @@ -95,18 +95,65 @@ static void cow_request_end(CowRequest *req) qemu_co_queue_restart_all(&req->wait_queue); } +static BlockErrorAction backup_error_action(BackupBlockJob *job, +bool read, int error) +{ +if (read) { +return block_job_error_action(&job->common, job->on_source_error, + true, error); +} else { +return block_job_error_action(&job->common, job->on_target_error, + false, error); +} +} + +static bool coroutine_fn yield_and_check(BackupBlockJob *job) +{ +if (block_job_is_cancelled(&job->common)) { +return true; +} + +/* we need to yield so that bdrv_drain_all() returns. + * (without, VM does not reboot) + */ +if (job->common.speed) { +uint64_t delay_ns = ratelimit_calculate_delay(&job->limit, + job->sectors_read); +job->sectors_read = 0; +block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, delay_ns); +} else { +block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, 0); +} + +if (block_job_is_cancelled(&job->common)) { +return true; +} + +return false; +} + static int coroutine_fn backup_do_read(BackupBlockJob *job, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, bool is_write_notifier) { -int ret = blk_co_preadv(job->common.blk, offset, bytes, qiov, -is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0); +int ret; +BdrvRequestFlags flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0; + +retry: +ret = blk_co_preadv(job->common.blk, offset, bytes, qiov, flags); if (ret < 0) { trace_backup_do_read_fail(job, offset, bytes, ret); + +BlockErrorAction action = backup_error_action(job, true, -ret); +if (action != BLOCK_ERROR_ACTION_REPORT && !yield_and_check(job)) { +goto retry; +} + +return ret; } -return ret; +return 0; } static int coroutine_fn backup_do_write(BackupBlockJob *job, @@ -114,9 +161,13 @@ static int coroutine_fn backup_do_write(BackupBlockJob *job, QEMUIOVector *qiov) { int ret; +bool zeroes; + assert(qiov->niov == 1); +zeroes = buffer_is_zero(qiov->iov->iov_base, qiov->iov->iov_len); -if (buffer_is_zero(qiov->iov->iov_base, qiov->iov->iov_len)) { +retry: +if (zeroes) { ret = blk_co_pwrite_zeroes(job->target, offset, bytes, BDRV_REQ_MAY_UNMAP); } else { @@ -125,14 +176,20 @@ static int coroutine_fn backup_do_write(BackupBlockJob *job, } if (ret < 0) { trace_backup_do_write_fail(job, offset, bytes, ret); + +BlockErrorAction action = backup_error_action(job, false, -ret); +if (action != BLOCK_ERROR_ACTION_REPORT && !yield_and_check(job)) { +goto retry; +} + +return ret; } -return ret; +return 0; } static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, int64_t cluster, -bool *error_is_read, bool is_write_notifier, void *bounce_buffer) { @@ -156,17 +213,11 @@ static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, ret = backup_do_read(job, offset, bounce_qiov.size, &bounce_qiov, is_write_notifier); if (ret < 0) { -if (error_is_read) { -*error_is_read = true; -} return ret; } ret = backup_do_write(job, offset, bounce_qiov.size, &bounce_qiov); if (ret < 0) { -if (error_is_read) { -*error_is_read = false; -} return ret; } @@ -181,7 +232,6 @@ static int coroutine_fn backup_copy_cluster(BackupBlockJob *job, static int coroutine_fn backup_do_cow(BackupBlockJob *job, int64_t sector_num, int nb_sectors, - bool *error_is_read, bool is_write_notifier) { BlockBackend *blk = job->common.blk; @@ -212,8 +262,7 @@ static int corou
[Qemu-devel] [PATCH] The QEMU crashes since invoking qemu_thread_set_name(), the backtrace is:
From: Caoxinhua (gdb) bt #0 0x7f9a68b095d7 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x7f9a68b0acc8 in __GI_abort () at abort.c:90 #2 0x7f9a69cda389 in PAT_abort () from /usr/lib64/libuvpuserhotfix.so #3 0x7f9a69cdda0d in patchIllInsHandler () from /usr/lib64/libuvpuserhotfix.so #4 #5 pthread_setname_np (th=140298470549248, name=name@entry=0x8cc74a "io-task-worker") at ../nptl/sysdeps/unix/sysv/linux/pthread_setname.c:49 #6 0x007f5f20 in qemu_thread_set_name (thread=thread@entry=0x7ffd2ac09680, name=name@entry=0x8cc74a "io-task-worker") at util/qemu_thread_posix.c:459 #7 0x007f679e in qemu_thread_create (thread=thread@entry=0x7ffd2ac09680, name=name@entry=0x8cc74a "io-task-worker",start_routine=start_routine@entry=0x7c1300 , arg=arg@entry=0x7f99b8001720, mode=mode@entry=1) at util/qemu_thread_posix.c:498 #8 0x007c15b6 in qio_task_run_in_thread (task=task@entry=0x7f99b80033d0, worker=worker@entry=0x7bd920 , opaque=0x7f99b8003370, destroy=0x7c6220 ) at io/task.c:133 #9 0x007bda04 in qio_channel_socket_connect_async (ioc=0x7f99b80014c0, addr=0x37235d0, callback=callback@entry=0x54ad00 , opaque=opaque@entry=0x38118b0, destroy=destroy@entry=0x0) at io/channel_socket.c:191 #10 0x005487f6 in socket_reconnect_timeout (opaque=0x38118b0) at qemu_char.c:4402 #11 0x7f9a6a1533b3 in g_timeout_dispatch () from /usr/lib64/libglib-2.0.so.0 #12 0x7f9a6a15299a in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0 #13 0x00747386 in glib_pollfds_poll () at main_loop.c:227 #14 0x00747424 in os_host_main_loop_wait (timeout=40400) at main_loop.c:272 #15 0x00747575 in main_loop_wait (nonblocking=nonblocking@entry=0) at main_loop.c:520 #16 0x00557d31 in main_loop () at vl.c:2170 #17 0x0041c8b7 in main (argc=, argv=, envp=) at vl.c:5083 That's because the corresponding child thread has been exited before the main thread calling qemu_thread_set_name(). Let's detach the thread after calling qemu_thread_set_name(). Signed-off-by: Caoxinhua --- util/qemu-thread-posix.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index d20cdde..d31793d 100644 --- a/util/qemu-thread-posix.c +++ b/util/qemu-thread-posix.c @@ -481,12 +481,6 @@ void qemu_thread_create(QemuThread *thread, const char *name, if (err) { error_exit(err, __func__); } -if (mode == QEMU_THREAD_DETACHED) { -err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); -if (err) { -error_exit(err, __func__); -} -} /* Leave signal handling to the iothread. */ sigfillset(&set); @@ -499,6 +493,12 @@ void qemu_thread_create(QemuThread *thread, const char *name, qemu_thread_set_name(thread, name); } +if (mode == QEMU_THREAD_DETACHED) { +err = pthread_detach(thread->thread); +if (err) { +error_exit(err, __func__); +} +} pthread_sigmask(SIG_SETMASK, &oldset, NULL); pthread_attr_destroy(&attr); -- 1.8.3.1
[Qemu-devel] [PATCH 0/2] tcg/s390 improvements
One bug fix, one cleanup. r~ The following changes since commit a470b33259bf82ef2336bfcd5d07640562d3f63b: Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging (2016-12-22 19:23:51 +) are available in the git repository at: git://github.com/rth7680/qemu.git tags/pull-tcg-20161223 for you to fetch changes up to e45d4ef6e345831c8d67a5bffe0d057efc20f4ff: tcg/s390: Remove 'R' constraint (2016-12-23 19:38:27 -0800) queued s390 host fixes Richard Henderson (2): tcg/s390: Fix setcond expansion tcg/s390: Remove 'R' constraint tcg/s390/tcg-target.inc.c | 75 +-- 1 file changed, 40 insertions(+), 35 deletions(-)
[Qemu-devel] [PATCH 2/2] tcg/s390: Remove 'R' constraint
Since R0 is reserved, we don't need a special case constraint. Signed-off-by: Richard Henderson --- tcg/s390/tcg-target.inc.c | 25 ++--- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/tcg/s390/tcg-target.inc.c b/tcg/s390/tcg-target.inc.c index 23115b5..8d5d2bd 100644 --- a/tcg/s390/tcg-target.inc.c +++ b/tcg/s390/tcg-target.inc.c @@ -378,11 +378,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ct->ct |= TCG_CT_REG; tcg_regset_set32(ct->u.regs, 0, 0x); break; -case 'R': /* not R0 */ -ct->ct |= TCG_CT_REG; -tcg_regset_set32(ct->u.regs, 0, 0x); -tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); -break; case 'L': /* qemu_ld/st constraint */ ct->ct |= TCG_CT_REG; tcg_regset_set32(ct->u.regs, 0, 0x); @@ -2226,12 +2221,12 @@ static const TCGTargetOpDef s390_op_defs[] = { { INDEX_op_neg_i32, { "r", "r" } }, -{ INDEX_op_shl_i32, { "r", "0", "Ri" } }, -{ INDEX_op_shr_i32, { "r", "0", "Ri" } }, -{ INDEX_op_sar_i32, { "r", "0", "Ri" } }, +{ INDEX_op_shl_i32, { "r", "0", "ri" } }, +{ INDEX_op_shr_i32, { "r", "0", "ri" } }, +{ INDEX_op_sar_i32, { "r", "0", "ri" } }, -{ INDEX_op_rotl_i32, { "r", "r", "Ri" } }, -{ INDEX_op_rotr_i32, { "r", "r", "Ri" } }, +{ INDEX_op_rotl_i32, { "r", "r", "ri" } }, +{ INDEX_op_rotr_i32, { "r", "r", "ri" } }, { INDEX_op_ext8s_i32, { "r", "r" } }, { INDEX_op_ext8u_i32, { "r", "r" } }, @@ -2281,12 +2276,12 @@ static const TCGTargetOpDef s390_op_defs[] = { { INDEX_op_neg_i64, { "r", "r" } }, -{ INDEX_op_shl_i64, { "r", "r", "Ri" } }, -{ INDEX_op_shr_i64, { "r", "r", "Ri" } }, -{ INDEX_op_sar_i64, { "r", "r", "Ri" } }, +{ INDEX_op_shl_i64, { "r", "r", "ri" } }, +{ INDEX_op_shr_i64, { "r", "r", "ri" } }, +{ INDEX_op_sar_i64, { "r", "r", "ri" } }, -{ INDEX_op_rotl_i64, { "r", "r", "Ri" } }, -{ INDEX_op_rotr_i64, { "r", "r", "Ri" } }, +{ INDEX_op_rotl_i64, { "r", "r", "ri" } }, +{ INDEX_op_rotr_i64, { "r", "r", "ri" } }, { INDEX_op_ext8s_i64, { "r", "r" } }, { INDEX_op_ext8u_i64, { "r", "r" } }, -- 2.9.3
[Qemu-devel] [PATCH 1/2] tcg/s390: Fix setcond expansion
We can't use LOAD AND TEST for unsigned data and then expect to extract the result with ADD LOGICAL WITH CARRY. Fall through to using COMPARE LOGICAL IMMEDIATE instead. Signed-off-by: Richard Henderson --- tcg/s390/tcg-target.inc.c | 50 --- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/tcg/s390/tcg-target.inc.c b/tcg/s390/tcg-target.inc.c index 253d4a0..23115b5 100644 --- a/tcg/s390/tcg-target.inc.c +++ b/tcg/s390/tcg-target.inc.c @@ -1093,33 +1093,43 @@ static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val) } static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, -TCGArg c2, int c2const) +TCGArg c2, bool c2const, bool need_carry) { bool is_unsigned = is_unsigned_cond(c); if (c2const) { if (c2 == 0) { +if (!(is_unsigned && need_carry)) { +if (type == TCG_TYPE_I32) { +tcg_out_insn(s, RR, LTR, r1, r1); +} else { +tcg_out_insn(s, RRE, LTGR, r1, r1); +} +return tcg_cond_to_ltr_cond[c]; +} +/* If we only got here because of load-and-test, + and we couldn't use that, then we need to load + the constant into a register. */ +if (!(facilities & FACILITY_EXT_IMM)) { +c2 = TCG_TMP0; +tcg_out_movi(s, type, c2, 0); +goto do_reg; +} +} +if (is_unsigned) { if (type == TCG_TYPE_I32) { -tcg_out_insn(s, RR, LTR, r1, r1); +tcg_out_insn(s, RIL, CLFI, r1, c2); } else { -tcg_out_insn(s, RRE, LTGR, r1, r1); +tcg_out_insn(s, RIL, CLGFI, r1, c2); } -return tcg_cond_to_ltr_cond[c]; } else { -if (is_unsigned) { -if (type == TCG_TYPE_I32) { -tcg_out_insn(s, RIL, CLFI, r1, c2); -} else { -tcg_out_insn(s, RIL, CLGFI, r1, c2); -} +if (type == TCG_TYPE_I32) { +tcg_out_insn(s, RIL, CFI, r1, c2); } else { -if (type == TCG_TYPE_I32) { -tcg_out_insn(s, RIL, CFI, r1, c2); -} else { -tcg_out_insn(s, RIL, CGFI, r1, c2); -} +tcg_out_insn(s, RIL, CGFI, r1, c2); } } } else { +do_reg: if (is_unsigned) { if (type == TCG_TYPE_I32) { tcg_out_insn(s, RR, CLR, r1, c2); @@ -1148,7 +1158,7 @@ static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond, do_greater: /* The result of a compare has CC=2 for GT and CC=3 unused. ADD LOGICAL WITH CARRY considers (CC & 2) the carry bit. */ -tgen_cmp(s, type, cond, c1, c2, c2const); +tgen_cmp(s, type, cond, c1, c2, c2const, true); tcg_out_movi(s, type, dest, 0); tcg_out_insn(s, RRE, ALCGR, dest, dest); return; @@ -1219,7 +1229,7 @@ static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond, break; } -cc = tgen_cmp(s, type, cond, c1, c2, c2const); +cc = tgen_cmp(s, type, cond, c1, c2, c2const, false); if (facilities & FACILITY_LOAD_ON_COND) { /* Emit: d = 0, t = 1, d = (cc ? t : d). */ tcg_out_movi(s, TCG_TYPE_I64, dest, 0); @@ -1238,11 +1248,11 @@ static void tgen_movcond(TCGContext *s, TCGType type, TCGCond c, TCGReg dest, { int cc; if (facilities & FACILITY_LOAD_ON_COND) { -cc = tgen_cmp(s, type, c, c1, c2, c2const); +cc = tgen_cmp(s, type, c, c1, c2, c2const, false); tcg_out_insn(s, RRF, LOCGR, dest, r3, cc); } else { c = tcg_invert_cond(c); -cc = tgen_cmp(s, type, c, c1, c2, c2const); +cc = tgen_cmp(s, type, c, c1, c2, c2const, false); /* Emit: if (cc) goto over; dest = r3; over: */ tcg_out_insn(s, RI, BRC, cc, (4 + 4) >> 1); @@ -1374,7 +1384,7 @@ static void tgen_brcond(TCGContext *s, TCGType type, TCGCond c, } } -cc = tgen_cmp(s, type, c, r1, c2, c2const); +cc = tgen_cmp(s, type, c, r1, c2, c2const, false); tgen_branch(s, cc, l); } -- 2.9.3
[Qemu-devel] [PATCH 0/2] tcg/s390 improvements
One bug fix, one cleanup. r~ The following changes since commit a470b33259bf82ef2336bfcd5d07640562d3f63b: Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging (2016-12-22 19:23:51 +) are available in the git repository at: git://github.com/rth7680/qemu.git tags/pull-tcg-20161223 for you to fetch changes up to e45d4ef6e345831c8d67a5bffe0d057efc20f4ff: tcg/s390: Remove 'R' constraint (2016-12-23 19:38:27 -0800) queued s390 host fixes Richard Henderson (2): tcg/s390: Fix setcond expansion tcg/s390: Remove 'R' constraint tcg/s390/tcg-target.inc.c | 75 +-- 1 file changed, 40 insertions(+), 35 deletions(-)
[Qemu-devel] [PATCH 02/65] tcg: Minor adjustments to deposit expanders
Assert that len is not 0. Since we have asserted that ofs + len <= N, a later check for len == N implies that ofs == 0. Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- tcg/tcg-op.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index c185b9c..b17f03f 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -533,10 +533,11 @@ void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, TCGv_i32 t1; tcg_debug_assert(ofs < 32); +tcg_debug_assert(len > 0); tcg_debug_assert(len <= 32); tcg_debug_assert(ofs + len <= 32); -if (ofs == 0 && len == 32) { +if (len == 32) { tcg_gen_mov_i32(ret, arg2); return; } @@ -1718,10 +1719,11 @@ void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, TCGv_i64 t1; tcg_debug_assert(ofs < 64); +tcg_debug_assert(len > 0); tcg_debug_assert(len <= 64); tcg_debug_assert(ofs + len <= 64); -if (ofs == 0 && len == 64) { +if (len == 64) { tcg_gen_mov_i64(ret, arg2); return; } -- 2.9.3
[Qemu-devel] [PATCH 01/65] tcg: Add field extraction primitives
Adds tcg_gen_extract_* and tcg_gen_sextract_* for extraction of fixed position bitfields, much like we already have for deposit. Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- tcg/README | 20 ++- tcg/aarch64/tcg-target.h | 4 + tcg/arm/tcg-target.h | 2 + tcg/i386/tcg-target.h| 4 + tcg/ia64/tcg-target.h| 4 + tcg/mips/tcg-target.h| 2 + tcg/optimize.c | 29 + tcg/ppc/tcg-target.h | 4 + tcg/s390/tcg-target.h| 4 + tcg/sparc/tcg-target.h | 4 + tcg/tcg-op.c | 323 +++ tcg/tcg-op.h | 12 ++ tcg/tcg-opc.h| 4 + tcg/tcg.h| 8 ++ tcg/tci/tcg-target.h | 4 + 15 files changed, 426 insertions(+), 2 deletions(-) diff --git a/tcg/README b/tcg/README index ae31388..065d9c2 100644 --- a/tcg/README +++ b/tcg/README @@ -314,11 +314,27 @@ The bitfield is described by POS/LEN, which are immediate values: LEN - the length of the bitfield POS - the position of the first bit, counting from the LSB -For example, pos=8, len=4 indicates a 4-bit field at bit 8. -This operation would be equivalent to +For example, "deposit_i32 dest, t1, t2, 8, 4" indicates a 4-bit field +at bit 8. This operation would be equivalent to dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00) +* extract_i32/i64 dest, t1, pos, len +* sextract_i32/i64 dest, t1, pos, len + +Extract a bitfield from T1, placing the result in DEST. +The bitfield is described by POS/LEN, which are immediate values, +as above for deposit. For extract_*, the result will be extended +to the left with zeros; for sextract_*, the result will be extended +to the left with copies of the bitfield sign bit at pos + len - 1. + +For example, "sextract_i32 dest, t1, 8, 4" indicates a 4-bit field +at bit 8. This operation would be equivalent to + + dest = (t1 << 20) >> 28 + +(using an arithmetic right shift). + * extrl_i64_i32 t0, t1 For 64-bit hosts only, extract the low 32-bits of input T1 and place it diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index a1d101f..410c31b 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -63,6 +63,8 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1 @@ -93,6 +95,8 @@ typedef enum { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 +#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1 diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index a0e1acf..8e724be 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -80,6 +80,8 @@ extern bool use_idiv_instructions; #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_mulu2_i321 #define TCG_TARGET_HAS_muls2_i321 diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 524cfc6..7625188 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -94,6 +94,8 @@ extern bool have_bmi1; #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1 @@ -124,6 +126,8 @@ extern bool have_bmi1; #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 +#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1 diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 6dddb7f..8856dc8 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -149,6 +149,10 @@ typedef enum { #define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_deposit_i64 1 +#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_sextract_i32 0 +#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_add2_i32 0 #define TCG_TARGET_HAS_add2_i64
[Qemu-devel] [PATCH v5 00/65] tcg 2.9 patch queue
This is a combination of two patch sets that have had previous revisions, as well as some new patches. I wanted to post this all together since Alex was having trouble with prerequisites. The full tree is at git://github.com/rth7680/qemu.git tcg-2.9 Changes sinve v4: * Feedback from Alex Bennee, including aarch64 guest fixes and a new test case. Changes since v3: * PPC host patches have been properly annotated for cpu revision, - cnttz[wd] are power9 inventions, - cntpop[wd] are power7 inventions. * X86 host checks the correct cpuid bit for lzcnt. * Generic TCG has significant changes to enable "interesting" combinations of constraints for X86 host bsr/bsf and to some extent lzcnt/tzcnt. * Opcode for ctpop. I had begun with only the helpers for ctpop, but added the opcode after I discovered that power7/8 could use that as a better alternative for implementing ctz. * Updates to the i386 and ppc disassemblers, to handle the new insns that we're emitting. r~ Alex Bennée (1): tests: New test-bitcnt Richard Henderson (64): tcg: Add field extraction primitives tcg: Minor adjustments to deposit expanders tcg: Add deposit_z expander tcg/aarch64: Implement field extraction opcodes tcg/arm: Move isa detection to tcg-target.h tcg/arm: Implement field extraction opcodes tcg/i386: Implement field extraction opcodes tcg/mips: Implement field extraction opcodes tcg/ppc: Implement field extraction opcodes tcg/s390: Expose host facilities to tcg-target.h tcg/s390: Implement field extraction opcodes tcg/s390: Support deposit into zero target-alpha: Use deposit and extract ops target-arm: Use new deposit and extract ops target-i386: Use new deposit and extract ops target-mips: Use the new extract op target-ppc: Use the new deposit and extract ops target-s390x: Use the new deposit and extract ops tcg/optimize: Fold movcond 0/1 into setcond tcg: Add markup for output requires new register tcg: Transition flat op_defs array to a target callback tcg: Pass the opcode width to target_parse_constraint tcg: Allow an operand to be matching or a constant tcg: Add clz and ctz opcodes disas/i386.c: Handle tzcnt disas/ppc: Handle popcnt and cnttz target-alpha: Use the ctz and clz opcodes target-cris: Use clz opcode target-microblaze: Use clz opcode target-mips: Use clz opcode target-openrisc: Use clz and ctz opcodes target-ppc: Use clz and ctz opcodes target-s390x: Use clz opcode target-tilegx: Use clz and ctz opcodes target-tricore: Use clz opcode target-unicore32: Use clz opcode target-xtensa: Use clz opcode target-arm: Use clz opcode target-i386: Use clz and ctz opcodes tcg/ppc: Handle ctz and clz opcodes tcg/aarch64: Handle ctz and clz opcodes tcg/arm: Handle ctz and clz opcodes tcg/mips: Handle clz opcode tcg/s390: Handle clz opcode tcg/i386: Fuly convert tcg_target_op_def tcg/i386: Hoist common arguments in tcg_out_op tcg/i386: Allow bmi2 shiftx to have non-matching operands tcg/i386: Handle ctz and clz opcodes tcg/i386: Rely on undefined/undocumented behaviour of BSF/BSR tcg: Add helpers for clrsb target-arm: Use clrsb helper target-tricore: Use clrsb helper target-xtensa: Use clrsb helper tcg: Add opcode for ctpop target-alpha: Use ctpop helper target-ppc: Use ctpop helper target-s390x: Avoid a loop for popcnt target-sparc: Use ctpop helper target-tilegx: Use ctpop helper target-i386: Use ctpop helper qemu/host-utils.h: Reduce the operation count in the fallback ctpop tcg: Use ctpop to generate ctz if needed tcg/ppc: Handle ctpop opcode tcg/i386: Handle ctpop opcode disas/i386.c | 12 +- disas/ppc.c | 10 + include/qemu/host-utils.h | 25 +- target/alpha/helper.h | 4 - target/alpha/int_helper.c | 15 - target/alpha/translate.c | 73 +++-- target/arm/helper-a64.c | 20 -- target/arm/helper-a64.h | 4 - target/arm/helper.c | 5 - target/arm/helper.h | 1 - target/arm/translate-a64.c| 97 +++--- target/arm/translate.c| 43 +-- target/cris/helper.h | 1 - target/cris/op_helper.c | 5 - target/cris/translate.c | 2 +- target/i386/cc_helper.c | 3 + target/i386/cpu.h | 1 + target/i386/helper.h | 2 - target/i386/int_helper.c | 11 - target/i386/ops_sse.h | 26 -- target/i386/ops_sse_header.h | 1 - target/i386/translate.c | 89 ++--- target/microblaze/helper.h| 1 - target/microblaze/op_helper.c | 5 - target/microblaze/translate.c | 2 +- target/mips/helper.h | 7 - target/mips/op_helper.c | 22 -- target/mips/translate.c | 35 +- target/openrisc/helper.h | 2 - target/openrisc/int_helper.c | 19 -- target/openrisc/translate.c | 6 +- target/ppc/helper.h | 7 +- target/ppc/int_helper.c
[Qemu-devel] [PATCH 03/65] tcg: Add deposit_z expander
While we don't require a new opcode, it is handy to have an expander that knows the first source is zero. Signed-off-by: Richard Henderson --- tcg/tcg-op.c | 143 +++ tcg/tcg-op.h | 6 +++ 2 files changed, 149 insertions(+) diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index b17f03f..1927e53 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -561,6 +561,64 @@ void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, tcg_temp_free_i32(t1); } +void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg, + unsigned int ofs, unsigned int len) +{ +tcg_debug_assert(ofs < 32); +tcg_debug_assert(len > 0); +tcg_debug_assert(len <= 32); +tcg_debug_assert(ofs + len <= 32); + +if (ofs + len == 32) { +tcg_gen_shli_i32(ret, arg, ofs); +} else if (ofs == 0) { +tcg_gen_andi_i32(ret, arg, (1u << len) - 1); +} else if (TCG_TARGET_HAS_deposit_i32 + && TCG_TARGET_deposit_i32_valid(ofs, len)) { +TCGv_i32 zero = tcg_const_i32(0); +tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len); +tcg_temp_free_i32(zero); +} else { +/* To help two-operand hosts we prefer to zero-extend first, + which allows ARG to stay live. */ +switch (len) { +case 16: +if (TCG_TARGET_HAS_ext16u_i32) { +tcg_gen_ext16u_i32(ret, arg); +tcg_gen_shli_i32(ret, ret, ofs); +return; +} +break; +case 8: +if (TCG_TARGET_HAS_ext8u_i32) { +tcg_gen_ext8u_i32(ret, arg); +tcg_gen_shli_i32(ret, ret, ofs); +return; +} +break; +} +/* Otherwise prefer zero-extension over AND for code size. */ +switch (ofs + len) { +case 16: +if (TCG_TARGET_HAS_ext16u_i32) { +tcg_gen_shli_i32(ret, arg, ofs); +tcg_gen_ext16u_i32(ret, ret); +return; +} +break; +case 8: +if (TCG_TARGET_HAS_ext8u_i32) { +tcg_gen_shli_i32(ret, arg, ofs); +tcg_gen_ext8u_i32(ret, ret); +return; +} +break; +} +tcg_gen_andi_i32(ret, arg, (1u << len) - 1); +tcg_gen_shli_i32(ret, ret, ofs); +} +} + void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, unsigned int ofs, unsigned int len) { @@ -1762,6 +1820,91 @@ void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, tcg_temp_free_i64(t1); } +void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg, + unsigned int ofs, unsigned int len) +{ +tcg_debug_assert(ofs < 64); +tcg_debug_assert(len > 0); +tcg_debug_assert(len <= 64); +tcg_debug_assert(ofs + len <= 64); + +if (ofs + len == 64) { +tcg_gen_shli_i64(ret, arg, ofs); +} else if (ofs == 0) { +tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); +} else if (TCG_TARGET_HAS_deposit_i64 + && TCG_TARGET_deposit_i64_valid(ofs, len)) { +TCGv_i64 zero = tcg_const_i64(0); +tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len); +tcg_temp_free_i64(zero); +} else { +if (TCG_TARGET_REG_BITS == 32) { +if (ofs >= 32) { +tcg_gen_deposit_z_i32(TCGV_HIGH(ret), TCGV_LOW(arg), + ofs - 32, len); +tcg_gen_movi_i32(TCGV_LOW(ret), 0); +return; +} +if (ofs + len <= 32) { +tcg_gen_deposit_z_i32(TCGV_LOW(ret), TCGV_LOW(arg), ofs, len); +tcg_gen_movi_i32(TCGV_HIGH(ret), 0); +return; +} +} +/* To help two-operand hosts we prefer to zero-extend first, + which allows ARG to stay live. */ +switch (len) { +case 32: +if (TCG_TARGET_HAS_ext32u_i64) { +tcg_gen_ext32u_i64(ret, arg); +tcg_gen_shli_i64(ret, ret, ofs); +return; +} +break; +case 16: +if (TCG_TARGET_HAS_ext16u_i64) { +tcg_gen_ext16u_i64(ret, arg); +tcg_gen_shli_i64(ret, ret, ofs); +return; +} +break; +case 8: +if (TCG_TARGET_HAS_ext8u_i64) { +tcg_gen_ext8u_i64(ret, arg); +tcg_gen_shli_i64(ret, ret, ofs); +return; +} +break; +} +/* Otherwise prefer zero-extension over AND for code size. */ +switch (ofs + len) { +case 32: +if (TCG_TARGET_HAS_ext32u_i64) { +tcg_gen_shli_i64(ret, arg, ofs); +tcg_gen_ext32u_i64(ret, ret); +retur
[Qemu-devel] [PATCH 12/65] tcg/s390: Support deposit into zero
Since we can no longer use matching constraints, this does mean we must handle that data movement by hand. Signed-off-by: Richard Henderson --- tcg/s390/tcg-target.inc.c | 30 ++ 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/tcg/s390/tcg-target.inc.c b/tcg/s390/tcg-target.inc.c index 083c992..f4c510e 100644 --- a/tcg/s390/tcg-target.inc.c +++ b/tcg/s390/tcg-target.inc.c @@ -43,6 +43,7 @@ #define TCG_CT_CONST_XORI 0x400 #define TCG_CT_CONST_CMPI 0x800 #define TCG_CT_CONST_ADLI 0x1000 +#define TCG_CT_CONST_ZERO 0x2000 /* Several places within the instruction set 0 means "no register" rather than TCG_REG_R0. */ @@ -404,6 +405,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) case 'C': ct->ct |= TCG_CT_CONST_CMPI; break; +case 'Z': +ct->ct |= TCG_CT_CONST_ZERO; +break; default: return -1; } @@ -543,6 +547,8 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type, return tcg_match_xori(type, val); } else if (ct & TCG_CT_CONST_CMPI) { return tcg_match_cmpi(type, val); +} else if (ct & TCG_CT_CONST_ZERO) { +return val == 0; } return 0; @@ -1240,11 +1246,11 @@ static void tgen_movcond(TCGContext *s, TCGType type, TCGCond c, TCGReg dest, } static void tgen_deposit(TCGContext *s, TCGReg dest, TCGReg src, - int ofs, int len) + int ofs, int len, int z) { int lsb = (63 - ofs); int msb = lsb - (len - 1); -tcg_out_risbg(s, dest, src, msb, lsb, ofs, 0); +tcg_out_risbg(s, dest, src, msb, lsb, ofs, z); } static void tgen_extract(TCGContext *s, TCGReg dest, TCGReg src, @@ -2157,8 +2163,24 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; OP_32_64(deposit): -tgen_deposit(s, args[0], args[2], args[3], args[4]); +a0 = args[0], a1 = args[1], a2 = args[2]; +if (const_args[1]) { +tgen_deposit(s, a0, a2, args[3], args[4], 1); +} else { +/* Since we can't support "0Z" as a constraint, we allow a1 in + any register. Fix things up as if a matching constraint. */ +if (a0 != a1) { +TCGType type = (opc == INDEX_op_deposit_i64); +if (a0 == a2) { +tcg_out_mov(s, type, TCG_TMP0, a2); +a2 = TCG_TMP0; +} +tcg_out_mov(s, type, a0, a1); +} +tgen_deposit(s, a0, a2, args[3], args[4], 0); +} break; + OP_32_64(extract): tgen_extract(s, args[0], args[1], args[2], args[3]); break; @@ -2230,7 +2252,7 @@ static const TCGTargetOpDef s390_op_defs[] = { { INDEX_op_brcond_i32, { "r", "rC" } }, { INDEX_op_setcond_i32, { "r", "r", "rC" } }, { INDEX_op_movcond_i32, { "r", "r", "rC", "r", "0" } }, -{ INDEX_op_deposit_i32, { "r", "0", "r" } }, +{ INDEX_op_deposit_i32, { "r", "rZ", "r" } }, { INDEX_op_extract_i32, { "r", "r" } }, { INDEX_op_qemu_ld_i32, { "r", "L" } }, -- 2.9.3
[Qemu-devel] [PATCH 04/65] tcg/aarch64: Implement field extraction opcodes
Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- tcg/aarch64/tcg-target.h | 8 tcg/aarch64/tcg-target.inc.c | 14 ++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index 410c31b..4a74bd8 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -63,8 +63,8 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 0 -#define TCG_TARGET_HAS_sextract_i32 0 +#define TCG_TARGET_HAS_extract_i32 1 +#define TCG_TARGET_HAS_sextract_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1 @@ -95,8 +95,8 @@ typedef enum { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 0 -#define TCG_TARGET_HAS_sextract_i64 0 +#define TCG_TARGET_HAS_extract_i64 1 +#define TCG_TARGET_HAS_sextract_i64 1 #define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1 diff --git a/tcg/aarch64/tcg-target.inc.c b/tcg/aarch64/tcg-target.inc.c index 1939d35..c0e9890 100644 --- a/tcg/aarch64/tcg-target.inc.c +++ b/tcg/aarch64/tcg-target.inc.c @@ -1640,6 +1640,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]); break; +case INDEX_op_extract_i64: +case INDEX_op_extract_i32: +tcg_out_ubfm(s, ext, a0, a1, a2, a2 + args[3] - 1); +break; + +case INDEX_op_sextract_i64: +case INDEX_op_sextract_i32: +tcg_out_sbfm(s, ext, a0, a1, a2, a2 + args[3] - 1); +break; + case INDEX_op_add2_i32: tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3), (int32_t)args[4], args[5], const_args[4], @@ -1785,6 +1795,10 @@ static const TCGTargetOpDef aarch64_op_defs[] = { { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, { INDEX_op_deposit_i64, { "r", "0", "rZ" } }, +{ INDEX_op_extract_i32, { "r", "r" } }, +{ INDEX_op_extract_i64, { "r", "r" } }, +{ INDEX_op_sextract_i32, { "r", "r" } }, +{ INDEX_op_sextract_i64, { "r", "r" } }, { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } }, { INDEX_op_add2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } }, -- 2.9.3
[Qemu-devel] [PATCH 05/65] tcg/arm: Move isa detection to tcg-target.h
This allows us to use this detection within the TCG_TARGET_HAS_* macros, instead of requiring a function call into tcg-target.inc.c. Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- tcg/arm/tcg-target.h | 36 tcg/arm/tcg-target.inc.c | 41 + 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 8e724be..d1fe12b 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -26,6 +26,37 @@ #ifndef ARM_TCG_TARGET_H #define ARM_TCG_TARGET_H +/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */ +#ifndef __ARM_ARCH +# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH 7 +# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH 6 +# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \ + || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH 5 +# else +# define __ARM_ARCH 4 +# endif +#endif + +extern int arm_arch; + +#if defined(__ARM_ARCH_5T__) \ +|| defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) +# define use_armv5t_instructions 1 +#else +# define use_armv5t_instructions use_armv6_instructions +#endif + +#define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6) +#define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7) + #undef TCG_TARGET_STACK_GROWSUP #define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 16 @@ -79,7 +110,7 @@ extern bool use_idiv_instructions; #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_deposit_i32 use_armv7_instructions #define TCG_TARGET_HAS_extract_i32 0 #define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_movcond_i32 1 @@ -90,9 +121,6 @@ extern bool use_idiv_instructions; #define TCG_TARGET_HAS_div_i32 use_idiv_instructions #define TCG_TARGET_HAS_rem_i32 0 -extern bool tcg_target_deposit_valid(int ofs, int len); -#define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid - enum { TCG_AREG0 = TCG_REG_R6, }; diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c index ffa0d40..1415c27 100644 --- a/tcg/arm/tcg-target.inc.c +++ b/tcg/arm/tcg-target.inc.c @@ -25,36 +25,7 @@ #include "elf.h" #include "tcg-be-ldst.h" -/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */ -#ifndef __ARM_ARCH -# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ - || defined(__ARM_ARCH_7EM__) -# define __ARM_ARCH 7 -# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ - || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) -# define __ARM_ARCH 6 -# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \ - || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ - || defined(__ARM_ARCH_5TEJ__) -# define __ARM_ARCH 5 -# else -# define __ARM_ARCH 4 -# endif -#endif - -static int arm_arch = __ARM_ARCH; - -#if defined(__ARM_ARCH_5T__) \ -|| defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) -# define use_armv5t_instructions 1 -#else -# define use_armv5t_instructions use_armv6_instructions -#endif - -#define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6) -#define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7) +int arm_arch = __ARM_ARCH; #ifndef use_idiv_instructions bool use_idiv_instructions; @@ -730,16 +701,6 @@ static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn) } } -bool tcg_target_deposit_valid(int ofs, int len) -{ -/* ??? Without bfi, we could improve over generic code by combining - the right-shift from a non-zero ofs with the orr. We do run into - problems when rd == rs, and the mask generated from ofs+len doesn't - fit into an immediate. We would have to be careful not to pessimize - wrt the optimizations performed on the expanded code. */ -return use_armv7_instructions; -} - static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd, TCGArg a1, int ofs, int len, bool const_a1) { -- 2.9.3
[Qemu-devel] [PATCH 16/65] target-mips: Use the new extract op
Use extract for EXT and DEXT. Reviewed-by: Yongbok Kim Signed-off-by: Richard Henderson --- target/mips/translate.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/target/mips/translate.c b/target/mips/translate.c index 57b824f..8deffa1 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -4488,11 +4488,12 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, if (lsb + msb > 31) { goto fail; } -tcg_gen_shri_tl(t0, t1, lsb); if (msb != 31) { -tcg_gen_andi_tl(t0, t0, (1U << (msb + 1)) - 1); +tcg_gen_extract_tl(t0, t1, lsb, msb + 1); } else { -tcg_gen_ext32s_tl(t0, t0); +/* The two checks together imply that lsb == 0, + so this is a simple sign-extension. */ +tcg_gen_ext32s_tl(t0, t1); } break; #if defined(TARGET_MIPS64) @@ -4507,10 +4508,7 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, if (lsb + msb > 63) { goto fail; } -tcg_gen_shri_tl(t0, t1, lsb); -if (msb != 63) { -tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1); -} +tcg_gen_extract_tl(t0, t1, lsb, msb + 1); break; #endif case OPC_INS: -- 2.9.3
[Qemu-devel] [PATCH 06/65] tcg/arm: Implement field extraction opcodes
Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- tcg/arm/tcg-target.h | 4 ++-- tcg/arm/tcg-target.inc.c | 24 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index d1fe12b..4e30728 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -111,8 +111,8 @@ extern bool use_idiv_instructions; #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 use_armv7_instructions -#define TCG_TARGET_HAS_extract_i32 0 -#define TCG_TARGET_HAS_sextract_i32 0 +#define TCG_TARGET_HAS_extract_i32 use_armv7_instructions +#define TCG_TARGET_HAS_sextract_i32 use_armv7_instructions #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_mulu2_i321 #define TCG_TARGET_HAS_muls2_i321 diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c index 1415c27..2d5af0f 100644 --- a/tcg/arm/tcg-target.inc.c +++ b/tcg/arm/tcg-target.inc.c @@ -713,6 +713,22 @@ static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd, | (ofs << 7) | ((ofs + len - 1) << 16)); } +static inline void tcg_out_extract(TCGContext *s, int cond, TCGReg rd, + TCGArg a1, int ofs, int len) +{ +/* ubfx */ +tcg_out32(s, 0x07e00050 | (cond << 28) | (rd << 12) | a1 + | (ofs << 7) | ((len - 1) << 16)); +} + +static inline void tcg_out_sextract(TCGContext *s, int cond, TCGReg rd, +TCGArg a1, int ofs, int len) +{ +/* sbfx */ +tcg_out32(s, 0x07a00050 | (cond << 28) | (rd << 12) | a1 + | (ofs << 7) | ((len - 1) << 16)); +} + /* Note that this routine is used for both LDR and LDRH formats, so we do not wish to include an immediate shift at this point. */ static void tcg_out_memop_r(TCGContext *s, int cond, ARMInsn opc, TCGReg rt, @@ -1894,6 +1910,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_deposit(s, COND_AL, args[0], args[2], args[3], args[4], const_args[2]); break; +case INDEX_op_extract_i32: +tcg_out_extract(s, COND_AL, args[0], args[1], args[2], args[3]); +break; +case INDEX_op_sextract_i32: +tcg_out_sextract(s, COND_AL, args[0], args[1], args[2], args[3]); +break; case INDEX_op_div_i32: tcg_out_sdiv(s, COND_AL, args[0], args[1], args[2]); @@ -1976,6 +1998,8 @@ static const TCGTargetOpDef arm_op_defs[] = { { INDEX_op_ext16u_i32, { "r", "r" } }, { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, +{ INDEX_op_extract_i32, { "r", "r" } }, +{ INDEX_op_sextract_i32, { "r", "r" } }, { INDEX_op_div_i32, { "r", "r", "r" } }, { INDEX_op_divu_i32, { "r", "r", "r" } }, -- 2.9.3
[Qemu-devel] [PATCH 15/65] target-i386: Use new deposit and extract ops
A couple of places where it was easy to identify a right-shift followed by an extract or and-with-immediate, and the obvious sign-extract from a high byte register. Acked-by: Eduardo Habkost Signed-off-by: Richard Henderson --- target/i386/translate.c | 45 +++-- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/target/i386/translate.c b/target/i386/translate.c index 59e11fc..816d0b1 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -383,8 +383,7 @@ static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0) static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg) { if (ot == MO_8 && byte_reg_is_xH(reg)) { -tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8); -tcg_gen_ext8u_tl(t0, t0); +tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8); } else { tcg_gen_mov_tl(t0, cpu_regs[reg]); } @@ -3768,8 +3767,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, /* Extract the LEN into a mask. Lengths larger than operand size get all ones. */ -tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8); -tcg_gen_ext8u_tl(cpu_A0, cpu_A0); +tcg_gen_extract_tl(cpu_A0, cpu_regs[s->vex_v], 8, 8); tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound, cpu_A0, bound); tcg_temp_free(bound); @@ -3920,9 +3918,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_compute_eflags(s); } carry_in = cpu_tmp0; -tcg_gen_shri_tl(carry_in, cpu_cc_src, -ctz32(b == 0x1f6 ? CC_C : CC_O)); -tcg_gen_andi_tl(carry_in, carry_in, 1); +tcg_gen_extract_tl(carry_in, cpu_cc_src, + ctz32(b == 0x1f6 ? CC_C : CC_O), 1); } switch (ot) { @@ -5447,21 +5444,25 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, rm = (modrm & 7) | REX_B(s); if (mod == 3) { -gen_op_mov_v_reg(ot, cpu_T0, rm); -switch (s_ot) { -case MO_UB: -tcg_gen_ext8u_tl(cpu_T0, cpu_T0); -break; -case MO_SB: -tcg_gen_ext8s_tl(cpu_T0, cpu_T0); -break; -case MO_UW: -tcg_gen_ext16u_tl(cpu_T0, cpu_T0); -break; -default: -case MO_SW: -tcg_gen_ext16s_tl(cpu_T0, cpu_T0); -break; +if (s_ot == MO_SB && byte_reg_is_xH(rm)) { +tcg_gen_sextract_tl(cpu_T0, cpu_regs[rm - 4], 8, 8); +} else { +gen_op_mov_v_reg(ot, cpu_T0, rm); +switch (s_ot) { +case MO_UB: +tcg_gen_ext8u_tl(cpu_T0, cpu_T0); +break; +case MO_SB: +tcg_gen_ext8s_tl(cpu_T0, cpu_T0); +break; +case MO_UW: +tcg_gen_ext16u_tl(cpu_T0, cpu_T0); +break; +default: +case MO_SW: +tcg_gen_ext16s_tl(cpu_T0, cpu_T0); +break; +} } gen_op_mov_reg_v(d_ot, reg, cpu_T0); } else { -- 2.9.3
[Qemu-devel] [PATCH 07/65] tcg/i386: Implement field extraction opcodes
Signed-off-by: Richard Henderson --- tcg/i386/tcg-target.h | 12 +--- tcg/i386/tcg-target.inc.c | 38 ++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 7625188..dc19c47 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -94,8 +94,8 @@ extern bool have_bmi1; #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 0 -#define TCG_TARGET_HAS_sextract_i32 0 +#define TCG_TARGET_HAS_extract_i32 1 +#define TCG_TARGET_HAS_sextract_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1 @@ -126,7 +126,7 @@ extern bool have_bmi1; #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_extract_i64 1 #define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_add2_i64 1 @@ -142,6 +142,12 @@ extern bool have_bmi1; ((ofs) == 0 && (len) == 16)) #define TCG_TARGET_deposit_i64_validTCG_TARGET_deposit_i32_valid +/* Check for the possibility of high-byte extraction and, for 64-bit, + zero-extending 32-bit right-shift. */ +#define TCG_TARGET_extract_i32_valid(ofs, len) ((ofs) == 8 && (len) == 8) +#define TCG_TARGET_extract_i64_valid(ofs, len) \ +(((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32) + #if TCG_TARGET_REG_BITS == 64 # define TCG_AREG0 TCG_REG_R14 #else diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c index eeb1777..39f62bd 100644 --- a/tcg/i386/tcg-target.inc.c +++ b/tcg/i386/tcg-target.inc.c @@ -2143,6 +2143,40 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; +case INDEX_op_extract_i64: +if (args[2] + args[3] == 32) { +/* This is a 32-bit zero-extending right shift. */ +tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]); +tcg_out_shifti(s, SHIFT_SHR, args[0], args[2]); +break; +} +/* FALLTHRU */ +case INDEX_op_extract_i32: +/* On the off-chance that we can use the high-byte registers. + Otherwise we emit the same ext16 + shift pattern that we + would have gotten from the normal tcg-op.c expansion. */ +tcg_debug_assert(args[2] == 8 && args[3] == 8); +if (args[1] < 4 && args[0] < 8) { +tcg_out_modrm(s, OPC_MOVZBL, args[0], args[1] + 4); +} else { +tcg_out_ext16u(s, args[0], args[1]); +tcg_out_shifti(s, SHIFT_SHR, args[0], 8); +} +break; + +case INDEX_op_sextract_i32: +/* We don't implement sextract_i64, as we cannot sign-extend to + 64-bits without using the REX prefix that explicitly excludes + access to the high-byte registers. */ +tcg_debug_assert(args[2] == 8 && args[3] == 8); +if (args[1] < 4 && args[0] < 8) { +tcg_out_modrm(s, OPC_MOVSBL, args[0], args[1] + 4); +} else { +tcg_out_ext16s(s, args[0], args[1], 0); +tcg_out_shifti(s, SHIFT_SAR, args[0], 8); +} +break; + case INDEX_op_mb: tcg_out_mb(s, args[0]); break; @@ -2204,6 +2238,9 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_setcond_i32, { "q", "r", "ri" } }, { INDEX_op_deposit_i32, { "Q", "0", "Q" } }, +{ INDEX_op_extract_i32, { "r", "r" } }, +{ INDEX_op_sextract_i32, { "r", "r" } }, + { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } }, { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } }, @@ -2265,6 +2302,7 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_extu_i32_i64, { "r", "r" } }, { INDEX_op_deposit_i64, { "Q", "0", "Q" } }, +{ INDEX_op_extract_i64, { "r", "r" } }, { INDEX_op_movcond_i64, { "r", "r", "re", "r", "0" } }, { INDEX_op_mulu2_i64, { "a", "d", "a", "r" } }, -- 2.9.3
[Qemu-devel] [PATCH 23/65] tcg: Allow an operand to be matching or a constant
This allows an output operand to match an input operand only when the input operand needs a register. Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- tcg/README | 13 + tcg/tcg.c | 63 +++--- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/tcg/README b/tcg/README index 065d9c2..6946b5b 100644 --- a/tcg/README +++ b/tcg/README @@ -539,24 +539,29 @@ version. Aliases are specified in the input operands as for GCC. The same register may be used for both an input and an output, even when they are not explicitly aliased. If an op expands to multiple target instructions then care must be taken to avoid clobbering input values. -GCC style "early clobber" outputs are not currently supported. +GCC style "early clobber" outputs are supported, with '&'. A target can define specific register or constant constraints. If an operation uses a constant input constraint which does not allow all constants, it must also accept registers in order to have a fallback. +The constraint 'i' is defined generically to accept any constant. +The constraint 'r' is not defined generically, but is consistently +used by each backend to indicate all registers. The movi_i32 and movi_i64 operations must accept any constants. The mov_i32 and mov_i64 operations must accept any registers of the same type. -The ld/st instructions must accept signed 32 bit constant offsets. It -can be implemented by reserving a specific register to compute the -address if the offset is too big. +The ld/st/sti instructions must accept signed 32 bit constant offsets. +This can be implemented by reserving a specific register in which to +compute the address if the offset is too big. The ld/st instructions must accept any destination (ld) or source (st) register. +The sti instruction may fail if it cannot store the given constant. + 4.3) Function call assumptions - The only supported types for parameters and return value are: 32 and diff --git a/tcg/tcg.c b/tcg/tcg.c index 8b4dce7..cb898f1 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1256,37 +1256,37 @@ static void process_op_defs(TCGContext *s) tcg_regset_clear(def->args_ct[i].u.regs); def->args_ct[i].ct = 0; -if (ct_str[0] >= '0' && ct_str[0] <= '9') { -int oarg; -oarg = ct_str[0] - '0'; -tcg_debug_assert(oarg < def->nb_oargs); -tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG); -/* TCG_CT_ALIAS is for the output arguments. The input - argument is tagged with TCG_CT_IALIAS. */ -def->args_ct[i] = def->args_ct[oarg]; -def->args_ct[oarg].ct = TCG_CT_ALIAS; -def->args_ct[oarg].alias_index = i; -def->args_ct[i].ct |= TCG_CT_IALIAS; -def->args_ct[i].alias_index = oarg; -} else { -for(;;) { -if (*ct_str == '\0') -break; -switch(*ct_str) { -case '&': -def->args_ct[i].ct |= TCG_CT_NEWREG; -ct_str++; -break; -case 'i': -def->args_ct[i].ct |= TCG_CT_CONST; -ct_str++; -break; -default: -ct_str = target_parse_constraint(&def->args_ct[i], - ct_str, type); -/* Typo in TCGTargetOpDef constraint. */ -tcg_debug_assert(ct_str != NULL); +while (*ct_str != '\0') { +switch(*ct_str) { +case '0' ... '9': +{ +int oarg = *ct_str - '0'; +tcg_debug_assert(ct_str == tdefs->args_ct_str[i]); +tcg_debug_assert(oarg < def->nb_oargs); +tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG); +/* TCG_CT_ALIAS is for the output arguments. + The input is tagged with TCG_CT_IALIAS. */ +def->args_ct[i] = def->args_ct[oarg]; +def->args_ct[oarg].ct |= TCG_CT_ALIAS; +def->args_ct[oarg].alias_index = i; +def->args_ct[i].ct |= TCG_CT_IALIAS; +def->args_ct[i].alias_index = oarg; } +ct_str++; +break; +case '&': +def->args_ct[i].ct |= TCG_CT_NEWREG; +ct_str++; +break; +case 'i': +def->args_ct[i].ct |= TCG_CT_CONST; +ct_str++; +break; +default: +
[Qemu-devel] [PATCH 17/65] target-ppc: Use the new deposit and extract ops
Use the new primitives for RDWINM and RLDICL. Reviewed-by: David Gibson Signed-off-by: Richard Henderson --- target/ppc/translate.c | 35 +++ 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 59e9552..435c6f0 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -1975,16 +1975,16 @@ static void gen_rlwinm(DisasContext *ctx) { TCGv t_ra = cpu_gpr[rA(ctx->opcode)]; TCGv t_rs = cpu_gpr[rS(ctx->opcode)]; -uint32_t sh = SH(ctx->opcode); -uint32_t mb = MB(ctx->opcode); -uint32_t me = ME(ctx->opcode); - -if (mb == 0 && me == (31 - sh)) { -tcg_gen_shli_tl(t_ra, t_rs, sh); -tcg_gen_ext32u_tl(t_ra, t_ra); -} else if (sh != 0 && me == 31 && sh == (32 - mb)) { -tcg_gen_ext32u_tl(t_ra, t_rs); -tcg_gen_shri_tl(t_ra, t_ra, mb); +int sh = SH(ctx->opcode); +int mb = MB(ctx->opcode); +int me = ME(ctx->opcode); +int len = me - mb + 1; +int rsh = (32 - sh) & 31; + +if (sh != 0 && len > 0 && me == (31 - sh)) { +tcg_gen_deposit_z_tl(t_ra, t_rs, sh, len); +} else if (me == 31 && rsh + len <= 32) { +tcg_gen_extract_tl(t_ra, t_rs, rsh, len); } else { target_ulong mask; #if defined(TARGET_PPC64) @@ -1992,8 +1992,9 @@ static void gen_rlwinm(DisasContext *ctx) me += 32; #endif mask = MASK(mb, me); - -if (mask <= 0xu) { +if (sh == 0) { +tcg_gen_andi_tl(t_ra, t_rs, mask); +} else if (mask <= 0xu) { TCGv_i32 t0 = tcg_temp_new_i32(); tcg_gen_trunc_tl_i32(t0, t_rs); tcg_gen_rotli_i32(t0, t0, sh); @@ -2096,11 +2097,13 @@ static void gen_rldinm(DisasContext *ctx, int mb, int me, int sh) { TCGv t_ra = cpu_gpr[rA(ctx->opcode)]; TCGv t_rs = cpu_gpr[rS(ctx->opcode)]; +int len = me - mb + 1; +int rsh = (64 - sh) & 63; -if (sh != 0 && mb == 0 && me == (63 - sh)) { -tcg_gen_shli_tl(t_ra, t_rs, sh); -} else if (sh != 0 && me == 63 && sh == (64 - mb)) { -tcg_gen_shri_tl(t_ra, t_rs, mb); +if (sh != 0 && len > 0 && me == (63 - sh)) { +tcg_gen_deposit_z_tl(t_ra, t_rs, sh, len); +} else if (me == 63 && rsh + len <= 64) { +tcg_gen_extract_tl(t_ra, t_rs, rsh, len); } else { tcg_gen_rotli_tl(t_ra, t_rs, sh); tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me)); -- 2.9.3
[Qemu-devel] [PATCH 25/65] disas/i386.c: Handle tzcnt
Signed-off-by: Richard Henderson --- disas/i386.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/disas/i386.c b/disas/i386.c index 57145d0..07f871f 100644 --- a/disas/i386.c +++ b/disas/i386.c @@ -682,6 +682,7 @@ fetch_data(struct disassemble_info *info, bfd_byte *addr) #define PREGRP104 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 104 } } #define PREGRP105 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 105 } } #define PREGRP106 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 106 } } +#define PREGRP107 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 107 } } #define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } #define X86_64_1 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 1 } } @@ -1247,7 +1248,7 @@ static const struct dis386 dis386_twobyte[] = { { "ud2b",{ XX } }, { GRP8 }, { "btcS",{ Ev, Gv } }, - { "bsfS",{ Gv, Ev } }, + { PREGRP107 }, { PREGRP36 }, { "movs{bR|x|bR|x}", { Gv, Eb } }, { "movs{wR|x|wR|x}", { Gv, Ew } }, /* yes, there really is movsww ! */ @@ -1431,7 +1432,7 @@ static const unsigned char twobyte_uses_REPZ_prefix[256] = { /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, /* bf */ + /* b0 */ 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0, /* bf */ /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ @@ -2800,6 +2801,13 @@ static const struct dis386 prefix_user_table[][4] = { { "shrxS", { Gv, Ev, Bv } }, }, + /* PREGRP107 */ + { +{ "bsfS", { Gv, Ev } }, +{ "tzcntS",{ Gv, Ev } }, +{ "bsfS", { Gv, Ev } }, +{ "(bad)", { XX } }, + }, }; static const struct dis386 x86_64_table[][2] = { -- 2.9.3
[Qemu-devel] [PATCH 10/65] tcg/s390: Expose host facilities to tcg-target.h
This lets us expose facilities to TCG_TARGET_HAS_* defines directly, rather than hiding behind function calls. Signed-off-by: Richard Henderson --- tcg/s390/tcg-target.h | 126 -- tcg/s390/tcg-target.inc.c | 74 +++ 2 files changed, 96 insertions(+), 104 deletions(-) diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index 9583df4..d650a72 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -49,67 +49,75 @@ typedef enum TCGReg { #define TCG_TARGET_NB_REGS 16 -/* optional instructions */ -#define TCG_TARGET_HAS_div2_i32 1 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_ext8s_i321 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_ext8u_i321 -#define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_not_i32 0 -#define TCG_TARGET_HAS_neg_i32 1 -#define TCG_TARGET_HAS_andc_i32 0 -#define TCG_TARGET_HAS_orc_i32 0 -#define TCG_TARGET_HAS_eqv_i32 0 -#define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 0 -#define TCG_TARGET_HAS_sextract_i32 0 -#define TCG_TARGET_HAS_movcond_i32 1 -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#define TCG_TARGET_HAS_mulu2_i320 -#define TCG_TARGET_HAS_muls2_i320 -#define TCG_TARGET_HAS_muluh_i320 -#define TCG_TARGET_HAS_mulsh_i320 -#define TCG_TARGET_HAS_extrl_i64_i320 -#define TCG_TARGET_HAS_extrh_i64_i320 +/* A list of relevant facilities used by this translator. Some of these + are required for proper operation, and these are checked at startup. */ + +#define FACILITY_ZARCH_ACTIVE (1ULL << (63 - 2)) +#define FACILITY_LONG_DISP(1ULL << (63 - 18)) +#define FACILITY_EXT_IMM (1ULL << (63 - 21)) +#define FACILITY_GEN_INST_EXT (1ULL << (63 - 34)) +#define FACILITY_LOAD_ON_COND (1ULL << (63 - 45)) +#define FACILITY_FAST_BCR_SER FACILITY_LOAD_ON_COND -#define TCG_TARGET_HAS_div2_i64 1 -#define TCG_TARGET_HAS_rot_i64 1 -#define TCG_TARGET_HAS_ext8s_i641 -#define TCG_TARGET_HAS_ext16s_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i641 -#define TCG_TARGET_HAS_ext16u_i64 1 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 1 -#define TCG_TARGET_HAS_bswap32_i64 1 -#define TCG_TARGET_HAS_bswap64_i64 1 -#define TCG_TARGET_HAS_not_i64 0 -#define TCG_TARGET_HAS_neg_i64 1 -#define TCG_TARGET_HAS_andc_i64 0 -#define TCG_TARGET_HAS_orc_i64 0 -#define TCG_TARGET_HAS_eqv_i64 0 -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 0 -#define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 0 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_movcond_i64 1 -#define TCG_TARGET_HAS_add2_i64 1 -#define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i641 -#define TCG_TARGET_HAS_muls2_i640 -#define TCG_TARGET_HAS_muluh_i640 -#define TCG_TARGET_HAS_mulsh_i640 +extern uint64_t s390_facilities; + +/* optional instructions */ +#define TCG_TARGET_HAS_div2_i32 1 +#define TCG_TARGET_HAS_rot_i321 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i321 +#define TCG_TARGET_HAS_bswap32_i321 +#define TCG_TARGET_HAS_not_i320 +#define TCG_TARGET_HAS_neg_i321 +#define TCG_TARGET_HAS_andc_i32 0 +#define TCG_TARGET_HAS_orc_i320 +#define TCG_TARGET_HAS_eqv_i320 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i320 +#define TCG_TARGET_HAS_deposit_i32(s390_facilities & FACILITY_GEN_INST_EXT) +#define TCG_TARGET_HAS_extract_i320 +#define TCG_TARGET_HAS_sextract_i32 0 +#define TCG_TARGET_HAS_movcond_i321 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 0 +#define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_extrl_i64_i32 0 +#define TCG_TARGET_HAS_extrh_i64_i32 0 -extern bool tcg_target_deposit_valid(int ofs, int len); -#define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid -#define TCG_TARGET_deposit_i64_valid tcg_target_deposit_valid +#define TCG_TARGET_HAS_div2_i64 1 +#define TCG_TARGET_HAS_rot_i641 +#define TCG_TARGET_HAS_ext8s_i64 1 +#defi
[Qemu-devel] [PATCH 08/65] tcg/mips: Implement field extraction opcodes
Cc: Yongbok Kim Signed-off-by: Richard Henderson --- tcg/mips/tcg-target.h | 2 +- tcg/mips/tcg-target.inc.c | 4 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 1bcea3b..f1c3137 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -123,7 +123,7 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_bswap32_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_deposit_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_extract_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_ext8s_i32use_mips32r2_instructions #define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index abce602..1ecae08 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -1637,6 +1637,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_deposit_i32: tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]); break; +case INDEX_op_extract_i32: +tcg_out_opc_bf(s, OPC_EXT, a0, a1, a2 + args[3] - 1, a2); +break; case INDEX_op_brcond_i32: tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); @@ -1736,6 +1739,7 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_ext16s_i32, { "r", "rZ" } }, { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, +{ INDEX_op_extract_i32, { "r", "r" } }, { INDEX_op_brcond_i32, { "rZ", "rZ" } }, #if use_mips32r6_instructions -- 2.9.3
[Qemu-devel] [PATCH 32/65] target-ppc: Use clz and ctz opcodes
Cc: qemu-...@nongnu.org Signed-off-by: Richard Henderson --- target/ppc/helper.h | 4 target/ppc/int_helper.c | 20 target/ppc/translate.c | 20 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/target/ppc/helper.h b/target/ppc/helper.h index da00f0a..1ed1d2c 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -38,16 +38,12 @@ DEF_HELPER_4(divde, i64, env, i64, i64, i32) DEF_HELPER_4(divweu, tl, env, tl, tl, i32) DEF_HELPER_4(divwe, tl, env, tl, tl, i32) -DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(cnttzw, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_2(cmpb, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_3(sraw, tl, env, tl, tl) #if defined(TARGET_PPC64) DEF_HELPER_FLAGS_2(cmpeqb, TCG_CALL_NO_RWG_SE, i32, tl, tl) -DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(cnttzd, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(popcntd, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_2(bpermd, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_3(srad, tl, env, tl, tl) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 2d57c9a..e1bb695 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -141,16 +141,6 @@ uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe) #endif -target_ulong helper_cntlzw(target_ulong t) -{ -return clz32(t); -} - -target_ulong helper_cnttzw(target_ulong t) -{ -return ctz32(t); -} - #if defined(TARGET_PPC64) /* if x = 0xab, returns 0xababababababababa */ #define pattern(x) (((x) & 0xff) * (~(target_ulong)0 / 0xff)) @@ -174,16 +164,6 @@ uint32_t helper_cmpeqb(target_ulong ra, target_ulong rb) #undef haszero #undef hasvalue -target_ulong helper_cntlzd(target_ulong t) -{ -return clz64(t); -} - -target_ulong helper_cnttzd(target_ulong t) -{ -return ctz64(t); -} - /* Return invalid random number. * * FIXME: Add rng backend or other mechanism to get cryptographically suitable diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 435c6f0..1224f56 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -1641,7 +1641,13 @@ static void gen_andis_(DisasContext *ctx) /* cntlzw */ static void gen_cntlzw(DisasContext *ctx) { -gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); +TCGv_i32 t = tcg_temp_new_i32(); + +tcg_gen_trunc_tl_i32(t, cpu_gpr[rS(ctx->opcode)]); +tcg_gen_clzi_i32(t, t, 32); +tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t); +tcg_temp_free_i32(t); + if (unlikely(Rc(ctx->opcode) != 0)) gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } @@ -1649,7 +1655,13 @@ static void gen_cntlzw(DisasContext *ctx) /* cnttzw */ static void gen_cnttzw(DisasContext *ctx) { -gen_helper_cnttzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); +TCGv_i32 t = tcg_temp_new_i32(); + +tcg_gen_trunc_tl_i32(t, cpu_gpr[rS(ctx->opcode)]); +tcg_gen_ctzi_i32(t, t, 32); +tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t); +tcg_temp_free_i32(t); + if (unlikely(Rc(ctx->opcode) != 0)) { gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } @@ -1891,7 +1903,7 @@ GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B); /* cntlzd */ static void gen_cntlzd(DisasContext *ctx) { -gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); +tcg_gen_clzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64); if (unlikely(Rc(ctx->opcode) != 0)) gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } @@ -1899,7 +1911,7 @@ static void gen_cntlzd(DisasContext *ctx) /* cnttzd */ static void gen_cnttzd(DisasContext *ctx) { -gen_helper_cnttzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); +tcg_gen_ctzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64); if (unlikely(Rc(ctx->opcode) != 0)) { gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } -- 2.9.3
[Qemu-devel] [PATCH 29/65] target-microblaze: Use clz opcode
Cc: Edgar E. Iglesias Signed-off-by: Richard Henderson --- target/microblaze/helper.h| 1 - target/microblaze/op_helper.c | 5 - target/microblaze/translate.c | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/target/microblaze/helper.h b/target/microblaze/helper.h index bd13826..71a6c08 100644 --- a/target/microblaze/helper.h +++ b/target/microblaze/helper.h @@ -3,7 +3,6 @@ DEF_HELPER_1(debug, void, env) DEF_HELPER_FLAGS_3(carry, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(cmp, i32, i32, i32) DEF_HELPER_2(cmpu, i32, i32, i32) -DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_3(divs, i32, env, i32, i32) DEF_HELPER_3(divu, i32, env, i32, i32) diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c index 4a856e6..1e07e21 100644 --- a/target/microblaze/op_helper.c +++ b/target/microblaze/op_helper.c @@ -145,11 +145,6 @@ uint32_t helper_cmpu(uint32_t a, uint32_t b) return t; } -uint32_t helper_clz(uint32_t t0) -{ -return clz32(t0); -} - uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf) { return compute_carry(a, b, cf); diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index de2090a..0bb6095 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -768,7 +768,7 @@ static void dec_bit(DisasContext *dc) t_gen_raise_exception(dc, EXCP_HW_EXCP); } if (dc->cpu->env.pvr.regs[2] & PVR2_USE_PCMP_INSTR) { -gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]); +tcg_gen_clzi_i32(cpu_R[dc->rd], cpu_R[dc->ra], 32); } break; case 0x1e0: -- 2.9.3
[Qemu-devel] [PATCH 27/65] target-alpha: Use the ctz and clz opcodes
Signed-off-by: Richard Henderson --- target/alpha/helper.h | 2 -- target/alpha/int_helper.c | 10 -- target/alpha/translate.c | 4 ++-- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/target/alpha/helper.h b/target/alpha/helper.h index 004221d..eed3906 100644 --- a/target/alpha/helper.h +++ b/target/alpha/helper.h @@ -4,8 +4,6 @@ DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_NO_RWG_SE, i64, env) DEF_HELPER_FLAGS_3(check_overflow, TCG_CALL_NO_WG, void, env, i64, i64) DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_NO_RWG_SE, i64, i64) -DEF_HELPER_FLAGS_1(ctlz, TCG_CALL_NO_RWG_SE, i64, i64) -DEF_HELPER_FLAGS_1(cttz, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_2(zap, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(zapnot, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target/alpha/int_helper.c b/target/alpha/int_helper.c index 19bebfe..3c303bd 100644 --- a/target/alpha/int_helper.c +++ b/target/alpha/int_helper.c @@ -29,16 +29,6 @@ uint64_t helper_ctpop(uint64_t arg) return ctpop64(arg); } -uint64_t helper_ctlz(uint64_t arg) -{ -return clz64(arg); -} - -uint64_t helper_cttz(uint64_t arg) -{ -return ctz64(arg); -} - uint64_t helper_zapnot(uint64_t val, uint64_t mskb) { uint64_t mask; diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 5ac2277..6e2e563 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -2555,14 +2555,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX); REQUIRE_REG_31(ra); REQUIRE_NO_LIT; -gen_helper_ctlz(vc, vb); +tcg_gen_clzi_i64(vc, vb, 64); break; case 0x33: /* CTTZ */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX); REQUIRE_REG_31(ra); REQUIRE_NO_LIT; -gen_helper_cttz(vc, vb); +tcg_gen_ctzi_i64(vc, vb, 64); break; case 0x34: /* UNPKBW */ -- 2.9.3
[Qemu-devel] [PATCH 09/65] tcg/ppc: Implement field extraction opcodes
Reviewed-by: David Gibson Signed-off-by: Richard Henderson --- tcg/ppc/tcg-target.h | 4 ++-- tcg/ppc/tcg-target.inc.c | 10 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index c765d3e..b42c57a 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -69,7 +69,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 1 #define TCG_TARGET_HAS_nor_i32 1 #define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_extract_i32 1 #define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_mulu2_i320 @@ -102,7 +102,7 @@ typedef enum { #define TCG_TARGET_HAS_nand_i64 1 #define TCG_TARGET_HAS_nor_i64 1 #define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_extract_i64 1 #define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_add2_i64 1 diff --git a/tcg/ppc/tcg-target.inc.c b/tcg/ppc/tcg-target.inc.c index a3262cf..7ec54a2 100644 --- a/tcg/ppc/tcg-target.inc.c +++ b/tcg/ppc/tcg-target.inc.c @@ -2396,6 +2396,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, } break; +case INDEX_op_extract_i32: +tcg_out_rlw(s, RLWINM, args[0], args[1], +32 - args[2], 32 - args[3], 31); +break; +case INDEX_op_extract_i64: +tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 64 - args[3]); +break; + case INDEX_op_movcond_i32: tcg_out_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1], args[2], args[3], args[4], const_args[2]); @@ -2530,6 +2538,7 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_movcond_i32, { "r", "r", "ri", "rZ", "rZ" } }, { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, +{ INDEX_op_extract_i32, { "r", "r" } }, { INDEX_op_muluh_i32, { "r", "r", "r" } }, { INDEX_op_mulsh_i32, { "r", "r", "r" } }, @@ -2585,6 +2594,7 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_movcond_i64, { "r", "r", "ri", "rZ", "rZ" } }, { INDEX_op_deposit_i64, { "r", "0", "rZ" } }, +{ INDEX_op_extract_i64, { "r", "r" } }, { INDEX_op_mulsh_i64, { "r", "r", "r" } }, { INDEX_op_muluh_i64, { "r", "r", "r" } }, -- 2.9.3
[Qemu-devel] [PATCH 31/65] target-openrisc: Use clz and ctz opcodes
Signed-off-by: Richard Henderson --- target/openrisc/helper.h | 2 -- target/openrisc/int_helper.c | 19 --- target/openrisc/translate.c | 6 -- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index f53fa21..bcc7245 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -54,8 +54,6 @@ FOP_CMP(ge) #undef FOP_CMP /* int */ -DEF_HELPER_FLAGS_1(ff1, 0, tl, tl) -DEF_HELPER_FLAGS_1(fl1, 0, tl, tl) DEF_HELPER_FLAGS_3(mul32, 0, i32, env, i32, i32) /* interrupt */ diff --git a/target/openrisc/int_helper.c b/target/openrisc/int_helper.c index 4d1f958..ba0fd27 100644 --- a/target/openrisc/int_helper.c +++ b/target/openrisc/int_helper.c @@ -24,25 +24,6 @@ #include "exception.h" #include "qemu/host-utils.h" -target_ulong HELPER(ff1)(target_ulong x) -{ -/*#ifdef TARGET_OPENRISC64 -return x ? ctz64(x) + 1 : 0; -#else*/ -return x ? ctz32(x) + 1 : 0; -/*#endif*/ -} - -target_ulong HELPER(fl1)(target_ulong x) -{ -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 -return 64 - clz64(x); -#else*/ -return 32 - clz32(x); -/*#endif*/ -} - uint32_t HELPER(mul32)(CPUOpenRISCState *env, uint32_t ra, uint32_t rb) { diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 229361a..03fa7db 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -602,11 +602,13 @@ static void dec_calc(DisasContext *dc, uint32_t insn) switch (op1) { case 0x00:/* l.ff1 */ LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); -gen_helper_ff1(cpu_R[rd], cpu_R[ra]); +tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1); +tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1); break; case 0x01:/* l.fl1 */ LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); -gen_helper_fl1(cpu_R[rd], cpu_R[ra]); +tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS); +tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]); break; default: -- 2.9.3
[Qemu-devel] [PATCH 37/65] target-xtensa: Use clz opcode
Cc: Max Filippov Signed-off-by: Richard Henderson --- target/xtensa/helper.h| 2 -- target/xtensa/op_helper.c | 13 - target/xtensa/translate.c | 13 +++-- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h index 5ea9c5b..0c8adae 100644 --- a/target/xtensa/helper.h +++ b/target/xtensa/helper.h @@ -3,8 +3,6 @@ DEF_HELPER_3(exception_cause, noreturn, env, i32, i32) DEF_HELPER_4(exception_cause_vaddr, noreturn, env, i32, i32, i32) DEF_HELPER_3(debug_exception, noreturn, env, i32, i32) -DEF_HELPER_FLAGS_1(nsa, TCG_CALL_NO_RWG_SE, i32, i32) -DEF_HELPER_FLAGS_1(nsau, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_2(wsr_windowbase, void, env, i32) DEF_HELPER_4(entry, void, env, i32, i32, i32) DEF_HELPER_2(retw, i32, env, i32) diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 0a4b214..dc25625 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -161,19 +161,6 @@ void HELPER(debug_exception)(CPUXtensaState *env, uint32_t pc, uint32_t cause) HELPER(exception)(env, EXC_DEBUG); } -uint32_t HELPER(nsa)(uint32_t v) -{ -if (v & 0x8000) { -v = ~v; -} -return v ? clz32(v) - 1 : 31; -} - -uint32_t HELPER(nsau)(uint32_t v) -{ -return v ? clz32(v) : 32; -} - static void copy_window_from_phys(CPUXtensaState *env, uint32_t window, uint32_t phys, uint32_t n) { diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 0858c29..5c719a4 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1372,14 +1372,23 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) case 14: /*NSAu*/ HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA); if (gen_window_check2(dc, RRR_S, RRR_T)) { -gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]); +TCGv_i32 t0 = tcg_temp_new_i32(); + +/* if (v & 0x8000) v = ~v; */ +tcg_gen_sari_i32(t0, cpu_R[RRR_S], 31); +tcg_gen_xor_i32(t0, t0, cpu_R[RRR_S]); + +/* r = (v ? clz(v) : 32) - 1; */ +tcg_gen_clzi_i32(t0, t0, 32); +tcg_gen_subi_i32(cpu_R[RRR_T], t0, 1); +tcg_temp_free_i32(t0); } break; case 15: /*NSAUu*/ HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA); if (gen_window_check2(dc, RRR_S, RRR_T)) { -gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]); +tcg_gen_clzi_i32(cpu_R[RRR_T], cpu_R[RRR_S], 32); } break; -- 2.9.3
[Qemu-devel] [PATCH 24/65] tcg: Add clz and ctz opcodes
Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- tcg-runtime.c| 20 +++ tcg/README | 8 +++ tcg/aarch64/tcg-target.h | 4 ++ tcg/arm/tcg-target.h | 2 + tcg/i386/tcg-target.h| 4 ++ tcg/ia64/tcg-target.h| 4 ++ tcg/mips/tcg-target.h| 2 + tcg/optimize.c | 36 tcg/ppc/tcg-target.h | 4 ++ tcg/s390/tcg-target.h| 4 ++ tcg/sparc/tcg-target.h | 4 ++ tcg/tcg-op.c | 143 +++ tcg/tcg-op.h | 16 ++ tcg/tcg-opc.h| 4 ++ tcg/tcg-runtime.h| 5 ++ tcg/tcg.h| 2 + tcg/tci/tcg-target.h | 4 ++ 17 files changed, 266 insertions(+) diff --git a/tcg-runtime.c b/tcg-runtime.c index 9327b6f..eb3bade 100644 --- a/tcg-runtime.c +++ b/tcg-runtime.c @@ -101,6 +101,26 @@ int64_t HELPER(mulsh_i64)(int64_t arg1, int64_t arg2) return h; } +uint32_t HELPER(clz_i32)(uint32_t arg, uint32_t zero_val) +{ +return arg ? clz32(arg) : zero_val; +} + +uint32_t HELPER(ctz_i32)(uint32_t arg, uint32_t zero_val) +{ +return arg ? ctz32(arg) : zero_val; +} + +uint64_t HELPER(clz_i64)(uint64_t arg, uint64_t zero_val) +{ +return arg ? clz64(arg) : zero_val; +} + +uint64_t HELPER(ctz_i64)(uint64_t arg, uint64_t zero_val) +{ +return arg ? ctz64(arg) : zero_val; +} + void HELPER(exit_atomic)(CPUArchState *env) { cpu_loop_exit_atomic(ENV_GET_CPU(env), GETPC()); diff --git a/tcg/README b/tcg/README index 6946b5b..a9858c2 100644 --- a/tcg/README +++ b/tcg/README @@ -246,6 +246,14 @@ t0=~(t1|t2) t0=t1|~t2 +* clz_i32/i64 t0, t1, t2 + +t0 = t1 ? clz(t1) : t2 + +* ctz_i32/i64 t0, t1, t2 + +t0 = t1 ? ctz(t1) : t2 + * Shifts/Rotates * shl_i32/i64 t0, t1, t2 diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index 4a74bd8..976f493 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -62,6 +62,8 @@ typedef enum { #define TCG_TARGET_HAS_eqv_i32 1 #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 0 +#define TCG_TARGET_HAS_ctz_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_extract_i32 1 #define TCG_TARGET_HAS_sextract_i32 1 @@ -94,6 +96,8 @@ typedef enum { #define TCG_TARGET_HAS_eqv_i64 1 #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 0 +#define TCG_TARGET_HAS_ctz_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 #define TCG_TARGET_HAS_extract_i64 1 #define TCG_TARGET_HAS_sextract_i64 1 diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 4e30728..02cc242 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -110,6 +110,8 @@ extern bool use_idiv_instructions; #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 0 +#define TCG_TARGET_HAS_ctz_i32 0 #define TCG_TARGET_HAS_deposit_i32 use_armv7_instructions #define TCG_TARGET_HAS_extract_i32 use_armv7_instructions #define TCG_TARGET_HAS_sextract_i32 use_armv7_instructions diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index dc19c47..f2d9955 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -93,6 +93,8 @@ extern bool have_bmi1; #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 0 +#define TCG_TARGET_HAS_ctz_i32 0 #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_extract_i32 1 #define TCG_TARGET_HAS_sextract_i32 1 @@ -125,6 +127,8 @@ extern bool have_bmi1; #define TCG_TARGET_HAS_eqv_i64 0 #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 0 +#define TCG_TARGET_HAS_ctz_i64 0 #define TCG_TARGET_HAS_deposit_i64 1 #define TCG_TARGET_HAS_extract_i64 1 #define TCG_TARGET_HAS_sextract_i64 0 diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 8856dc8..9a829ae 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -140,6 +140,10 @@ typedef enum { #define TCG_TARGET_HAS_nand_i32 1 #define TCG_TARGET_HAS_nand_i64 1 #define TCG_TARGET_HAS_nor_i32 1 +#define TCG_TARGET_HAS_clz_i32 0 +#define TCG_TARGET_HAS_clz_i64 0 +#define TCG_TARGET_HAS_ctz_i32 0 +#define TCG_TARGET_HAS_ctz_i64 0 #define TCG_TARGET_HAS_nor_i64 1 #define TCG_TARGET_HAS_orc_i32 1 #define TCG_TARGET_HAS_orc_i64 1 diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index f1c3137..f133684 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h
[Qemu-devel] [PATCH 11/65] tcg/s390: Implement field extraction opcodes
Signed-off-by: Richard Henderson --- tcg/s390/tcg-target.h | 4 ++-- tcg/s390/tcg-target.inc.c | 11 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index d650a72..e9ac12e 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -78,7 +78,7 @@ extern uint64_t s390_facilities; #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i320 #define TCG_TARGET_HAS_deposit_i32(s390_facilities & FACILITY_GEN_INST_EXT) -#define TCG_TARGET_HAS_extract_i320 +#define TCG_TARGET_HAS_extract_i32(s390_facilities & FACILITY_GEN_INST_EXT) #define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_movcond_i321 #define TCG_TARGET_HAS_add2_i32 1 @@ -109,7 +109,7 @@ extern uint64_t s390_facilities; #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i640 #define TCG_TARGET_HAS_deposit_i64(s390_facilities & FACILITY_GEN_INST_EXT) -#define TCG_TARGET_HAS_extract_i640 +#define TCG_TARGET_HAS_extract_i64(s390_facilities & FACILITY_GEN_INST_EXT) #define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_movcond_i641 #define TCG_TARGET_HAS_add2_i64 1 diff --git a/tcg/s390/tcg-target.inc.c b/tcg/s390/tcg-target.inc.c index 9f51133..083c992 100644 --- a/tcg/s390/tcg-target.inc.c +++ b/tcg/s390/tcg-target.inc.c @@ -1247,6 +1247,12 @@ static void tgen_deposit(TCGContext *s, TCGReg dest, TCGReg src, tcg_out_risbg(s, dest, src, msb, lsb, ofs, 0); } +static void tgen_extract(TCGContext *s, TCGReg dest, TCGReg src, + int ofs, int len) +{ +tcg_out_risbg(s, dest, src, 64 - len, 63, 64 - ofs, 1); +} + static void tgen_gotoi(TCGContext *s, int cc, tcg_insn_unit *dest) { ptrdiff_t off = dest - s->code_ptr; @@ -2153,6 +2159,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, OP_32_64(deposit): tgen_deposit(s, args[0], args[2], args[3], args[4]); break; +OP_32_64(extract): +tgen_extract(s, args[0], args[1], args[2], args[3]); +break; case INDEX_op_mb: /* The host memory model is quite strong, we simply need to @@ -,6 +2231,7 @@ static const TCGTargetOpDef s390_op_defs[] = { { INDEX_op_setcond_i32, { "r", "r", "rC" } }, { INDEX_op_movcond_i32, { "r", "r", "rC", "r", "0" } }, { INDEX_op_deposit_i32, { "r", "0", "r" } }, +{ INDEX_op_extract_i32, { "r", "r" } }, { INDEX_op_qemu_ld_i32, { "r", "L" } }, { INDEX_op_qemu_ld_i64, { "r", "L" } }, @@ -2283,6 +2293,7 @@ static const TCGTargetOpDef s390_op_defs[] = { { INDEX_op_setcond_i64, { "r", "r", "rC" } }, { INDEX_op_movcond_i64, { "r", "r", "rC", "r", "0" } }, { INDEX_op_deposit_i64, { "r", "0", "r" } }, +{ INDEX_op_extract_i64, { "r", "r" } }, { INDEX_op_mb, { } }, { -1 }, -- 2.9.3
[Qemu-devel] [PATCH 35/65] target-tricore: Use clz opcode
Tested-by: Bastian Koppelmann Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/tricore/helper.h| 2 -- target/tricore/op_helper.c | 10 -- target/tricore/translate.c | 5 +++-- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/target/tricore/helper.h b/target/tricore/helper.h index 9333e16..2cf04e1 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -87,9 +87,7 @@ DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(ixmin, TCG_CALL_NO_RWG_SE, i64, i64, i32) DEF_HELPER_FLAGS_2(ixmin_u, TCG_CALL_NO_RWG_SE, i64, i64, i32) /* count leading ... */ -DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_FLAGS_1(clo_h, TCG_CALL_NO_RWG_SE, i32, i32) -DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_FLAGS_1(clz_h, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_FLAGS_1(cls, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_FLAGS_1(cls_h, TCG_CALL_NO_RWG_SE, i32, i32) diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c index ac02e0a..3731d5e 100644 --- a/target/tricore/op_helper.c +++ b/target/tricore/op_helper.c @@ -1733,11 +1733,6 @@ EXTREMA_H_B(min, <) #undef EXTREMA_H_B -uint32_t helper_clo(target_ulong r1) -{ -return clo32(r1); -} - uint32_t helper_clo_h(target_ulong r1) { uint32_t ret_hw0 = extract32(r1, 0, 16); @@ -1756,11 +1751,6 @@ uint32_t helper_clo_h(target_ulong r1) return ret_hw0 | (ret_hw1 << 16); } -uint32_t helper_clz(target_ulong r1) -{ -return clz32(r1); -} - uint32_t helper_clz_h(target_ulong r1) { uint32_t ret_hw0 = extract32(r1, 0, 16); diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 36f734a..69cdfb9 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6367,7 +6367,8 @@ static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx) tcg_gen_andc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); break; case OPC2_32_RR_CLO: -gen_helper_clo(cpu_gpr_d[r3], cpu_gpr_d[r1]); +tcg_gen_not_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]); +tcg_gen_clzi_tl(cpu_gpr_d[r3], cpu_gpr_d[r3], TARGET_LONG_BITS); break; case OPC2_32_RR_CLO_H: gen_helper_clo_h(cpu_gpr_d[r3], cpu_gpr_d[r1]); @@ -6379,7 +6380,7 @@ static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx) gen_helper_cls_h(cpu_gpr_d[r3], cpu_gpr_d[r1]); break; case OPC2_32_RR_CLZ: -gen_helper_clz(cpu_gpr_d[r3], cpu_gpr_d[r1]); +tcg_gen_clzi_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], TARGET_LONG_BITS); break; case OPC2_32_RR_CLZ_H: gen_helper_clz_h(cpu_gpr_d[r3], cpu_gpr_d[r1]); -- 2.9.3
[Qemu-devel] [PATCH 42/65] tcg/arm: Handle ctz and clz opcodes
Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- tcg/arm/tcg-target.h | 4 ++-- tcg/arm/tcg-target.inc.c | 27 +++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 02cc242..4cb94dc 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -110,8 +110,8 @@ extern bool use_idiv_instructions; #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_clz_i32 0 -#define TCG_TARGET_HAS_ctz_i32 0 +#define TCG_TARGET_HAS_clz_i32 use_armv5t_instructions +#define TCG_TARGET_HAS_ctz_i32 use_armv7_instructions #define TCG_TARGET_HAS_deposit_i32 use_armv7_instructions #define TCG_TARGET_HAS_extract_i32 use_armv7_instructions #define TCG_TARGET_HAS_sextract_i32 use_armv7_instructions diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c index ec0b861..e75a6d4 100644 --- a/tcg/arm/tcg-target.inc.c +++ b/tcg/arm/tcg-target.inc.c @@ -256,6 +256,9 @@ typedef enum { ARITH_BIC = 0xe << 21, ARITH_MVN = 0xf << 21, +INSN_CLZ = 0x016f0f10, +INSN_RBIT = 0x06ff0f30, + INSN_LDR_IMM = 0x0410, INSN_LDR_REG = 0x0610, INSN_STR_IMM = 0x0400, @@ -1829,6 +1832,28 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; +case INDEX_op_ctz_i32: +tcg_out_dat_reg(s, COND_AL, INSN_RBIT, TCG_REG_TMP, 0, args[1], 0); +a1 = TCG_REG_TMP; +goto do_clz; + +case INDEX_op_clz_i32: +a1 = args[1]; +do_clz: +a0 = args[0]; +a2 = args[2]; +c = const_args[2]; +if (c && a2 == 32) { +tcg_out_dat_reg(s, COND_AL, INSN_CLZ, a0, 0, a1, 0); +break; +} +tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0, a1, 0); +tcg_out_dat_reg(s, COND_NE, INSN_CLZ, a0, 0, a1, 0); +if (c || a0 != a2) { +tcg_out_dat_rIK(s, COND_EQ, ARITH_MOV, ARITH_MVN, a0, 0, a2, c); +} +break; + case INDEX_op_brcond_i32: tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0, args[0], args[1], const_args[1]); @@ -1963,6 +1988,8 @@ static const TCGTargetOpDef arm_op_defs[] = { { INDEX_op_sar_i32, { "r", "r", "ri" } }, { INDEX_op_rotl_i32, { "r", "r", "ri" } }, { INDEX_op_rotr_i32, { "r", "r", "ri" } }, +{ INDEX_op_clz_i32, { "r", "r", "rIK" } }, +{ INDEX_op_ctz_i32, { "r", "r", "rIK" } }, { INDEX_op_brcond_i32, { "r", "rIN" } }, { INDEX_op_setcond_i32, { "r", "r", "rIN" } }, -- 2.9.3
[Qemu-devel] [PATCH 13/65] target-alpha: Use deposit and extract ops
Signed-off-by: Richard Henderson --- target/alpha/translate.c | 67 ++-- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 114927b..5ac2277 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -949,7 +949,13 @@ static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, uint8_t lit, uint8_t byte_mask) { if (islit) { -tcg_gen_shli_i64(vc, va, (64 - lit * 8) & 0x3f); +int pos = (64 - lit * 8) & 0x3f; +int len = cto32(byte_mask) * 8; +if (pos < len) { +tcg_gen_deposit_z_i64(vc, va, pos, len - pos); +} else { +tcg_gen_movi_i64(vc, 0); +} } else { TCGv tmp = tcg_temp_new(); tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3); @@ -966,38 +972,44 @@ static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, uint8_t lit, uint8_t byte_mask) { if (islit) { -tcg_gen_shri_i64(vc, va, (lit & 7) * 8); +int pos = (lit & 7) * 8; +int len = cto32(byte_mask) * 8; +if (pos + len >= 64) { +len = 64 - pos; +} +tcg_gen_extract_i64(vc, va, pos, len); } else { TCGv tmp = tcg_temp_new(); tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7); tcg_gen_shli_i64(tmp, tmp, 3); tcg_gen_shr_i64(vc, va, tmp); tcg_temp_free(tmp); +gen_zapnoti(vc, vc, byte_mask); } -gen_zapnoti(vc, vc, byte_mask); } /* INSWH, INSLH, INSQH */ static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, uint8_t lit, uint8_t byte_mask) { -TCGv tmp = tcg_temp_new(); - -/* The instruction description has us left-shift the byte mask and extract - bits <15:8> and apply that zap at the end. This is equivalent to simply - performing the zap first and shifting afterward. */ -gen_zapnoti(tmp, va, byte_mask); - if (islit) { -lit &= 7; -if (unlikely(lit == 0)) { -tcg_gen_movi_i64(vc, 0); +int pos = 64 - (lit & 7) * 8; +int len = cto32(byte_mask) * 8; +if (pos < len) { +tcg_gen_extract_i64(vc, va, pos, len - pos); } else { -tcg_gen_shri_i64(vc, tmp, 64 - lit * 8); +tcg_gen_movi_i64(vc, 0); } } else { +TCGv tmp = tcg_temp_new(); TCGv shift = tcg_temp_new(); +/* The instruction description has us left-shift the byte mask + and extract bits <15:8> and apply that zap at the end. This + is equivalent to simply performing the zap first and shifting + afterward. */ +gen_zapnoti(tmp, va, byte_mask); + /* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this portably by splitting the shift into two parts: shift_count-1 and 1. Arrange for the -1 by using ones-complement instead of @@ -1010,32 +1022,37 @@ static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, tcg_gen_shr_i64(vc, tmp, shift); tcg_gen_shri_i64(vc, vc, 1); tcg_temp_free(shift); +tcg_temp_free(tmp); } -tcg_temp_free(tmp); } /* INSBL, INSWL, INSLL, INSQL */ static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, uint8_t lit, uint8_t byte_mask) { -TCGv tmp = tcg_temp_new(); - -/* The instruction description has us left-shift the byte mask - the same number of byte slots as the data and apply the zap - at the end. This is equivalent to simply performing the zap - first and shifting afterward. */ -gen_zapnoti(tmp, va, byte_mask); - if (islit) { -tcg_gen_shli_i64(vc, tmp, (lit & 7) * 8); +int pos = (lit & 7) * 8; +int len = cto32(byte_mask) * 8; +if (pos + len > 64) { +len = 64 - pos; +} +tcg_gen_deposit_z_i64(vc, va, pos, len); } else { +TCGv tmp = tcg_temp_new(); TCGv shift = tcg_temp_new(); + +/* The instruction description has us left-shift the byte mask + and extract bits <15:8> and apply that zap at the end. This + is equivalent to simply performing the zap first and shifting + afterward. */ +gen_zapnoti(tmp, va, byte_mask); + tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7); tcg_gen_shli_i64(shift, shift, 3); tcg_gen_shl_i64(vc, tmp, shift); tcg_temp_free(shift); +tcg_temp_free(tmp); } -tcg_temp_free(tmp); } /* MSKWH, MSKLH, MSKQH */ -- 2.9.3
[Qemu-devel] [PATCH 30/65] target-mips: Use clz opcode
Cc: Yongbok Kim Signed-off-by: Richard Henderson --- target/mips/helper.h| 7 --- target/mips/op_helper.c | 22 -- target/mips/translate.c | 23 --- 3 files changed, 16 insertions(+), 36 deletions(-) diff --git a/target/mips/helper.h b/target/mips/helper.h index 666936c..60efa01 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -20,13 +20,6 @@ DEF_HELPER_4(scd, tl, env, tl, tl, int) #endif #endif -DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl) -#ifdef TARGET_MIPS64 -DEF_HELPER_FLAGS_1(dclo, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(dclz, TCG_CALL_NO_RWG_SE, tl, tl) -#endif - DEF_HELPER_3(muls, tl, env, tl, tl) DEF_HELPER_3(mulsu, tl, env, tl, tl) DEF_HELPER_3(macc, tl, env, tl, tl) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 7af4c2f..11d781f 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -103,28 +103,6 @@ HELPER_ST(sd, stq, uint64_t) #endif #undef HELPER_ST -target_ulong helper_clo (target_ulong arg1) -{ -return clo32(arg1); -} - -target_ulong helper_clz (target_ulong arg1) -{ -return clz32(arg1); -} - -#if defined(TARGET_MIPS64) -target_ulong helper_dclo (target_ulong arg1) -{ -return clo64(arg1); -} - -target_ulong helper_dclz (target_ulong arg1) -{ -return clz64(arg1); -} -#endif /* TARGET_MIPS64 */ - /* 64 bits arithmetic for 32 bits hosts */ static inline uint64_t get_HILO(CPUMIPSState *env) { diff --git a/target/mips/translate.c b/target/mips/translate.c index 8deffa1..7f8ecf4 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -3626,29 +3626,38 @@ static void gen_cl (DisasContext *ctx, uint32_t opc, /* Treat as NOP. */ return; } -t0 = tcg_temp_new(); +t0 = cpu_gpr[rd]; gen_load_gpr(t0, rs); + switch (opc) { case OPC_CLO: case R6_OPC_CLO: -gen_helper_clo(cpu_gpr[rd], t0); +#if defined(TARGET_MIPS64) +case OPC_DCLO: +case R6_OPC_DCLO: +#endif +tcg_gen_not_tl(t0, t0); break; +} + +switch (opc) { +case OPC_CLO: +case R6_OPC_CLO: case OPC_CLZ: case R6_OPC_CLZ: -gen_helper_clz(cpu_gpr[rd], t0); +tcg_gen_ext32u_tl(t0, t0); +tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS); +tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32); break; #if defined(TARGET_MIPS64) case OPC_DCLO: case R6_OPC_DCLO: -gen_helper_dclo(cpu_gpr[rd], t0); -break; case OPC_DCLZ: case R6_OPC_DCLZ: -gen_helper_dclz(cpu_gpr[rd], t0); +tcg_gen_clzi_i64(t0, t0, 64); break; #endif } -tcg_temp_free(t0); } /* Godson integer instructions */ -- 2.9.3
[Qemu-devel] [PATCH 43/65] tcg/mips: Handle clz opcode
Cc: Yongbok Kim Signed-off-by: Richard Henderson --- tcg/mips/tcg-target.h | 4 ++-- tcg/mips/tcg-target.inc.c | 34 ++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index f133684..0526018 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -109,8 +109,6 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_not_i32 1 #define TCG_TARGET_HAS_nor_i32 1 -#define TCG_TARGET_HAS_clz_i32 0 -#define TCG_TARGET_HAS_ctz_i32 0 #define TCG_TARGET_HAS_andc_i32 0 #define TCG_TARGET_HAS_orc_i32 0 #define TCG_TARGET_HAS_eqv_i32 0 @@ -130,6 +128,8 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_ext8s_i32use_mips32r2_instructions #define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_clz_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_ctz_i32 0 /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */ diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c index 4341ea2..732246a 100644 --- a/tcg/mips/tcg-target.inc.c +++ b/tcg/mips/tcg-target.inc.c @@ -160,6 +160,7 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type, #define TCG_CT_CONST_S16 0x400/* Signed 16-bit: -32768 - 32767 */ #define TCG_CT_CONST_P2M1 0x800/* Power of 2 minus 1. */ #define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */ +#define TCG_CT_CONST_WSZ 0x2000 /* word size */ static inline bool is_p2m1(tcg_target_long val) { @@ -215,6 +216,9 @@ static const char *target_parse_constraint(TCGArgConstraint *ct, case 'N': ct->ct |= TCG_CT_CONST_N16; break; +case 'W': +ct->ct |= TCG_CT_CONST_WSZ; +break; case 'Z': /* We are cheating a bit here, using the fact that the register ZERO is also the register number 0. Hence there is no need @@ -246,6 +250,8 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type, } else if ((ct & TCG_CT_CONST_P2M1) && use_mips32r2_instructions && is_p2m1(val)) { return 1; +} else if ((ct & TCG_CT_CONST_WSZ) && val == 32) { +return 1; } return 0; } @@ -313,6 +319,7 @@ typedef enum { OPC_SLTU = OPC_SPECIAL | 0x2B, OPC_SELEQZ = OPC_SPECIAL | 0x35, OPC_SELNEZ = OPC_SPECIAL | 0x37, +OPC_CLZ_R6 = OPC_SPECIAL | 0120, OPC_REGIMM = 0x01 << 26, OPC_BLTZ = OPC_REGIMM | (0x00 << 16), @@ -320,6 +327,7 @@ typedef enum { OPC_SPECIAL2 = 0x1c << 26, OPC_MUL_R5 = OPC_SPECIAL2 | 0x002, +OPC_CLZ = OPC_SPECIAL2 | 040, OPC_SPECIAL3 = 0x1f << 26, OPC_EXT = OPC_SPECIAL3 | 0x000, @@ -1625,6 +1633,31 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; +case INDEX_op_clz_i32: +if (use_mips32r6_instructions) { +if (a2 == 32) { +tcg_out_opc_reg(s, OPC_CLZ_R6, a0, a1, 0); +} else { +tcg_out_opc_reg(s, OPC_CLZ_R6, TCG_TMP0, a1, 0); +tcg_out_movcond(s, TCG_COND_EQ, a0, a1, 0, a2, TCG_TMP0); +} +} else { +if (a2 == 32) { +tcg_out_opc_reg(s, OPC_CLZ, a0, a1, a1); +} else if (a0 == a2) { +tcg_out_opc_reg(s, OPC_CLZ, TCG_TMP0, a1, a1); +tcg_out_opc_reg(s, OPC_MOVN, a0, TCG_TMP0, a1); +} else if (a0 != a1) { +tcg_out_opc_reg(s, OPC_CLZ, a0, a1, a1); +tcg_out_opc_reg(s, OPC_MOVZ, a0, a2, a1); +} else { +tcg_out_opc_reg(s, OPC_CLZ, TCG_TMP0, a1, a1); +tcg_out_opc_reg(s, OPC_MOVZ, TCG_TMP0, a2, a1); +tcg_out_mov(s, TCG_TYPE_REG, a0, TCG_TMP0); +} +} +break; + case INDEX_op_bswap32_i32: tcg_out_opc_reg(s, OPC_WSBH, a0, 0, a1); tcg_out_opc_sa(s, OPC_ROTR, a0, a0, 16); @@ -1727,6 +1760,7 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_sar_i32, { "r", "rZ", "ri" } }, { INDEX_op_rotr_i32, { "r", "rZ", "ri" } }, { INDEX_op_rotl_i32, { "r", "rZ", "ri" } }, +{ INDEX_op_clz_i32, { "r", "r", "rWZ" } }, { INDEX_op_bswap16_i32, { "r", "r" } }, { INDEX_op_bswap32_i32, { "r", "r" } }, -- 2.9.3
[Qemu-devel] [PATCH 14/65] target-arm: Use new deposit and extract ops
Use the new primitives for UBFX and SBFX. Cc: qemu-...@nongnu.org Signed-off-by: Richard Henderson --- target/arm/translate-a64.c | 81 +- target/arm/translate.c | 37 + 2 files changed, 37 insertions(+), 81 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 6dc27a6..5ba5c3e 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -3215,67 +3215,44 @@ static void disas_bitfield(DisasContext *s, uint32_t insn) low 32-bits anyway. */ tcg_tmp = read_cpu_reg(s, rn, 1); -/* Recognize the common aliases. */ -if (opc == 0) { /* SBFM */ -if (ri == 0) { -if (si == 7) { /* SXTB */ -tcg_gen_ext8s_i64(tcg_rd, tcg_tmp); -goto done; -} else if (si == 15) { /* SXTH */ -tcg_gen_ext16s_i64(tcg_rd, tcg_tmp); -goto done; -} else if (si == 31) { /* SXTW */ -tcg_gen_ext32s_i64(tcg_rd, tcg_tmp); -goto done; -} -} -if (si == 63 || (si == 31 && ri <= si)) { /* ASR */ -if (si == 31) { -tcg_gen_ext32s_i64(tcg_tmp, tcg_tmp); -} -tcg_gen_sari_i64(tcg_rd, tcg_tmp, ri); +/* Recognize simple(r) extractions. */ +if (si <= ri) { +/* Wd = Wn */ +len = (si - ri) + 1; +if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */ +tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len); goto done; -} -} else if (opc == 2) { /* UBFM */ -if (ri == 0) { /* UXTB, UXTH, plus non-canonical AND */ -tcg_gen_andi_i64(tcg_rd, tcg_tmp, bitmask64(si + 1)); +} else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */ +tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len); return; } -if (si == 63 || (si == 31 && ri <= si)) { /* LSR */ -if (si == 31) { -tcg_gen_ext32u_i64(tcg_tmp, tcg_tmp); -} -tcg_gen_shri_i64(tcg_rd, tcg_tmp, ri); -return; -} -if (si + 1 == ri && si != bitsize - 1) { /* LSL */ -int shift = bitsize - 1 - si; -tcg_gen_shli_i64(tcg_rd, tcg_tmp, shift); -goto done; -} -} - -if (opc != 1) { /* SBFM or UBFM */ -tcg_gen_movi_i64(tcg_rd, 0); -} - -/* do the bit move operation */ -if (si >= ri) { -/* Wd = Wn */ -tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri); +/* opc == 1, BXFIL fall through to deposit */ +tcg_gen_extract_i64(tcg_tmp, tcg_tmp, ri, len); pos = 0; -len = (si - ri) + 1; } else { -/* Wd<32+s-r,32-r> = Wn */ -pos = bitsize - ri; +/* Handle the ri > si case with a deposit + * Wd<32+s-r,32-r> = Wn + */ len = si + 1; +pos = (bitsize - ri) & (bitsize - 1); } -tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len); +if (opc == 0 && len < ri) { +/* SBFM: sign extend the destination field from len to fill + the balance of the word. Let the deposit below insert all + of those sign bits. */ +tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len); +len = ri; +} -if (opc == 0) { /* SBFM - sign extend the destination field */ -tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len)); -tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len)); +if (opc == 1) { /* BFM, BXFIL */ +tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len); +} else { +/* SBFM or UBFM: We start with zero, and we haven't modified + any bits outside bitsize, therefore the zero-extension + below is unneeded. */ +tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len); +return; } done: diff --git a/target/arm/translate.c b/target/arm/translate.c index 0ad9070..08da9ac 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -288,29 +288,6 @@ static void gen_revsh(TCGv_i32 var) tcg_gen_ext16s_i32(var, var); } -/* Unsigned bitfield extract. */ -static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask) -{ -if (shift) -tcg_gen_shri_i32(var, var, shift); -tcg_gen_andi_i32(var, var, mask); -} - -/* Signed bitfield extract. */ -static void gen_sbfx(TCGv_i32 var, int shift, int width) -{ -uint32_t signbit; - -if (shift) -tcg_gen_sari_i32(var, var, shift); -if (shift + width < 32) { -signbit = 1u << (width - 1); -tcg_gen_andi_i32(var, var, (1u << width) - 1); -tcg_gen_xori_i32(var, var, signbit); -tcg_gen_subi_i32(var, var, signbit); -} -} - /* Return (b << 32) + a. Mark inputs as dead */ static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b) { @@ -9178,9 +9155,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)