Re: [Qemu-devel] [RFC] q35/mch: implement extended TSEG sizes
Hi, Patch looks sane overall. > Invent a new, QEMU-specific register in the config space of the DRAM > Controller, at offset 0x50, in order to allow guest firmware to query > the > TSEG (SMRAM) size. Hmm, 0x50 appears to be the only unused config space register in the specs. I suspect in reality it isn't unused but undocumented. I don't have a better idea though, and in practice it probably isn't much of a problem. cheers, Gerd
Re: [Qemu-devel] [PATCH 0/3] ppc: fix memory leaks
On Wed, 7 Jun 2017 09:45:06 +1000 David Gibsonwrote: > On Tue, Jun 06, 2017 at 05:22:42PM +0200, Greg Kurz wrote: > > Coverity just reported a memory leak introduced by this commit (QEMU 2.9): > > > > commit df58713396f8b2deb923e39c00b10744c5c63909 > > Author: Thomas Huth > > Date: Wed Feb 15 10:21:44 2017 +0100 > > > > hw/ppc/spapr: Check for valid page size when hot plugging memory > > > > It boils down to the fact that object_property_get_str() returns a string > > allocated with g_strdup(), which must be deallocated with g_free() at some > > point. > > Applied to ppc-for-2.10. Do we need to queue this for 2.9 stable as > well? > Yes. pgp1mba0QVHWh.pgp Description: OpenPGP digital signature
Re: [Qemu-devel] [PATCH v3 5/7] pci: Make errp the last parameter of pci_add_capability()
Hi, Eduardo On 06/06/2017 10:52 PM, Eduardo Habkost wrote: On Tue, Jun 06, 2017 at 07:26:30PM +0800, Mao Zhongyi wrote: Add Error argument for pci_add_capability() to leverage the errp to pass info on errors. This way is helpful for its callers to make a better error handling when moving to 'realize'. Cc: pbonz...@redhat.com Cc: r...@twiddle.net Cc: ehabk...@redhat.com Cc: m...@redhat.com CC: dmi...@daynix.com Cc: jasow...@redhat.com Cc: mar...@redhat.com Cc: alex.william...@redhat.com Cc: arm...@redhat.com Signed-off-by: Mao Zhongyi--- [...] There are multiple places below that checks for errors like this: function(...); if (function succeeded) { /* non-error code path here */ foo = bar; } Sometimes it even includes another branch for the error path: function(...); if (function succeeded) { /* non-error code path here */ foo = bar; } else { /* error path here */ return ret; } I suggest doing this instead, for readability: function(...) if (function failed) { return ...; /* or: "goto out" */ } /* non-error code path here */ foo = bar; Thank you very much for the detailed explanation,will use this more elegant way to check return value in next version. :) [...] static int e1000e_add_pm_capability(PCIDevice *pdev, uint8_t offset, uint16_t pmc) { -int ret = pci_add_capability(pdev, PCI_CAP_ID_PM, offset, PCI_PM_SIZEOF); +Error *local_err = NULL; +int ret = pci_add_capability(pdev, PCI_CAP_ID_PM, offset, + PCI_PM_SIZEOF, _err); if (ret > 0) { pci_set_word(pdev->config + offset + PCI_PM_PMC, @@ -386,6 +389,8 @@ e1000e_add_pm_capability(PCIDevice *pdev, uint8_t offset, uint16_t pmc) pci_set_word(pdev->w1cmask + offset + PCI_PM_CTRL, PCI_PM_CTRL_PME_STATUS); +} else { +error_report_err(local_err); } I suggest this instead: int ret = pci_add_capability(pdev, PCI_CAP_ID_PM, offset, PCI_PM_SIZEOF, _err); if (local_err) { error_report_err(local_err); return ret; } pci_set_word(...); pci_set_word(...); pci_set_word(...); return ret; OK, I see. /*/ diff --git a/hw/pci/pci.c b/hw/pci/pci.c index b73bfea..2bba37a 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2264,15 +2264,13 @@ static void pci_del_option_rom(PCIDevice *pdev) * in pci config space */ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, - uint8_t offset, uint8_t size) + uint8_t offset, uint8_t size, + Error **errp) { int ret; -Error *local_err = NULL; -ret = pci_add_capability2(pdev, cap_id, offset, size, _err); -if (ret < 0) { -error_report_err(local_err); -} +ret = pci_add_capability2(pdev, cap_id, offset, size, errp); + return ret; } pci_add_capability() and pci_add_capability2() now do exactly the same, why are both being kept? I suggest replacing pci_add_capability2() with pci_add_capability() everywhere (on a separate patch). Completely remove pci_add_capability and direct use pci_add_capability2() everywhere is it a more thorough way? Thanks Mao
[Qemu-devel] [PATCH] Remove restriction that prevents bootimg elf64 images
It is possible to create a 64 bit elf image that has valid multiboot header. qemu should be able to boot such images. Tested with homemade 64bit OS - now it boots fine with 'qemu -kernel' and as a grub image. Signed-off-by: Anatol Pomozov--- hw/i386/multiboot.c | 5 - 1 file changed, 5 deletions(-) diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c index 663f35a658..cf1b4f5fb3 100644 --- a/hw/i386/multiboot.c +++ b/hw/i386/multiboot.c @@ -192,11 +192,6 @@ int load_multiboot(FWCfgState *fw_cfg, int kernel_size; fclose(f); -if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) { -fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n"); -exit(1); -} - kernel_size = load_elf(kernel_filename, NULL, NULL, _entry, _low, _high, 0, I386_ELF_MACHINE, 0, 0); -- 2.13.1
[Qemu-devel] [Bug 1031955] Re: qemu-system-arm -M lm3s811evb fails
[Expired for QEMU because there has been no activity for 60 days.] ** Changed in: qemu Status: Incomplete => Expired -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1031955 Title: qemu-system-arm -M lm3s811evb fails Status in QEMU: Expired Bug description: I am trying out examples from StellarisWare. When I try the uart_echo example, that initially tries to talk to the display, I get this: $ .../qemu-1.1.1/bin/qemu-system-arm -M lm3s811evb -kernel uart_echo/gcc/uart_echo.bin qemu: hardware error: strllaris_i2c_read: Bad offset 0xfc0 CPU #0: R00=0001 R01=005b8d80 R02=00061a80 R03=007a11ff R04=4002 R05=005b8d80 R06=0002 R07= R08= R09= R10= R11= R12= R13=20d4 R14=0995 R15=09cc PSR=2173 --C- T svc32 Aborted The example is located in boards/ek-lm3s811/uart_echo in the StellarisWare distribution. With the latest from git: $ .../qemu-git/qemu/bin/qemu-system-arm -M lm3s811evb -kernel uart_echo/gcc/uart_echo.bin qemu-system-arm: hw/qdev.c:310: qdev_get_gpio_in: Assertion `n >= 0 && n < dev->num_gpio_in' failed. This however seems to be reported already (Bug #1028260). Both versions compiled from sources: ./configure --target-list=arm-linux-user,arm-softmmu,armeb-linux- user --enable-sdl --prefix=/path/to/... Running Ubunti 10.04 with Linux 2.6.32-40-generic-pae. /Lars To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1031955/+subscriptions
Re: [Qemu-devel] [PULL 0/2] Net patches
Hi, This series seems to have some coding style problems. See output below for more information: Type: series Subject: [Qemu-devel] [PULL 0/2] Net patches Message-id: 1496806444-27910-1-git-send-email-jasow...@redhat.com === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 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 Switched to a new branch 'test' a0be159 Revert "Change net/socket.c to use socket_*() functions" again 0e3dcc6 net/rocker: Cleanup the useless return value check === OUTPUT BEGIN === Checking PATCH 1/2: net/rocker: Cleanup the useless return value check... Checking PATCH 2/2: Revert "Change net/socket.c to use socket_*() functions" again... ERROR: braces {} are necessary for all arms of this statement #58: FILE: net/socket.c:495: +if (parse_host_port(, host_str) < 0) [...] ERROR: braces {} are necessary for all arms of this statement #161: FILE: net/socket.c:540: +if (parse_host_port(, host_str) < 0) [...] ERROR: space required before the open parenthesis '(' #174: FILE: net/socket.c:551: +for(;;) { ERROR: braces {} are necessary for all arms of this statement #194: FILE: net/socket.c:571: +if (!s) [...] total: 4 errors, 0 warnings, 162 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] [Bug 1077708] Re: Video capture from webcam with USB passthrough freezes
[Expired for QEMU because there has been no activity for 60 days.] ** Changed in: qemu Status: Incomplete => Expired -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1077708 Title: Video capture from webcam with USB passthrough freezes Status in QEMU: Expired Bug description: QEMU version: 1.2.0 Graphics: Spice Guest: Windows 7 32-bit Host: Ubuntu 12.10 amd64 (using distro package qemu-kvm-spice) I am using USB 2.0 passthrough of a Logitech C920 webcam. The guest is running the proprietary Logitech drivers. When video chatting with either Google+ Hangouts or Skype 3.8.0.115, video capture from the webcam is initially fine but eventually freezes. It remains frozen for up to several minutes and then resumes on its own. The process then repeats. Audio recorded from the webcam's mic works continuously. The problem also affects video recording in Logitech's bundled software. Strangely though, the live preview is _not_ affected. The freezing is only present in the recorded video file. I can tell that the problem is not introduced by Spice during playback, because the user on the other end of Hangouts/Skype sees the same problem, and the freezes in a recorded video file are seen at the same point every time the file is played. Command line: /usr/bin/kvm-spice -name Windows7 -S -M pc-1.0 -enable-kvm -m 2048 -smp 3,sockets=3,cores=1,threads=1 -uuid cfcc7e85-7873-1c32-0a00-d1c35f3eb073 -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/Windows7.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=localtime -no-shutdown -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x6.0x7 -device ich9-usb- uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x6 -device ich9-usb- uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x6.0x1 -device ich9 -usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x6.0x2 -drive file=/data/libvirt/images/Windows7.img,if=none,id=drive- ide0-0-0,format=raw -device ide-hd,bus=ide.0,unit=0,drive=drive- ide0-0-0,id=ide0-0-0,bootindex=1 -drive if=none,id=drive- ide0-1-0,readonly=on,format=raw -device ide-cd,bus=ide.1,unit=0,drive =drive-ide0-1-0,id=ide0-1-0 -netdev tap,fd=21,id=hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:7e:0b:d9,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa- serial,chardev=charserial0,id=serial0 -device usb-tablet,id=input0 -spice port=5900,addr=127.0.0.1,disable-ticketing -vga std -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda- duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device usb- host,hostbus=2,hostaddr=8,id=hostdev0 -device virtio-balloon- pci,id=balloon0,bus=pci.0,addr=0x5 To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1077708/+subscriptions
[Qemu-devel] [Bug 1089005] Re: Qemu does not shutdown with vnc enabled on OS X
[Expired for QEMU because there has been no activity for 60 days.] ** Changed in: qemu Status: Incomplete => Expired -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1089005 Title: Qemu does not shutdown with vnc enabled on OS X Status in QEMU: Expired Bug description: I am running OS X 10.8.2 and Qemu 1.3.50 from your git repository. Running qemu-system-i386 works fine. I can quit the process using ctrl-c. When I try to use qemu-system-i386 -vnc : ctrl-c does nothing and I have to kill the process trough the activity monitor. Furthermore terminating the process from my java program does not work either. I have also posted a question on Stackoverflow: http://stackoverflow.com/questions/13798367/qemu-does-not-shutdown-with-vnc-enabled-on-os-x Thanks Leander To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1089005/+subscriptions
[Qemu-devel] [Bug 1078892] Re: qemu doesn't general protection fault if there are reserved bits set in page-directory-pointer table entries
[Expired for QEMU because there has been no activity for 60 days.] ** Changed in: qemu Status: Incomplete => Expired -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1078892 Title: qemu doesn't general protection fault if there are reserved bits set in page-directory-pointer table entries Status in QEMU: Expired Bug description: While working on implementing 32-bit PAE mode in a custom operating system, which I was testing in QEMU, I noticed that my OS worked correctly, but resulted in a general protection fault when booted on VMware, VirtualBox, or bochs. According to the Intel Architecture Manual, Volume 3A, Section 4.4.1 "PDPTE Registers", "If any of the PDPTEs sets both the P flag (bit 0) and any reserved bit, the MOV to CR instruction causes a general- protection exception (#GP(0)) and the PDPTEs are not loaded." QEMU does not emulate this behavior. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1078892/+subscriptions
[Qemu-devel] [Bug 1073952] Re: data sent to serial interface gets truncated after 64kb
[Expired for QEMU because there has been no activity for 60 days.] ** Changed in: qemu Status: Incomplete => Expired -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1073952 Title: data sent to serial interface gets truncated after 64kb Status in QEMU: Expired Bug description: When sending more than 64kb of data to the serial interface in a short timespan, the data seems to disappear. I tested it with the latest release (qemu-kvm-1.2.0-rc2.tar.gz) where the bug still occurs. I stumbled upon it when I upraged my qemu version. The bug did not occur in the last version i had (0.12.5). You can reproduce it as follows: 1. Start a dd or cat command in one terminal and pipe the output to a netcat. The testfile has to be larger than 64kb. I used one that had 93kb and did contain only ascii text. $ dd if= | nc -l 127.0.0.1 65432 or $ cat | nc -l 127.0.0.1 65432 2. Start a qemu and let the first serial port connect to the listening netcat. I suppose that the testsystem can be any system that does not read from the serial port on its own (e.g. during boot process). I used a self compiled minimal linux. $ qemu -cdrom -serial tcp:127.0.0.1:65432 3. When the testsystem is booted, read from the serial device and write it to a file. $ dd if=/dev/ttyS0 of=/tmp/testFile or $ cat /dev/ttyS0 > /tmp/testFile The result in almost all of my testruns is, that the /tmp/testFile does only has the size of 64kb. The rest of the data vanished. In some cases the file was slightly bigger (65kb or 67kb) but allways under 70kb. The complete file (93kb) was not trasmitted in any of the runs. I hope my explanation is exactly enough for you to reproduce it. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1073952/+subscriptions
Re: [Qemu-devel] [PATCH 2/3] exec: simplify address_space_get_iotlb_entry
On Wed, Jun 07, 2017 at 09:47:05AM +1000, David Gibson wrote: > On Tue, Jun 06, 2017 at 04:34:30PM +0200, Paolo Bonzini wrote: > > > > > > On 05/06/2017 05:07, Peter Xu wrote: > > > I don't sure whether it'll be a good interface for IOTLB. AFAIU at > > > least for VT-d, the IOMMU translation is page aligned which is defined > > > by spec, so it makes sense that (again at least for VT-d) here we'd > > > better just use page_mask/addr_mask. > > > > > > That's also how I know about IOMMU in general - I assume it do the > > > translations always with page masks (never arbitary length), though > > > page size can differ from platfrom to platform, that's why here the > > > IOTLB interface used addr_mask, then it works for all platforms. I > > > don't know whether I'm 100% correct here though. > > > > > > Maybe David/Paolo/... would comment as well? > > > > I would ask David. There are PowerPC MMUs that allow fast lookup of > > arbitrarily-sized windows (not necessarily power of two), > > Uh.. I'm not sure what you mean here. You might be thinking of the > BATs which really old (32-bit) PowerPC MMUs had - those allow > arbitrary large block translations, but they do have to be a power of > two. > > > so maybe the > > IOMMUs can do the same. > > The only Power IOMMU I know about uses a fixed, power-of-two page size > per DMA window. If so, I would still be inclined to keep using masks for QEMU IOTLB. Then, my first two patches should still stand. I am just afraid that not using masks will diverge the emulation from real hardware and brings trouble one day. For vhost IOTLB interface, it does not need to be strictly aligned to QEMU IOMMU IOTLB definition, and that's how it's working now (current vhost iotlb allows arbitary length, and I think it's good). So imho we don't really need to worry about the performance - after all, we can do everything customized for vhost, just like what patch 3 did (yeah, it can be better...). Thanks, -- Peter Xu
[Qemu-devel] [PULL 1/2] net/rocker: Cleanup the useless return value check
From: Mao ZhongyiNone of pci_dma_read()'s callers check the return value except rocker. There is no need to check it because it always return 0. So the check work is useless. Remove it entirely. Suggested-by: Markus Armbruster Signed-off-by: Mao Zhongyi Signed-off-by: Jason Wang --- hw/net/rocker/rocker.c | 9 +++-- hw/net/rocker/rocker_desc.c | 4 +--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index 6e70fdd..4f0f6d7 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -244,11 +244,9 @@ static int tx_consume(Rocker *r, DescInfo *info) goto err_no_mem; } -if (pci_dma_read(dev, frag_addr, iov[iovcnt].iov_base, - iov[iovcnt].iov_len)) { -err = -ROCKER_ENXIO; -goto err_bad_io; -} +pci_dma_read(dev, frag_addr, iov[iovcnt].iov_base, + iov[iovcnt].iov_len); + iovcnt++; } @@ -261,7 +259,6 @@ static int tx_consume(Rocker *r, DescInfo *info) err = fp_port_eg(r->fp_port[port], iov, iovcnt); err_too_many_frags: -err_bad_io: err_no_mem: err_bad_attr: for (i = 0; i < ROCKER_TX_FRAGS_MAX; i++) { diff --git a/hw/net/rocker/rocker_desc.c b/hw/net/rocker/rocker_desc.c index ac02797..6184c40 100644 --- a/hw/net/rocker/rocker_desc.c +++ b/hw/net/rocker/rocker_desc.c @@ -69,9 +69,7 @@ char *desc_get_buf(DescInfo *info, bool read_only) return NULL; } -if (pci_dma_read(dev, le64_to_cpu(info->desc.buf_addr), info->buf, size)) { -return NULL; -} +pci_dma_read(dev, le64_to_cpu(info->desc.buf_addr), info->buf, size); return info->buf; } -- 2.7.4
[Qemu-devel] [PULL 2/2] Revert "Change net/socket.c to use socket_*() functions" again
From: "Daniel P. Berrange"This reverts commit 883e4f7624e10b98d16d9adaffb8b1795664d899. This code changed net/socket.c from using socket()+connect(), to using socket_connect(). In theory this is great, but in practice this has completely broken the ability to connect the frontend and backend: $ ./x86_64-softmmu/qemu-system-x86_64 \ -device e1000,id=e0,netdev=hn0,mac=DE:AD:BE:EF:AF:05 \ -netdev socket,id=hn0,connect=localhost:1234 qemu-system-x86_64: -device e1000,id=e0,netdev=hn0,mac=DE:AD:BE:EF:AF:05: Property 'e1000.netdev' can't find value 'hn0' The old code would call net_socket_fd_init() synchronously, while letting the connect() complete in the backgorund. The new code moved net_socket_fd_init() so that it is only called after connect() completes in the background. Thus at the time we initialize the NIC frontend, the backend does not exist. The socket_connect() conversion as done is a bad fit for the current code, since it did not try to change the way it deals with async connection completion. Rather than try to fix this, just revert the socket_connect() conversion entirely. The code is about to be converted to use QIOChannel which will let the problem be solved in a cleaner manner. This revert is more suitable for stable branches in the meantime. Signed-off-by: Daniel P. Berrange Reviewed-by: Stefan Hajnoczi Signed-off-by: Jason Wang --- net/socket.c | 127 ++- 1 file changed, 56 insertions(+), 71 deletions(-) diff --git a/net/socket.c b/net/socket.c index b8c931e..dcae1ae 100644 --- a/net/socket.c +++ b/net/socket.c @@ -489,106 +489,91 @@ static int net_socket_listen_init(NetClientState *peer, { NetClientState *nc; NetSocketState *s; -SocketAddress *saddr; -int ret; -Error *local_error = NULL; +struct sockaddr_in saddr; +int fd, ret; -saddr = socket_parse(host_str, _error); -if (saddr == NULL) { -error_report_err(local_error); +if (parse_host_port(, host_str) < 0) +return -1; + +fd = qemu_socket(PF_INET, SOCK_STREAM, 0); +if (fd < 0) { +perror("socket"); return -1; } +qemu_set_nonblock(fd); + +socket_set_fast_reuse(fd); -ret = socket_listen(saddr, _error); +ret = bind(fd, (struct sockaddr *), sizeof(saddr)); if (ret < 0) { -qapi_free_SocketAddress(saddr); -error_report_err(local_error); +perror("bind"); +closesocket(fd); +return -1; +} +ret = listen(fd, 0); +if (ret < 0) { +perror("listen"); +closesocket(fd); return -1; } nc = qemu_new_net_client(_socket_info, peer, model, name); s = DO_UPCAST(NetSocketState, nc, nc); s->fd = -1; -s->listen_fd = ret; +s->listen_fd = fd; s->nc.link_down = true; net_socket_rs_init(>rs, net_socket_rs_finalize); qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); -qapi_free_SocketAddress(saddr); return 0; } -typedef struct { -NetClientState *peer; -SocketAddress *saddr; -char *model; -char *name; -} socket_connect_data; - -static void socket_connect_data_free(socket_connect_data *c) -{ -qapi_free_SocketAddress(c->saddr); -g_free(c->model); -g_free(c->name); -g_free(c); -} - -static void net_socket_connected(int fd, Error *err, void *opaque) -{ -socket_connect_data *c = opaque; -NetSocketState *s; -char *addr_str = NULL; -Error *local_error = NULL; - -addr_str = socket_address_to_string(c->saddr, _error); -if (addr_str == NULL) { -error_report_err(local_error); -closesocket(fd); -goto end; -} - -s = net_socket_fd_init(c->peer, c->model, c->name, fd, true); -if (!s) { -closesocket(fd); -goto end; -} - -snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "socket: connect to %s", addr_str); - -end: -g_free(addr_str); -socket_connect_data_free(c); -} - static int net_socket_connect_init(NetClientState *peer, const char *model, const char *name, const char *host_str) { -socket_connect_data *c = g_new0(socket_connect_data, 1); -int fd = -1; -Error *local_error = NULL; +NetSocketState *s; +int fd, connected, ret; +struct sockaddr_in saddr; -c->peer = peer; -c->model = g_strdup(model); -c->name = g_strdup(name); -c->saddr = socket_parse(host_str, _error); -if (c->saddr == NULL) { -goto err; -} +if (parse_host_port(, host_str) < 0) +return -1; -fd = socket_connect(c->saddr, net_socket_connected, c, _error); +fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { -goto err; +perror("socket"); +return
[Qemu-devel] [PULL 0/2] Net patches
The following changes since commit 199e19ee538eb61fd08b1c1ee5aa838ebdcc968e: Merge remote-tracking branch 'remotes/mjt/tags/trivial-patches-fetch' into staging (2017-06-05 15:28:12 +0100) are available in the git repository at: https://github.com/jasowang/qemu.git tags/net-pull-request for you to fetch changes up to 6701e5514beab7b781a10424a94e9850c707287c: Revert "Change net/socket.c to use socket_*() functions" again (2017-06-07 10:58:31 +0800) Daniel P. Berrange (1): Revert "Change net/socket.c to use socket_*() functions" again Mao Zhongyi (1): net/rocker: Cleanup the useless return value check hw/net/rocker/rocker.c | 9 ++-- hw/net/rocker/rocker_desc.c | 4 +- net/socket.c| 127 +++- 3 files changed, 60 insertions(+), 80 deletions(-)
Re: [Qemu-devel] [PATCH v2 1/1] qemu/migration: fix the double free problem on from_src_file
On Tue, Jun 06, 2017 at 06:42:18PM +0100, Dr. David Alan Gilbert wrote: > * Kevin Wolf (kw...@redhat.com) wrote: > > Am 06.06.2017 um 07:24 hat QingFeng Hao geschrieben: > > > In load_snapshot, mis->from_src_file is freed twice, the first free is by > > > qemu_fclose, the second is by migration_incoming_state_destroy and > > > it causes Illegal instruction exception. The fix is just to remove the > > > first free. > > > > > > This problem is found by qemu-iotests case 068 since commit > > > "660819b migration: shut src return path unconditionally". The error is: > > > 068 1s ... - output mismatch (see 068.out.bad) > > > --- tests/qemu-iotests/068.out2017-05-06 01:00:26.417270437 > > > +0200 > > > +++ 068.out.bad 2017-06-03 13:59:55.360274640 +0200 > > > @@ -6,6 +6,8 @@ > > > QEMU X.Y.Z monitor - type 'help' for more information > > > (qemu) savevm 0 > > > (qemu) quit > > > +./common.config: line 107: 242472 Illegal instruction (core > > > dumped) ( if [ -n "${QEMU_NEED_PID}" ]; then > > > +echo $BASHPID > "${QEMU_TEST_DIR}/qemu-${_QEMU_HANDLE}.pid"; > > > +fi; exec "$QEMU_PROG" $QEMU_OPTIONS "$@" ) > > > QEMU X.Y.Z monitor - type 'help' for more information > > > -(qemu) quit > > > -*** done > > > +(qemu) *** done > > > > > > Signed-off-by: QingFeng Hao> > > Reviewed-by: Dr. David Alan Gilbert > > > Reviewed-by: Peter Xu > > > > Dave, as you only gave R-b rather than merging the patch, should this be > > merged through the block tree? > > I'm happy for it to go via block but also happy for it to go via > migration; Juan is mostly doing the migration set at the moment since > they're dominated by his cleanups. > > > > diff --git a/migration/savevm.c b/migration/savevm.c > > > index 9c320f59d0..853e14e34e 100644 > > > --- a/migration/savevm.c > > > +++ b/migration/savevm.c > > > @@ -2290,7 +2290,6 @@ int load_snapshot(const char *name, Error **errp) > > > > > > aio_context_acquire(aio_context); > > > ret = qemu_loadvm_state(f); > > > -qemu_fclose(f); > > > aio_context_release(aio_context); > > > > > > migration_incoming_state_destroy(); > > > > Did we check other callers of migration_incoming_state_destroy()? > > > > For example, qmp_xen_load_devices_state() looks suspicious, too. > > Hmm, it looks suspicious in the opposite direction; it never sets > mis->from_src_file as was added by b4b076da into the load_snapshot path. Agree. Does qmp_xen_load_devices_state() needs to call migration_incoming_state_destroy() after all? Since the latter function only cleanups MigrationIncomingState and looks like the former xen code didn't really use it at all. > > > I can't tell for postcopy_ram_listen_thread() - commit 660819b didn't > > seem to remove a qemu_fclose() call there, but I can't see one left > > behind either. Was the file leaked before commit 660819b or am I > > missing something? > > I don't think there's a problem in the postcopy path, although hmm was > I missing a close before? > > Dave > > > > Kevin > -- > Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK -- Peter Xu
[Qemu-devel] [PATCHv2 7/7] spapr: Rework DRC name handling
DRC objects have a get_name method which returns the DRC name generated when the DRC is created. Replace that with a fixed spapr_drc_name() function which generates the name on the fly from other information. This means: * We get rid of a method with only one implementation, and only local callers * We don't have to carry the name string around for the lifetime of the DRC * We use information added to the class structure to generate the name in standard format, so we don't need an explicit switch on drc type any more We also eliminate the 'name' property; it's basically useless since the only information in it can easily be deduced from other things. Signed-off-by: David Gibson--- hw/ppc/spapr_drc.c | 80 +- include/hw/ppc/spapr_drc.h | 3 +- 2 files changed, 30 insertions(+), 53 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 82c0b94..15ef67d 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -155,9 +155,32 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, return RTAS_OUT_SUCCESS; } -static const char *get_name(sPAPRDRConnector *drc) +static const char *spapr_drc_name(sPAPRDRConnector *drc) { -return drc->name; +sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + +/* human-readable name for a DRC to encode into the DT + * description. this is mainly only used within a guest in place + * of the unique DRC index. + * + * in the case of VIO/PCI devices, it corresponds to a "location + * code" that maps a logical device/function (DRC index) to a + * physical (or virtual in the case of VIO) location in the system + * by chaining together the "location label" for each + * encapsulating component. + * + * since this is more to do with diagnosing physical hardware + * issues than guest compatibility, we choose location codes/DRC + * names that adhere to the documented format, but avoid encoding + * the entire topology information into the label/code, instead + * just using the location codes based on the labels for the + * endpoints (VIO/PCI adaptor connectors), which is basically just + * "C" followed by an integer ID. + * + * DRC names as documented by PAPR+ v2.7, 13.5.2.4 + * location codes as documented by PAPR+ v2.7, 12.3.1.5 + */ +return g_strdup_printf("%s%d", drck->drc_name_prefix, drc->id); } /* has the guest been notified of device attachment? */ @@ -202,13 +225,6 @@ static void prop_get_index(Object *obj, Visitor *v, const char *name, visit_type_uint32(v, name, , errp); } -static char *prop_get_name(Object *obj, Error **errp) -{ -sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj); -sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); -return g_strdup(drck->get_name(drc)); -} - static void prop_get_fdt(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -567,45 +583,6 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type, object_property_set_bool(OBJECT(drc), true, "realized", NULL); g_free(prop_name); -/* human-readable name for a DRC to encode into the DT - * description. this is mainly only used within a guest in place - * of the unique DRC index. - * - * in the case of VIO/PCI devices, it corresponds to a - * "location code" that maps a logical device/function (DRC index) - * to a physical (or virtual in the case of VIO) location in the - * system by chaining together the "location label" for each - * encapsulating component. - * - * since this is more to do with diagnosing physical hardware - * issues than guest compatibility, we choose location codes/DRC - * names that adhere to the documented format, but avoid encoding - * the entire topology information into the label/code, instead - * just using the location codes based on the labels for the - * endpoints (VIO/PCI adaptor connectors), which is basically - * just "C" followed by an integer ID. - * - * DRC names as documented by PAPR+ v2.7, 13.5.2.4 - * location codes as documented by PAPR+ v2.7, 12.3.1.5 - */ -switch (spapr_drc_type(drc)) { -case SPAPR_DR_CONNECTOR_TYPE_CPU: -drc->name = g_strdup_printf("CPU %d", id); -break; -case SPAPR_DR_CONNECTOR_TYPE_PHB: -drc->name = g_strdup_printf("PHB %d", id); -break; -case SPAPR_DR_CONNECTOR_TYPE_VIO: -case SPAPR_DR_CONNECTOR_TYPE_PCI: -drc->name = g_strdup_printf("C%d", id); -break; -case SPAPR_DR_CONNECTOR_TYPE_LMB: -drc->name = g_strdup_printf("LMB %d", id); -break; -default: -g_assert(false); -} - /* PCI slot always start in a USABLE state, and stay there */ if (spapr_drc_type(drc) ==
[Qemu-devel] [PATCHv2 5/7] spapr: Change DRC attach & detach methods to functions
DRC objects have attach & detach methods, but there's only one implementation. Although there are some differences in its behaviour for different DRC types, the overall structure is the same, so while we might want different method implementations for some parts, we're unlikely to want them for the top-level functions. So, replace them with direct function calls. Signed-off-by: David Gibson--- hw/ppc/spapr.c | 19 ++- hw/ppc/spapr_drc.c | 18 ++ hw/ppc/spapr_pci.c | 9 +++-- include/hw/ppc/spapr_drc.h | 7 --- 4 files changed, 19 insertions(+), 34 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index b2311dc..e340ff3 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2523,7 +2523,6 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, Error **errp) { sPAPRDRConnector *drc; -sPAPRDRConnectorClass *drck; uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; int i, fdt_offset, fdt_size; void *fdt; @@ -2538,10 +2537,10 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, fdt_offset = spapr_populate_memory_node(fdt, node, addr, SPAPR_MEMORY_BLOCK_SIZE); -drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); -drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); +spapr_drc_attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); addr += SPAPR_MEMORY_BLOCK_SIZE; if (!dev->hotplugged) { +sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); /* guests expect coldplugged LMBs to be pre-allocated */ drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE); drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED); @@ -2554,7 +2553,6 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, if (dedicated_hp_event_source) { drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr_start / SPAPR_MEMORY_BLOCK_SIZE); -drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs, spapr_drc_index(drc)); @@ -2742,7 +2740,6 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, uint64_t addr_start, addr; int i; sPAPRDRConnector *drc; -sPAPRDRConnectorClass *drck; sPAPRDIMMState *ds; addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, @@ -2762,14 +2759,12 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); -drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); -drck->detach(drc, dev, errp); +spapr_drc_detach(drc, dev, errp); addr += SPAPR_MEMORY_BLOCK_SIZE; } drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr_start / SPAPR_MEMORY_BLOCK_SIZE); -drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs, spapr_drc_index(drc)); out: @@ -2824,7 +2819,6 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, { int index; sPAPRDRConnector *drc; -sPAPRDRConnectorClass *drck; Error *local_err = NULL; CPUCore *cc = CPU_CORE(dev); int smt = kvmppc_smt_threads(); @@ -2842,8 +2836,7 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * smt); g_assert(drc); -drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); -drck->detach(drc, dev, _err); +spapr_drc_detach(drc, dev, _err); if (local_err) { error_propagate(errp, local_err); return; @@ -2887,8 +2880,8 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, } if (drc) { -sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); -drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, _err); +spapr_drc_attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, + _err); if (local_err) { g_free(fdt); error_propagate(errp, local_err); diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 19e2c0d..82c0b94 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -49,8 +49,6 @@ uint32_t spapr_drc_index(sPAPRDRConnector *drc) static uint32_t set_isolation_state(sPAPRDRConnector *drc, sPAPRDRIsolationState state) { -sPAPRDRConnectorClass *drck =
[Qemu-devel] [PATCHv2 4/7] spapr: Clean up handling of DR-indicator
There are 3 types of "indicator" associated with hotplug in the PAPR spec the "allocation state", "isolation state" and "DR-indicator". The first two are intimately tied to the various state transitions associated with hotplug. The DR-indicator, however, is different and simpler. It's basically just a guest controlled variable which can be used by the guest to flag state or problems associated with a device. The idea is that the hypervisor can use it to present information back on management consoles (on some machines with PowerVM it may even control physical LEDs on the machine case associated with the relevant device). For that reason, there's only ever likely to be a single update implementation so the set_indicator_state method isn't useful. Replace it with a direct function call. While we're there, make some small associated cleanups: * PAPR doesn't use the term "indicator state", just "DR-indicator" and the allocation state and isolation state are also considered "indicators". Rename things to be less confusing * Fold set_indicator_state() and rtas_set_indicator_state() into a single rtas_set_dr_indicator() function. Signed-off-by: David Gibson--- hw/ppc/spapr_drc.c | 25 - hw/ppc/trace-events| 2 +- include/hw/ppc/spapr_drc.h | 16 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index f0cff0b..19e2c0d 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -116,14 +116,6 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc, return RTAS_OUT_SUCCESS; } -static uint32_t set_indicator_state(sPAPRDRConnector *drc, -sPAPRDRIndicatorState state) -{ -trace_spapr_drc_set_indicator_state(spapr_drc_index(drc), state); -drc->indicator_state = state; -return RTAS_OUT_SUCCESS; -} - static uint32_t set_allocation_state(sPAPRDRConnector *drc, sPAPRDRAllocationState state) { @@ -321,7 +313,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->isolation_state = SPAPR_DR_ISOLATION_STATE_UNISOLATED; } -drc->indicator_state = SPAPR_DR_INDICATOR_STATE_ACTIVE; +drc->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE; drc->dev = d; drc->fdt = fdt; @@ -394,7 +386,7 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) } } -drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE; +drc->dr_indicator = SPAPR_DR_INDICATOR_INACTIVE; /* Calling release callbacks based on spapr_drc_type(drc). */ switch (spapr_drc_type(drc)) { @@ -507,7 +499,7 @@ static const VMStateDescription vmstate_spapr_drc = { .fields = (VMStateField []) { VMSTATE_UINT32(isolation_state, sPAPRDRConnector), VMSTATE_UINT32(allocation_state, sPAPRDRConnector), -VMSTATE_UINT32(indicator_state, sPAPRDRConnector), +VMSTATE_UINT32(dr_indicator, sPAPRDRConnector), VMSTATE_BOOL(configured, sPAPRDRConnector), VMSTATE_BOOL(awaiting_release, sPAPRDRConnector), VMSTATE_BOOL(awaiting_allocation, sPAPRDRConnector), @@ -647,7 +639,6 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) dk->realize = realize; dk->unrealize = unrealize; drck->set_isolation_state = set_isolation_state; -drck->set_indicator_state = set_indicator_state; drck->set_allocation_state = set_allocation_state; drck->get_name = get_name; drck->attach = attach; @@ -929,17 +920,17 @@ static uint32_t rtas_set_allocation_state(uint32_t idx, uint32_t state) return drck->set_allocation_state(drc, state); } -static uint32_t rtas_set_indicator_state(uint32_t idx, uint32_t state) +static uint32_t rtas_set_dr_indicator(uint32_t idx, uint32_t state) { sPAPRDRConnector *drc = spapr_drc_by_index(idx); -sPAPRDRConnectorClass *drck; if (!drc) { return RTAS_OUT_PARAM_ERROR; } -drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); -return drck->set_indicator_state(drc, state); +trace_spapr_drc_set_dr_indicator(idx, state); +drc->dr_indicator = state; +return RTAS_OUT_SUCCESS; } static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, @@ -964,7 +955,7 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, ret = rtas_set_isolation_state(idx, state); break; case RTAS_SENSOR_TYPE_DR: -ret = rtas_set_indicator_state(idx, state); +ret = rtas_set_dr_indicator(idx, state); break; case RTAS_SENSOR_TYPE_ALLOCATION_STATE: ret = rtas_set_allocation_state(idx, state); diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 581fa85..3e8e3cf 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -39,7 +39,7 @@
[Qemu-devel] [PATCHv2 0/7] spapr: DRC cleanups (part III)
A third batch of cleanups to the DRC code. This continues to clear away relatively simple cruft, to get a clearer look at the fundamental state handling. Changes since v1: * Some comment updates suggested by Mike Roth * Changed approach to the get_name cleanup, using generated on the fly names, instead of externally assigned names * Added in some cleanups to hotplug code in spapr_pci.c David Gibson (7): spapr: Clean up DR entity sense handling spapr: Don't misuse DR-indicator in spapr_recover_pending_dimm_state() spapr: Clean up RTAS set-indicator spapr: Clean up handling of DR-indicator spapr: Change DRC attach & detach methods to functions spapr: Fold spapr_phb_{add,remove}_pci_device() into their only callers spapr: Rework DRC name handling hw/ppc/spapr.c | 30 ++--- hw/ppc/spapr_drc.c | 269 - hw/ppc/spapr_pci.c | 72 +--- hw/ppc/trace-events| 5 +- include/hw/ppc/spapr_drc.h | 30 ++--- 5 files changed, 171 insertions(+), 235 deletions(-) -- 2.9.4
[Qemu-devel] [PATCHv2 6/7] spapr: Fold spapr_phb_{add, remove}_pci_device() into their only callers
Both functions are fairly short, and so are their callers. There's no particular logical distinction between them, so fold them together. Signed-off-by: David Gibson--- hw/ppc/spapr_pci.c | 63 -- 1 file changed, 23 insertions(+), 40 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 56cb4b8..0b447f2 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1344,30 +1344,6 @@ static int spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev, return offset; } -static void spapr_phb_add_pci_device(sPAPRDRConnector *drc, - sPAPRPHBState *phb, - PCIDevice *pdev, - Error **errp) -{ -DeviceState *dev = DEVICE(pdev); -void *fdt = NULL; -int fdt_start_offset = 0, fdt_size; - -fdt = create_device_tree(_size); -fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); -if (!fdt_start_offset) { -error_setg(errp, "Failed to create pci child device tree node"); -goto out; -} - -spapr_drc_attach(drc, DEVICE(pdev), - fdt, fdt_start_offset, !dev->hotplugged, errp); -out: -if (*errp) { -g_free(fdt); -} -} - /* Callback to be called during DRC release. */ void spapr_phb_remove_pci_device_cb(DeviceState *dev) { @@ -1385,14 +1361,6 @@ void spapr_phb_remove_pci_device_cb(DeviceState *dev) object_unparent(OBJECT(dev)); } -static void spapr_phb_remove_pci_device(sPAPRDRConnector *drc, -sPAPRPHBState *phb, -PCIDevice *pdev, -Error **errp) -{ -spapr_drc_detach(drc, DEVICE(pdev), errp); -} - static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb, uint32_t busnr, int32_t devfn) @@ -1429,6 +1397,8 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, Error *local_err = NULL; PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))); uint32_t slotnr = PCI_SLOT(pdev->devfn); +void *fdt = NULL; +int fdt_start_offset, fdt_size; /* if DR is disabled we don't need to do anything in the case of * hotplug or coldplug callbacks @@ -1438,10 +1408,10 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, * we need to let them know it's not enabled */ if (plugged_dev->hotplugged) { -error_setg(errp, QERR_BUS_NO_HOTPLUG, +error_setg(_err, QERR_BUS_NO_HOTPLUG, object_get_typename(OBJECT(phb))); } -return; +goto out; } g_assert(drc); @@ -1452,16 +1422,23 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, */ if (plugged_dev->hotplugged && bus->devices[PCI_DEVFN(slotnr, 0)] && PCI_FUNC(pdev->devfn) != 0) { -error_setg(errp, "PCI: slot %d function 0 already ocuppied by %s," +error_setg(_err, "PCI: slot %d function 0 already ocuppied by %s," " additional functions can no longer be exposed to guest.", slotnr, bus->devices[PCI_DEVFN(slotnr, 0)]->name); -return; +goto out; +} + +fdt = create_device_tree(_size); +fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); +if (!fdt_start_offset) { +error_setg(_err, "Failed to create pci child device tree node"); +goto out; } -spapr_phb_add_pci_device(drc, phb, pdev, _err); +spapr_drc_attach(drc, DEVICE(pdev), fdt, fdt_start_offset, + !plugged_dev->hotplugged, _err); if (local_err) { -error_propagate(errp, local_err); -return; +goto out; } /* If this is function 0, signal hotplug for all the device functions. @@ -1485,6 +1462,12 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, } } } + +out: +if (local_err) { +error_propagate(errp, local_err); +g_free(fdt); +} } static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, @@ -1531,7 +1514,7 @@ static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, } } -spapr_phb_remove_pci_device(drc, phb, pdev, _err); +spapr_drc_detach(drc, DEVICE(pdev), _err); if (local_err) { error_propagate(errp, local_err); return; -- 2.9.4
Re: [Qemu-devel] [PATCH 0/3] ppc: fix memory leaks
On Tue, Jun 06, 2017 at 05:22:42PM +0200, Greg Kurz wrote: > Coverity just reported a memory leak introduced by this commit (QEMU 2.9): > > commit df58713396f8b2deb923e39c00b10744c5c63909 > Author: Thomas Huth> Date: Wed Feb 15 10:21:44 2017 +0100 > > hw/ppc/spapr: Check for valid page size when hot plugging memory > > It boils down to the fact that object_property_get_str() returns a string > allocated with g_strdup(), which must be deallocated with g_free() at some > point. Applied to ppc-for-2.10. Do we need to queue this for 2.9 stable as well? -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
[Qemu-devel] [PATCHv2 2/7] spapr: Don't misuse DR-indicator in spapr_recover_pending_dimm_state()
With some combinations of migration and hotplug we can lost temporary state indicating how many DRCs (guest side hotplug handles) are still connected to a DIMM object in the process of removal. When we hit that situation spapr_recover_pending_dimm_state() is used to scan more extensively and work out the right number. It does this using drc->indicator state to determine what state of disconnection the DRC is in. However, this is not safe, because the indicator state is guest settable - in fact it's more-or-less a purely guest->host notification mechanism which should have no bearing on the internals of hotplug state management. So, replace the test for this with a test on drc->dev, which is a purely qemu side managed variable, and updated the same BQL critical section as the indicator state. This does introduce an off-by-one change, because the indicator state was updated before the call to spapr_lmb_release() on the current DRC, whereas drc->dev is updated afterwards. That's corrected by always decrementing the nr_lmbs value instead of only doing so in the case where we didn't have to recover information. Signed-off-by: David Gibson--- hw/ppc/spapr.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 9b7ae28..b2311dc 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2676,7 +2676,7 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms, drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); -if (drc->indicator_state != SPAPR_DR_INDICATOR_STATE_INACTIVE) { +if (drc->dev) { avail_lmbs++; } addr += SPAPR_MEMORY_BLOCK_SIZE; @@ -2700,10 +2700,11 @@ void spapr_lmb_release(DeviceState *dev) * during the unplug process. In this case recover it. */ if (ds == NULL) { ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); -if (ds->nr_lmbs) { -return; -} -} else if (--ds->nr_lmbs) { +/* The DRC being examined by the caller at least must be counted */ +g_assert(ds->nr_lmbs); +} + +if (--ds->nr_lmbs) { return; } -- 2.9.4
Re: [Qemu-devel] [RFC 1/3] spapr: Fold spapr_phb_add_pci_device() into its only caller
On Tue, Jun 06, 2017 at 04:37:27PM -0500, Michael Roth wrote: > Quoting David Gibson (2017-06-06 08:05:32) > > This function is fairly short, and so is its only caller. There's no > > particular logical distinction between them, so fold them together. > > > > Signed-off-by: David Gibson> > --- > > hw/ppc/spapr_pci.c | 53 > > ++--- > > 1 file changed, 22 insertions(+), 31 deletions(-) > > > > diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c > > index 46e736d..a216f61 100644 > > --- a/hw/ppc/spapr_pci.c > > +++ b/hw/ppc/spapr_pci.c > > @@ -1344,30 +1344,6 @@ static int spapr_create_pci_child_dt(sPAPRPHBState > > *phb, PCIDevice *dev, > > return offset; > > } > > > > -static void spapr_phb_add_pci_device(sPAPRDRConnector *drc, > > - sPAPRPHBState *phb, > > - PCIDevice *pdev, > > - Error **errp) > > -{ > > -DeviceState *dev = DEVICE(pdev); > > -void *fdt = NULL; > > -int fdt_start_offset = 0, fdt_size; > > - > > -fdt = create_device_tree(_size); > > -fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); > > -if (!fdt_start_offset) { > > -error_setg(errp, "Failed to create pci child device tree node"); > > -goto out; > > -} > > - > > -spapr_drc_attach(drc, DEVICE(pdev), > > - fdt, fdt_start_offset, !dev->hotplugged, errp); > > -out: > > -if (*errp) { > > -g_free(fdt); > > -} > > -} > > - > > /* Callback to be called during DRC release. */ > > void spapr_phb_remove_pci_device_cb(DeviceState *dev) > > { > > @@ -1429,6 +1405,8 @@ static void spapr_phb_hot_plug_child(HotplugHandler > > *plug_handler, > > Error *local_err = NULL; > > PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))); > > uint32_t slotnr = PCI_SLOT(pdev->devfn); > > +void *fdt = NULL; > > +int fdt_start_offset, fdt_size; > > > > /* if DR is disabled we don't need to do anything in the case of > > * hotplug or coldplug callbacks > > @@ -1438,10 +1416,10 @@ static void spapr_phb_hot_plug_child(HotplugHandler > > *plug_handler, > > * we need to let them know it's not enabled > > */ > > if (plugged_dev->hotplugged) { > > -error_setg(errp, QERR_BUS_NO_HOTPLUG, > > +error_setg(_err, QERR_BUS_NO_HOTPLUG, > > object_get_typename(OBJECT(phb))); > > } > > -return; > > +goto out; > > } > > > > g_assert(drc); > > @@ -1452,16 +1430,23 @@ static void spapr_phb_hot_plug_child(HotplugHandler > > *plug_handler, > > */ > > if (plugged_dev->hotplugged && bus->devices[PCI_DEVFN(slotnr, 0)] && > > PCI_FUNC(pdev->devfn) != 0) { > > -error_setg(errp, "PCI: slot %d function 0 already ocuppied by %s," > > +error_setg(_err, "PCI: slot %d function 0 already ocuppied > > by %s," > > " additional functions can no longer be exposed to > > guest.", > > slotnr, bus->devices[PCI_DEVFN(slotnr, 0)]->name); > > -return; > > +goto out; > > } > > > > -spapr_phb_add_pci_device(drc, phb, pdev, _err); > > Since we never used local_err outside propagating it and immediately > bailing, and since we bail on errp in all prior callers, maybe we > should just drop local_err completely in favor errp. That doesn't quite work. The reason for the local_err pattern is so that we can tell locally if the error was triggered (errp might be NULL, so checking *errp isn't safe). > > > +fdt = create_device_tree(_size); > > +fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); > > +if (!fdt_start_offset) { > > +error_setg(_err, "Failed to create pci child device tree > > node"); > > +goto out; > > +} > > + > > +spapr_drc_attach(drc, DEVICE(pdev), fdt, fdt_start_offset, > > + !plugged_dev->hotplugged, _err); > > if (local_err) { > > -error_propagate(errp, local_err); > > -return; > > +goto out; > > } > > > > /* If this is function 0, signal hotplug for all the device functions. > > @@ -1485,6 +1470,12 @@ static void spapr_phb_hot_plug_child(HotplugHandler > > *plug_handler, > > } > > } > > } > > + > > +out: > > +if (local_err) { > > +error_propagate(errp, local_err); > > +g_free(fdt); > > +} > > } > > > > static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, > -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
Re: [Qemu-devel] [PATCH 2/3] exec: simplify address_space_get_iotlb_entry
On Tue, Jun 06, 2017 at 04:34:30PM +0200, Paolo Bonzini wrote: > > > On 05/06/2017 05:07, Peter Xu wrote: > > I don't sure whether it'll be a good interface for IOTLB. AFAIU at > > least for VT-d, the IOMMU translation is page aligned which is defined > > by spec, so it makes sense that (again at least for VT-d) here we'd > > better just use page_mask/addr_mask. > > > > That's also how I know about IOMMU in general - I assume it do the > > translations always with page masks (never arbitary length), though > > page size can differ from platfrom to platform, that's why here the > > IOTLB interface used addr_mask, then it works for all platforms. I > > don't know whether I'm 100% correct here though. > > > > Maybe David/Paolo/... would comment as well? > > I would ask David. There are PowerPC MMUs that allow fast lookup of > arbitrarily-sized windows (not necessarily power of two), Uh.. I'm not sure what you mean here. You might be thinking of the BATs which really old (32-bit) PowerPC MMUs had - those allow arbitrary large block translations, but they do have to be a power of two. > so maybe the > IOMMUs can do the same. The only Power IOMMU I know about uses a fixed, power-of-two page size per DMA window. -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
Re: [Qemu-devel] [PATCH 6/7] spapr: Clean up handling of DR-indicator
On Tue, Jun 06, 2017 at 04:04:33PM -0500, Michael Roth wrote: > Quoting David Gibson (2017-06-06 03:32:20) > > There are 3 types of "indicator" associated with hotplug in the PAPR spec > > the "allocation state", "isolation state" and "DR-indicator". The first > > two are intimately tied to the various state transitions associated with > > hotplug. The DR-indicator, however, is different and simpler. > > > > It's basically just a guest controlled variable which can be used by the > > guest to flag state or problems associated with a device. The idea is that > > the hypervisor can use it to present information back on management > > consoles (on some machines with PowerVM it may even control physical LEDs > > on the machine case associated with the relevant device). > > > > For that reason, there's only ever likely to be a single update > > implementation so the set_indicator_state method isn't useful. Replace it > > with a direct function call. > > > > While we're there, make some small associated cleanups: > > * PAPR doesn't use the term "indicator state", just "DR-indicator" and > > the allocation state and isolation state are also considered "indicators". > > Rename things to be less confusing > > * Fold set_indicator_state() and rtas_set_indicator_state() into a single > > rtas_set_dr_indicator() function. > > > > Signed-off-by: David Gibson> > --- > > hw/ppc/spapr_drc.c | 25 - > > hw/ppc/trace-events| 2 +- > > include/hw/ppc/spapr_drc.h | 16 > > 3 files changed, 17 insertions(+), 26 deletions(-) > > > > diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c > > index 6c2fa93..a4ece2e 100644 > > --- a/hw/ppc/spapr_drc.c > > +++ b/hw/ppc/spapr_drc.c > > @@ -116,14 +116,6 @@ static uint32_t set_isolation_state(sPAPRDRConnector > > *drc, > > return RTAS_OUT_SUCCESS; > > } > > > > -static uint32_t set_indicator_state(sPAPRDRConnector *drc, > > -sPAPRDRIndicatorState state) > > -{ > > -trace_spapr_drc_set_indicator_state(spapr_drc_index(drc), state); > > -drc->indicator_state = state; > > -return RTAS_OUT_SUCCESS; > > -} > > - > > static uint32_t set_allocation_state(sPAPRDRConnector *drc, > > sPAPRDRAllocationState state) > > { > > @@ -313,7 +305,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState > > *d, void *fdt, > > if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { > > drc->isolation_state = SPAPR_DR_ISOLATION_STATE_UNISOLATED; > > } > > -drc->indicator_state = SPAPR_DR_INDICATOR_STATE_ACTIVE; > > +drc->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE; > > > > drc->dev = d; > > drc->fdt = fdt; > > @@ -386,7 +378,7 @@ static void detach(sPAPRDRConnector *drc, DeviceState > > *d, Error **errp) > > } > > } > > > > -drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE; > > +drc->dr_indicator = SPAPR_DR_INDICATOR_INACTIVE; > > > > /* Calling release callbacks based on spapr_drc_type(drc). */ > > switch (spapr_drc_type(drc)) { > > @@ -499,7 +491,7 @@ static const VMStateDescription vmstate_spapr_drc = { > > .fields = (VMStateField []) { > > VMSTATE_UINT32(isolation_state, sPAPRDRConnector), > > VMSTATE_UINT32(allocation_state, sPAPRDRConnector), > > -VMSTATE_UINT32(indicator_state, sPAPRDRConnector), > > +VMSTATE_UINT32(dr_indicator, sPAPRDRConnector), > > VMSTATE_BOOL(configured, sPAPRDRConnector), > > VMSTATE_BOOL(awaiting_release, sPAPRDRConnector), > > VMSTATE_BOOL(awaiting_allocation, sPAPRDRConnector), > > @@ -614,7 +606,6 @@ static void spapr_dr_connector_class_init(ObjectClass > > *k, void *data) > > dk->realize = realize; > > dk->unrealize = unrealize; > > drck->set_isolation_state = set_isolation_state; > > -drck->set_indicator_state = set_indicator_state; > > drck->set_allocation_state = set_allocation_state; > > drck->attach = attach; > > drck->detach = detach; > > @@ -895,17 +886,17 @@ static uint32_t rtas_set_allocation_state(uint32_t > > idx, uint32_t state) > > return drck->set_allocation_state(drc, state); > > } > > > > -static uint32_t rtas_set_indicator_state(uint32_t idx, uint32_t state) > > +static uint32_t rtas_set_dr_indicator(uint32_t idx, uint32_t state) > > { > > sPAPRDRConnector *drc = spapr_drc_by_index(idx); > > -sPAPRDRConnectorClass *drck; > > > > if (!drc) { > > return RTAS_OUT_PARAM_ERROR; > > } > > > > -drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); > > -return drck->set_indicator_state(drc, state); > > +trace_spapr_drc_set_dr_indicator(idx, state); > > +drc->dr_indicator = state; > > +return RTAS_OUT_SUCCESS; > > } > > > > static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, > > @@ -930,7 +921,7 @@ static void
[Qemu-devel] [PATCHv2 3/7] spapr: Clean up RTAS set-indicator
In theory the RTAS set-indicator call can be used for a number of "indicators" defined by PAPR. In practice the only ones we're ever likely to implement are those used for Dynamic Reconfiguration (i.e. hotplug). Because of this, the current implementation determines the associated DRC object, before dispatching based on the type of indicator. However, this means we also need a check that we're dealing with a DR related indicator at all, which duplicates some of the logic from the switch further down. Even though it means a bit of code duplication, things work out cleaner if we delegate the DRC lookup to the individual indicator type functions - and it also allows some further cleanups. While we're there, remove references to "sensor", a copy/paste artefact from the related, but distinct "get-sensor" call. Signed-off-by: David Gibson--- hw/ppc/spapr_drc.c | 84 - hw/ppc/trace-events | 2 -- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index cabeacf..f0cff0b 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -903,74 +903,78 @@ out: * RTAS calls */ -static bool sensor_type_is_dr(uint32_t sensor_type) +static uint32_t rtas_set_isolation_state(uint32_t idx, uint32_t state) { -switch (sensor_type) { -case RTAS_SENSOR_TYPE_ISOLATION_STATE: -case RTAS_SENSOR_TYPE_DR: -case RTAS_SENSOR_TYPE_ALLOCATION_STATE: -return true; +sPAPRDRConnector *drc = spapr_drc_by_index(idx); +sPAPRDRConnectorClass *drck; + +if (!drc) { +return RTAS_OUT_PARAM_ERROR; } -return false; +drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); +return drck->set_isolation_state(drc, state); } -static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, uint32_t nret, - target_ulong rets) +static uint32_t rtas_set_allocation_state(uint32_t idx, uint32_t state) { -uint32_t sensor_type; -uint32_t sensor_index; -uint32_t sensor_state; -uint32_t ret = RTAS_OUT_SUCCESS; -sPAPRDRConnector *drc; +sPAPRDRConnector *drc = spapr_drc_by_index(idx); sPAPRDRConnectorClass *drck; -if (nargs != 3 || nret != 1) { -ret = RTAS_OUT_PARAM_ERROR; -goto out; +if (!drc) { +return RTAS_OUT_PARAM_ERROR; } -sensor_type = rtas_ld(args, 0); -sensor_index = rtas_ld(args, 1); -sensor_state = rtas_ld(args, 2); +drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); +return drck->set_allocation_state(drc, state); +} -if (!sensor_type_is_dr(sensor_type)) { -goto out_unimplemented; -} +static uint32_t rtas_set_indicator_state(uint32_t idx, uint32_t state) +{ +sPAPRDRConnector *drc = spapr_drc_by_index(idx); +sPAPRDRConnectorClass *drck; -/* if this is a DR sensor we can assume sensor_index == drc_index */ -drc = spapr_drc_by_index(sensor_index); if (!drc) { -trace_spapr_rtas_set_indicator_invalid(sensor_index); +return RTAS_OUT_PARAM_ERROR; +} + +drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); +return drck->set_indicator_state(drc, state); +} + +static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, + uint32_t token, + uint32_t nargs, target_ulong args, + uint32_t nret, target_ulong rets) +{ +uint32_t type, idx, state; +uint32_t ret = RTAS_OUT_SUCCESS; + +if (nargs != 3 || nret != 1) { ret = RTAS_OUT_PARAM_ERROR; goto out; } -drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); -switch (sensor_type) { +type = rtas_ld(args, 0); +idx = rtas_ld(args, 1); +state = rtas_ld(args, 2); + +switch (type) { case RTAS_SENSOR_TYPE_ISOLATION_STATE: -ret = drck->set_isolation_state(drc, sensor_state); +ret = rtas_set_isolation_state(idx, state); break; case RTAS_SENSOR_TYPE_DR: -ret = drck->set_indicator_state(drc, sensor_state); +ret = rtas_set_indicator_state(idx, state); break; case RTAS_SENSOR_TYPE_ALLOCATION_STATE: -ret = drck->set_allocation_state(drc, sensor_state); +ret = rtas_set_allocation_state(idx, state); break; default: -goto out_unimplemented; +ret = RTAS_OUT_NOT_SUPPORTED; } out: rtas_st(rets, 0, ret); -return; - -out_unimplemented: -/* currently only DR-related sensors are implemented */ -trace_spapr_rtas_set_indicator_not_supported(sensor_index, sensor_type); -rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); } static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr, diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 4979397..581fa85 100644 ---
[Qemu-devel] [PATCHv2 1/7] spapr: Clean up DR entity sense handling
DRC classes have an entity_sense method to determine (in a specific PAPR sense) the presence or absence of a device plugged into a DRC. However, we only have one implementation of the method, which explicitly tests for different DRC types. This changes it to instead have different method implementations for the two cases: "logical" and "physical" DRCs. While we're at it, the entity sense method always returns RTAS_OUT_SUCCESS, and the interesting value is returned via pass-by-reference. Simplify this to directly return the value we care about Signed-off-by: David Gibson--- hw/ppc/spapr_drc.c | 72 ++ hw/ppc/spapr_pci.c | 6 ++-- hw/ppc/trace-events| 1 - include/hw/ppc/spapr_drc.h | 4 +-- 4 files changed, 40 insertions(+), 43 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 39e7f30..cabeacf 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -185,39 +185,25 @@ static void set_signalled(sPAPRDRConnector *drc) * based on the current allocation/indicator/power states * for the DR connector. */ -static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state) +static sPAPRDREntitySense physical_entity_sense(sPAPRDRConnector *drc) { -if (drc->dev) { -if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI && -drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { -/* for logical DR, we return a state of UNUSABLE - * iff the allocation state UNUSABLE. - * Otherwise, report the state as USABLE/PRESENT, - * as we would for PCI. - */ -*state = SPAPR_DR_ENTITY_SENSE_UNUSABLE; -} else { -/* this assumes all PCI devices are assigned to - * a 'live insertion' power domain, where QEMU - * manages power state automatically as opposed - * to the guest. present, non-PCI resources are - * unaffected by power state. - */ -*state = SPAPR_DR_ENTITY_SENSE_PRESENT; -} +/* this assumes all PCI devices are assigned to a 'live insertion' + * power domain, where QEMU manages power state automatically as + * opposed to the guest. present, non-PCI resources are unaffected + * by power state. + */ +return drc->dev ? SPAPR_DR_ENTITY_SENSE_PRESENT +: SPAPR_DR_ENTITY_SENSE_EMPTY; +} + +static sPAPRDREntitySense logical_entity_sense(sPAPRDRConnector *drc) +{ +if (drc->dev +&& (drc->allocation_state != SPAPR_DR_ALLOCATION_STATE_UNUSABLE)) { +return SPAPR_DR_ENTITY_SENSE_PRESENT; } else { -if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { -/* PCI devices, and only PCI devices, use EMPTY - * in cases where we'd otherwise use UNUSABLE - */ -*state = SPAPR_DR_ENTITY_SENSE_EMPTY; -} else { -*state = SPAPR_DR_ENTITY_SENSE_UNUSABLE; -} +return SPAPR_DR_ENTITY_SENSE_UNUSABLE; } - -trace_spapr_drc_entity_sense(spapr_drc_index(drc), *state); -return RTAS_OUT_SUCCESS; } static void prop_get_index(Object *obj, Visitor *v, const char *name, @@ -445,7 +431,6 @@ static void reset(DeviceState *d) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); -sPAPRDREntitySense state; trace_spapr_drc_reset(spapr_drc_index(drc)); @@ -477,8 +462,7 @@ static void reset(DeviceState *d) } } -drck->entity_sense(drc, ); -if (state == SPAPR_DR_ENTITY_SENSE_PRESENT) { +if (drck->dr_entity_sense(drc) == SPAPR_DR_ENTITY_SENSE_PRESENT) { drck->set_signalled(drc); } } @@ -488,8 +472,7 @@ static bool spapr_drc_needed(void *opaque) sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque; sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); bool rc = false; -sPAPRDREntitySense value; -drck->entity_sense(drc, ); +sPAPRDREntitySense value = drck->dr_entity_sense(drc); /* If no dev is plugged in there is no need to migrate the DRC state */ if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) { @@ -667,7 +650,6 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) drck->set_indicator_state = set_indicator_state; drck->set_allocation_state = set_allocation_state; drck->get_name = get_name; -drck->entity_sense = entity_sense; drck->attach = attach; drck->detach = detach; drck->release_pending = release_pending; @@ -678,6 +660,20 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) dk->user_creatable = false; } +static void spapr_drc_physical_class_init(ObjectClass *k, void *data) +{ +sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); + +drck->dr_entity_sense = physical_entity_sense; +} + +static
Re: [Qemu-devel] [PATCH v2 1/1] qemu/migration: fix the double free problem on from_src_file
在 2017/6/6 20:49, Kevin Wolf 写道: Am 06.06.2017 um 07:24 hat QingFeng Hao geschrieben: In load_snapshot, mis->from_src_file is freed twice, the first free is by qemu_fclose, the second is by migration_incoming_state_destroy and it causes Illegal instruction exception. The fix is just to remove the first free. This problem is found by qemu-iotests case 068 since commit "660819b migration: shut src return path unconditionally". The error is: 068 1s ... - output mismatch (see 068.out.bad) --- tests/qemu-iotests/068.out 2017-05-06 01:00:26.417270437 +0200 +++ 068.out.bad2017-06-03 13:59:55.360274640 +0200 @@ -6,6 +6,8 @@ QEMU X.Y.Z monitor - type 'help' for more information (qemu) savevm 0 (qemu) quit +./common.config: line 107: 242472 Illegal instruction (core dumped) ( if [ -n "${QEMU_NEED_PID}" ]; then +echo $BASHPID > "${QEMU_TEST_DIR}/qemu-${_QEMU_HANDLE}.pid"; +fi; exec "$QEMU_PROG" $QEMU_OPTIONS "$@" ) QEMU X.Y.Z monitor - type 'help' for more information -(qemu) quit -*** done +(qemu) *** done Signed-off-by: QingFeng HaoReviewed-by: Dr. David Alan Gilbert Reviewed-by: Peter Xu Dave, as you only gave R-b rather than merging the patch, should this be merged through the block tree? diff --git a/migration/savevm.c b/migration/savevm.c index 9c320f59d0..853e14e34e 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2290,7 +2290,6 @@ int load_snapshot(const char *name, Error **errp) aio_context_acquire(aio_context); ret = qemu_loadvm_state(f); -qemu_fclose(f); aio_context_release(aio_context); migration_incoming_state_destroy(); Did we check other callers of migration_incoming_state_destroy()? For example, qmp_xen_load_devices_state() looks suspicious, too. Good reminder! Yes, I checked it and there is no assignment of from_src_file there and f is opened locally, so I think that qemu_fclose doesn't impact migration_incoming_state_destroy. migration_incoming_state_destroy is called in 4 places: process_incoming_migration_bh, postcopy_ram_listen_thread, qmp_xen_load_devices_state and load_snapshot. process_incoming_migration_bh is launched by process_incoming_migration_co whose qemu_fclose is removed by commit 660819b. For postcopy_ram_listen_thread, I didn't see where it calls qemu_fclose. Actually to simplify the check for the problem, I just searched where from_src_file is assigned to and got 2 places: process_incoming_migration_co and load_snapshot. qemu_fclose in the first function is removed by commit 660819b, and qemu_fclose in the second is removed by this one. I think a potential risk might be opaque is closed by anywhere else than process_incoming_migration_co, but there is legacy qemu_close before commit 660819b, so the risk might be low? thanks :) I can't tell for postcopy_ram_listen_thread() - commit 660819b didn't seem to remove a qemu_fclose() call there, but I can't see one left behind either. Was the file leaked before commit 660819b or am I missing something? I don't think so because loadvm_postcopy_handle_listen creates thread postcopy_ram_listen_thread and passes mis->from_src_file as its arg, which will be closed by migration_incoming_state_destroy. What confuses me is in the series function calls of qemu_loadvm_state_main etc, argument f looks to be redundant as mis already contains from_src_file which equals to f. Furthermore, mis may be also redundant as it can be got via migration_incoming_get_current. Thanks! Kevin -- Regards QingFeng Hao
Re: [Qemu-devel] [PATCH 4/5] ram: Use MigrationStats for statistics
On Tue, Jun 06, 2017 at 07:33:45PM +0200, Juan Quintela wrote: > Peter Xuwrote: > > On Mon, Jun 05, 2017 at 01:34:45PM +0100, Dr. David Alan Gilbert wrote: > >> * Juan Quintela (quint...@redhat.com) wrote: > >> > RAM Statistics need to survive migration to make info migrate work, so we > >> > need to store them outside of RAMState. As we already have an struct > >> > with those fields, just used them. (MigrationStats and XBZRLECacheStats). > >> > > >> > Signed-off-by: Juan Quintela > >> > >> Hmm OK; this feels very much like it's the opposite of 180f61f from > >> March; these variables keep moving around over the last couple of months > >> - are they going to stay still now? > > > > O:-) > > > > Meanwhile, I don't know whether it'll be necessary to remove all the > > functions like ram_bytes_transferred(), e.g., it would be just: > > > > uint64_t ram_bytes_transferred(void) > > { > > -return ram_state.bytes_transferred; > > +return ram_counters.transferred; > > } > > > > But I'm okay with either. > > That value was only used for filling the statistics. And we are filling > a struct from another struct of the exact same type. Going through an > exported function looks stranger. > > And as said in $commit, the idea was that creating a new counter was > easy, right now you have to: > > - add it to MigrationParam (still have to do this) > - add it to MigrationParams (still have to do this) > - create the field in MigrationStats or RAMState > - create a function that exports it > - add that function in ram.h to export it > - add it on qmp_query (still have to do this) > > So, we are moving from 6 steps to 3 steps. I think we are much better > now, no? O:-) Hmm, okay! (as long as we won't move these functions back one day :-) -- Peter Xu
Re: [Qemu-devel] [PATCH v2 0/6] Convert to realize and cleanup
Hi, Michael On 06/06/2017 11:23 PM, Michael S. Tsirkin wrote: Notes: - Please write a cover letter explaining what this patchset is about - Please add notes about how did you test it - Pls copy everyone on the cover letter too. - Please run a spell checker on comments and commit log Thanks! OK, I see. Thanks for your kind reminder. Mao On Fri, Jun 02, 2017 at 03:54:36PM +0800, Mao Zhongyi wrote: v2: * patch1: subject and commit message was rewrited by markus. * patch2: comment was added to pci_add_capability2(). * patch3: a new patch that fix the wrong return value judgment condition. * patch4: a new patch that fix code style problems. * patch5: add an errp argument for pci_add_capability to pass error for its callers. * patch6: convert part of pci-bridge device to realize. v1: * patch1: fix unreasonable return value check Mao Zhongyi (6): pci: Clean up error checking in pci_add_capability() pci: Add comment for pci_add_capability2() pci: Fix the wrong return value judgment condition net/eepro100: Fixed code style pci: Make errp the last parameter of pci_add_capability() pci: Convert to realize hw/i386/amd_iommu.c| 24 hw/net/e1000e.c| 9 - hw/net/eepro100.c | 77 +- hw/pci-bridge/i82801b11.c | 12 +++--- hw/pci-bridge/pcie_root_port.c | 15 +++- hw/pci-bridge/xio3130_downstream.c | 20 +- hw/pci-bridge/xio3130_upstream.c | 20 +- hw/pci/pci.c | 18 - hw/pci/pci_bridge.c| 8 +++- hw/pci/pcie.c | 15 ++-- hw/pci/shpc.c | 5 ++- hw/pci/slotid_cap.c| 7 +++- hw/vfio/pci.c | 5 ++- hw/virtio/virtio-pci.c | 19 +++--- include/hw/pci/pci.h | 3 +- include/hw/pci/pci_bridge.h| 3 +- include/hw/pci/pcie.h | 3 +- 17 files changed, 154 insertions(+), 109 deletions(-) -- 2.9.3
Re: [Qemu-devel] [PATCH v3 4/7] net/eepro100: Fix code style
Hi, Michael On 06/06/2017 11:31 PM, Michael S. Tsirkin wrote: On Tue, Jun 06, 2017 at 07:26:29PM +0800, Mao Zhongyi wrote: It reports a code style problem(ERROR: "foo * bar" should be "foo *bar") when running checkpatch.pl. So fix it to conform to the coding standards. Cc: jasow...@redhat.com Cc: arm...@redhat.com Signed-off-by: Mao ZhongyiWe don't generally do this kind of drive-by coding cleanups. Wait until you actually make some changes to this file. I'm also not merging this through the pci tree, pls split this out. The e100_pci_reset() in this file will be modified in the patch5. it will reports a code style problem such as 'ERROR: "foo * bar" should be "foo *bar"' when executing the checkpatch.pl for patch5. Of course, I could simply modify the e100_pci_reset() to avoid this error, but I think it's not a good idea. Since fix, all the same error should be fixed absolutely. So I make a separate patch to fix it, meanwhile prepare for patch5. Thanks Mao --- hw/net/eepro100.c | 62 +++ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index da36816..62e989c 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -405,7 +405,7 @@ enum scb_stat_ack { stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), }; -static void disable_interrupt(EEPRO100State * s) +static void disable_interrupt(EEPRO100State *s) { if (s->int_stat) { TRACE(INT, logout("interrupt disabled\n")); @@ -414,7 +414,7 @@ static void disable_interrupt(EEPRO100State * s) } } -static void enable_interrupt(EEPRO100State * s) +static void enable_interrupt(EEPRO100State *s) { if (!s->int_stat) { TRACE(INT, logout("interrupt enabled\n")); @@ -423,7 +423,7 @@ static void enable_interrupt(EEPRO100State * s) } } -static void eepro100_acknowledge(EEPRO100State * s) +static void eepro100_acknowledge(EEPRO100State *s) { s->scb_stat &= ~s->mem[SCBAck]; s->mem[SCBAck] = s->scb_stat; @@ -432,7 +432,7 @@ static void eepro100_acknowledge(EEPRO100State * s) } } -static void eepro100_interrupt(EEPRO100State * s, uint8_t status) +static void eepro100_interrupt(EEPRO100State *s, uint8_t status) { uint8_t mask = ~s->mem[SCBIntmask]; s->mem[SCBAck] |= status; @@ -449,52 +449,52 @@ static void eepro100_interrupt(EEPRO100State * s, uint8_t status) } } -static void eepro100_cx_interrupt(EEPRO100State * s) +static void eepro100_cx_interrupt(EEPRO100State *s) { /* CU completed action command. */ /* Transmit not ok (82557 only, not in emulation). */ eepro100_interrupt(s, 0x80); } -static void eepro100_cna_interrupt(EEPRO100State * s) +static void eepro100_cna_interrupt(EEPRO100State *s) { /* CU left the active state. */ eepro100_interrupt(s, 0x20); } -static void eepro100_fr_interrupt(EEPRO100State * s) +static void eepro100_fr_interrupt(EEPRO100State *s) { /* RU received a complete frame. */ eepro100_interrupt(s, 0x40); } -static void eepro100_rnr_interrupt(EEPRO100State * s) +static void eepro100_rnr_interrupt(EEPRO100State *s) { /* RU is not ready. */ eepro100_interrupt(s, 0x10); } -static void eepro100_mdi_interrupt(EEPRO100State * s) +static void eepro100_mdi_interrupt(EEPRO100State *s) { /* MDI completed read or write cycle. */ eepro100_interrupt(s, 0x08); } -static void eepro100_swi_interrupt(EEPRO100State * s) +static void eepro100_swi_interrupt(EEPRO100State *s) { /* Software has requested an interrupt. */ eepro100_interrupt(s, 0x04); } #if 0 -static void eepro100_fcp_interrupt(EEPRO100State * s) +static void eepro100_fcp_interrupt(EEPRO100State *s) { /* Flow control pause interrupt (82558 and later). */ eepro100_interrupt(s, 0x01); } #endif -static void e100_pci_reset(EEPRO100State * s) +static void e100_pci_reset(EEPRO100State *s) { E100PCIDeviceInfo *info = eepro100_get_class(s); uint32_t device = s->device; @@ -598,7 +598,7 @@ static void e100_pci_reset(EEPRO100State * s) #endif /* EEPROM_SIZE > 0 */ } -static void nic_selective_reset(EEPRO100State * s) +static void nic_selective_reset(EEPRO100State *s) { size_t i; uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom); @@ -669,7 +669,7 @@ static char *regname(uint32_t addr) / #if 0 -static uint16_t eepro100_read_command(EEPRO100State * s) +static uint16_t eepro100_read_command(EEPRO100State *s) { uint16_t val = 0x; TRACE(OTHER, logout("val=0x%04x\n", val)); @@ -694,27 +694,27 @@ enum commands { CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */ }; -static cu_state_t get_cu_state(EEPRO100State * s) +static cu_state_t get_cu_state(EEPRO100State *s) { return ((s->mem[SCBStatus] & BITS(7, 6)) >> 6); } -static void
Re: [Qemu-devel] [PATCH] target/xtensa: handle unknown registers in gdbstub
On 06/03/2017 02:19 AM, Max Filippov wrote: +memset(mem_buf, 0, reg->size); +return reg->size; return 0; Leaving a dead return. r~
[Qemu-devel] [PULL v2 70/70] target/s390x: addressing exceptions are suppressing
From: David HildenbrandWe have to make the address in the old PSW point at the next instruction, as addressing exceptions are suppressing and not nullifying. I assume that there are a lot of other broken cases (as most instructions we care about are suppressing) - all trigger_pgm_exception() specifying and explicit number or ILEN_LATER look suspicious, however this is another story that might require bigger changes (and I have to understand when the address might already have been incremented first). This is needed to make an upcoming kvm-unit-test work. Reviewed-by: Thomas Huth Signed-off-by: David Hildenbrand Message-Id: <20170529121228.2789-1-da...@redhat.com> Signed-off-by: Richard Henderson --- target/s390x/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 291db72..a8d20c5 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -204,7 +204,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, if (raddr > ram_size) { DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__, (uint64_t)raddr, (uint64_t)ram_size); -trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER); +trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER_INC); return 1; } -- 2.9.4
[Qemu-devel] [PULL v2 69/70] target/s390x: mark ETF2 and ETF2-ENH facilities as available
From: Aurelien JarnoSigned-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-30-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/cpu_models.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index e5e005a..fc3cb25 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -668,8 +668,10 @@ static void add_qemu_cpu_model_features(S390FeatBitmap fbm) static const int feats[] = { S390_FEAT_STFLE, S390_FEAT_EXTENDED_IMMEDIATE, +S390_FEAT_EXTENDED_TRANSLATION_2, S390_FEAT_LONG_DISPLACEMENT, S390_FEAT_LONG_DISPLACEMENT_FAST, +S390_FEAT_ETF2_ENH, S390_FEAT_STORE_CLOCK_FAST, S390_FEAT_GENERAL_INSTRUCTIONS_EXT, S390_FEAT_EXECUTE_EXT, -- 2.9.4
[Qemu-devel] [PULL v2 67/70] target/s390x: implement STORE PAIR TO QUADWORD
From: Aurelien JarnoSigned-off-by: Aurelien Jarno Message-Id: <20170604202034.16615-3-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 24 target/s390x/translate.c | 6 ++ 4 files changed, 33 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 054ccd6..69249a5 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -104,6 +104,7 @@ DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(stfl, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(stfle, i32, env, i64) DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64) +DEF_HELPER_FLAGS_4(stpq, TCG_CALL_NO_WG, void, env, i64, i64, i64) #ifndef CONFIG_USER_ONLY DEF_HELPER_3(servc, i32, env, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 32dee40..73dd05d 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -796,6 +796,8 @@ /* STORE ACCESS MULTIPLE */ C(0x9b00, STAM,RS_a, Z, 0, a2, 0, 0, stam, 0) C(0xeb9b, STAMY, RSY_a, LD, 0, a2, 0, 0, stam, 0) +/* STORE PAIR TO QUADWORD */ +C(0xe38e, STPQ,RXY_a, Z, 0, a2, r1_P, 0, stpq, 0) /* SUBTRACT */ C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index f48908c..a8988e0 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1692,6 +1692,30 @@ uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr) return hi; } +/* store pair to quadword */ +void HELPER(stpq)(CPUS390XState *env, uint64_t addr, + uint64_t low, uint64_t high) +{ +uintptr_t ra = GETPC(); + +if (parallel_cpus) { +#ifndef CONFIG_ATOMIC128 +cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); +#else +int mem_idx = cpu_mmu_index(env, false); +TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx); + +Int128 v = int128_make128(low, high); +helper_atomic_sto_be_mmu(env, addr, v, oi, ra); +#endif +} else { +check_alignment(env, addr, 16, ra); + +cpu_stq_data_ra(env, addr + 0, high, ra); +cpu_stq_data_ra(env, addr + 8, low, ra); +} +} + /* Execute instruction. This instruction executes an insn modified with the contents of r1. It does not change the executed instruction in memory; it does not change the program counter. diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 10019ed..95f91d4 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4203,6 +4203,12 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_stpq(DisasContext *s, DisasOps *o) +{ +gen_helper_stpq(cpu_env, o->in2, o->out2, o->out); +return NO_EXIT; +} + static ExitStatus op_srst(DisasContext *s, DisasOps *o) { gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 64/70] target/s390x: implement TEST DECIMAL
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-28-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 3 +++ target/s390x/mem_helper.c | 23 +++ target/s390x/translate.c | 9 + 4 files changed, 36 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 9d4bf64..5871568 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -91,6 +91,7 @@ DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(unpka, TCG_CALL_NO_WG, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_4(unpku, TCG_CALL_NO_WG, i32, env, i64, i32, i64) +DEF_HELPER_FLAGS_3(tp, TCG_CALL_NO_WG, i32, env, i64, i32) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) DEF_HELPER_4(trt, i32, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 6aa0221..7db5133 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -852,6 +852,9 @@ C(0xed11, TCDB,RXE, Z, f1_o, a2, 0, 0, tcdb, 0) C(0xed12, TCXB,RXE, Z, x1_o, a2, 0, 0, tcxb, 0) +/* TEST DECIMAL */ +C(0xebc0, TP, RSL, E2, la1, 0, 0, 0, tp, 0) + /* TEST UNDER MASK */ C(0x9100, TM, SI,Z, m1_8u, i2_8u, 0, 0, 0, tm32) C(0xeb51, TMY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, tm32) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 402147e..fa2bfbb 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1088,6 +1088,29 @@ uint32_t HELPER(unpku)(CPUS390XState *env, uint64_t dest, uint32_t destlen, return do_unpkau(env, dest, destlen, 2, src, GETPC()); } +uint32_t HELPER(tp)(CPUS390XState *env, uint64_t dest, uint32_t destlen) +{ +uintptr_t ra = GETPC(); +uint32_t cc = 0; +int i; + +for (i = 0; i < destlen; i++) { +uint8_t b = cpu_ldub_data_ra(env, dest + i, ra); +/* digit */ +cc |= (b & 0xf0) > 0x90 ? 2 : 0; + +if (i == (destlen - 1)) { +/* sign */ +cc |= (b & 0xf) < 0xa ? 1 : 0; +} else { +/* digit */ +cc |= (b & 0xf) > 0x9 ? 2 : 0; +} +} + +return cc; +} + static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t trans, uintptr_t ra) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index bba9ce8..2253ce6 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4305,6 +4305,15 @@ static ExitStatus op_tprot(DisasContext *s, DisasOps *o) #endif +static ExitStatus op_tp(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l1 = tcg_const_i32(get_field(s->fields, l1) + 1); +gen_helper_tp(cc_op, cpu_env, o->addr1, l1); +tcg_temp_free_i32(l1); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_tr(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -- 2.9.4
[Qemu-devel] [PULL v2 65/70] target/s390x: implement TRANSLATE ONE/TWO TO ONE/TWO
From: Aurelien JarnoSigned-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-29-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 9 + target/s390x/mem_helper.c | 45 + target/s390x/translate.c | 30 ++ 4 files changed, 85 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 5871568..11a545e 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -95,6 +95,7 @@ DEF_HELPER_FLAGS_3(tp, TCG_CALL_NO_WG, i32, env, i64, i32) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) DEF_HELPER_4(trt, i32, env, i32, i64, i64) +DEF_HELPER_5(trXX, i32, env, i32, i32, i32, i32) DEF_HELPER_4(cksm, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64) DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 7db5133..9976d29 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -870,6 +870,15 @@ /* TRANSLATE EXTENDED */ C(0xb2a5, TRE, RRE, Z, 0, r2, r1_P, 0, tre, 0) +/* TRANSLATE ONE TO ONE */ +C(0xb993, TROO,RRF_c, E2, 0, 0, 0, 0, trXX, 0) +/* TRANSLATE ONE TO TWO */ +C(0xb992, TROT,RRF_c, E2, 0, 0, 0, 0, trXX, 0) +/* TRANSLATE TWO TO ONE */ +C(0xb991, TRTO,RRF_c, E2, 0, 0, 0, 0, trXX, 0) +/* TRANSLATE TWO TO TWO */ +C(0xb990, TRTT,RRF_c, E2, 0, 0, 0, 0, trXX, 0) + /* UNPACK */ /* Really format SS_b, but we pack both lengths into one argument for the helper call, so we might as well leave one 8-bit field. */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index fa2bfbb..be89cc4 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1196,6 +1196,51 @@ uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array, return do_helper_trt(env, len, array, trans, GETPC()); } +/* Translate one/two to one/two */ +uint32_t HELPER(trXX)(CPUS390XState *env, uint32_t r1, uint32_t r2, + uint32_t tst, uint32_t sizes) +{ +uintptr_t ra = GETPC(); +int dsize = (sizes & 1) ? 1 : 2; +int ssize = (sizes & 2) ? 1 : 2; +uint64_t tbl = get_address(env, 1) & ~7; +uint64_t dst = get_address(env, r1); +uint64_t len = get_length(env, r1 + 1); +uint64_t src = get_address(env, r2); +uint32_t cc = 3; +int i; + +check_alignment(env, len, ssize, ra); + +/* Lest we fail to service interrupts in a timely manner, */ +/* limit the amount of work we're willing to do. */ +for (i = 0; i < 0x2000; i++) { +uint16_t sval = cpu_ldusize_data_ra(env, src, ssize, ra); +uint64_t tble = tbl + (sval * dsize); +uint16_t dval = cpu_ldusize_data_ra(env, tble, dsize, ra); +if (dval == tst) { +cc = 1; +break; +} +cpu_stsize_data_ra(env, dst, dval, dsize, ra); + +len -= ssize; +src += ssize; +dst += dsize; + +if (len == 0) { +cc = 0; +break; +} +} + +set_address(env, r1, dst); +set_length(env, r1 + 1, len); +set_address(env, r2, src); + +return cc; +} + void HELPER(cdsg)(CPUS390XState *env, uint64_t addr, uint32_t r1, uint32_t r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 2253ce6..9f3443e 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4340,6 +4340,36 @@ static ExitStatus op_trt(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_trXX(DisasContext *s, DisasOps *o) +{ +TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); +TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); +TCGv_i32 sizes = tcg_const_i32(s->insn->opc & 3); +TCGv_i32 tst = tcg_temp_new_i32(); +int m3 = get_field(s->fields, m3); + +/* XXX: the C bit in M3 should be considered as 0 when the + ETF2-enhancement facility is not installed. */ +if (m3 & 1) { +tcg_gen_movi_i32(tst, -1); +} else { +tcg_gen_extrl_i64_i32(tst, regs[0]); +if (s->insn->opc & 3) { +tcg_gen_ext8u_i32(tst, tst); +} else { +tcg_gen_ext16u_i32(tst, tst); +} +} +gen_helper_trXX(cc_op, cpu_env, r1, r2, tst, sizes); + +tcg_temp_free_i32(r1); +tcg_temp_free_i32(r2); +tcg_temp_free_i32(sizes); +tcg_temp_free_i32(tst); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_ts(DisasContext *s, DisasOps *o) { TCGv_i32 t1 = tcg_const_i32(0xff); -- 2.9.4
[Qemu-devel] [PULL v2 60/70] target/s390x: implement PACK ASCII
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-24-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 35 +++ target/s390x/translate.c | 16 4 files changed, 54 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 8ce5e3f..61f3ead 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -86,6 +86,7 @@ DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) +DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index d16857a..a5063a4 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -665,6 +665,8 @@ /* Really format SS_b, but we pack both lengths into one argument for the helper call, so we might as well leave one 8-bit field. */ C(0xf200, PACK,SS_a, Z, la1, a2, 0, 0, pack, 0) +/* PACK ASCII */ +C(0xe900, PKA, SS_f, E2, la1, a2, 0, 0, pka, 0) /* PREFETCH */ /* Implemented as nops of course. */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 581f107..4cf96c8 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -914,6 +914,41 @@ void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) } } +void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, + uint32_t srclen) +{ +uintptr_t ra = GETPC(); +int i; +/* The destination operand is always 16 bytes long. */ +const int destlen = 16; + +/* The operands are processed from right to left. */ +src += srclen - 1; +dest += destlen - 1; + +for (i = 0; i < destlen; i++) { +uint8_t b = 0; + +/* Start with a positive sign */ +if (i == 0) { +b = 0xc; +} else if (srclen > 1) { +b = cpu_ldub_data_ra(env, src, ra) & 0x0f; +src--; +srclen--; +} + +if (srclen > 1) { +b |= cpu_ldub_data_ra(env, src, ra) << 4; +src--; +srclen--; +} + +cpu_stb_data_ra(env, dest, b, ra); +dest--; +} +} + void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 4f1a50e..4939311 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3299,6 +3299,22 @@ static ExitStatus op_pack(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_pka(DisasContext *s, DisasOps *o) +{ +int l2 = get_field(s->fields, l2) + 1; +TCGv_i32 l; + +/* The length must not exceed 32 bytes. */ +if (l2 > 32) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} +l = tcg_const_i32(l2); +gen_helper_pka(cpu_env, o->addr1, o->in2, l); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_popcnt(DisasContext *s, DisasOps *o) { gen_helper_popcnt(o->out, o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 55/70] target/s390x: implement COMPARE LOGICAL LONG
From: Aurelien JarnoAs CLCL and CLCLE mostly differ by their operands, use a common do_clcl helper. Another difference is that CLCL is not interruptible. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-19-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 82 +- target/s390x/translate.c | 21 4 files changed, 83 insertions(+), 23 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index a537e51..a06e276 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -6,6 +6,7 @@ DEF_HELPER_FLAGS_4(mvc, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvcin, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_3(mvcl, i32, env, i32, i32) +DEF_HELPER_3(clcl, i32, env, i32, i32) DEF_HELPER_FLAGS_4(clm, TCG_CALL_NO_WG, i32, env, i32, i32, i64) DEF_HELPER_FLAGS_3(divs32, TCG_CALL_NO_WG, s64, env, s64, s64) DEF_HELPER_FLAGS_3(divu32, TCG_CALL_NO_WG, i64, env, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 7fb2e25..e30b1b9 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -216,6 +216,8 @@ C(0xc60e, CLGFRL, RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu64) C(0xc607, CLHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32) C(0xc606, CLGHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64) +/* COMPARE LOGICAL LONG */ +C(0x0f00, CLCL,RR_a, Z, 0, 0, 0, 0, clcl, 0) /* COMPARE LOGICAL LONG EXTENDED */ C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0) /* COMPARE LOGICAL CHARACTERS UNDER MASK */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index e30020c..4ed0b65 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -661,17 +661,14 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, return cc; } -/* compare logical long extended memcompare insn with padding */ -uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, - uint32_t r3) +/* compare logical long helper */ +static inline uint32_t do_clcl(CPUS390XState *env, + uint64_t *src1, uint64_t *src1len, + uint64_t *src3, uint64_t *src3len, + uint8_t pad, uint64_t limit, + uintptr_t ra) { -uintptr_t ra = GETPC(); -uint64_t src1len = get_length(env, r1 + 1); -uint64_t src1 = get_address(env, r1); -uint64_t src3len = get_length(env, r3 + 1); -uint64_t src3 = get_address(env, r3); -uint8_t pad = a2 & 0xff; -uint64_t len = MAX(src1len, src3len); +uint64_t len = MAX(*src1len, *src3len); uint32_t cc = 0; if (!len) { @@ -679,9 +676,9 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, } /* Lest we fail to service interrupts in a timely manner, limit the - amount of work we're willing to do. For now, let's cap at 8k. */ -if (len > 0x2000) { -len = 0x2000; + amount of work we're willing to do. */ +if (len > limit) { +len = limit; cc = 3; } @@ -689,11 +686,11 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint8_t v1 = pad; uint8_t v3 = pad; -if (src1len) { -v1 = cpu_ldub_data_ra(env, src1, ra); +if (*src1len) { +v1 = cpu_ldub_data_ra(env, *src1, ra); } -if (src3len) { -v3 = cpu_ldub_data_ra(env, src3, ra); +if (*src3len) { +v3 = cpu_ldub_data_ra(env, *src3, ra); } if (v1 != v3) { @@ -701,16 +698,55 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, break; } -if (src1len) { -src1++; -src1len--; +if (*src1len) { +*src1 += 1; +*src1len -= 1; } -if (src3len) { -src3++; -src3len--; +if (*src3len) { +*src3 += 1; +*src3len -= 1; } } +return cc; +} + + +/* compare logical long */ +uint32_t HELPER(clcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) +{ +uintptr_t ra = GETPC(); +uint64_t src1len = extract64(env->regs[r1 + 1], 0, 24); +uint64_t src1 = get_address(env, r1); +uint64_t src3len = extract64(env->regs[r2 + 1], 0, 24); +uint64_t src3 = get_address(env, r2); +uint8_t pad = env->regs[r2 + 1] >> 24; +uint32_t cc; + +cc = do_clcl(env, , , , , pad, -1, ra); + +env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, src1len); +env->regs[r2 + 1] =
[Qemu-devel] [PULL v2 59/70] target/s390x: implement MOVE LONG UNICODE
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-23-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 47 -- target/s390x/translate.c | 21 + 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index b672c3b..8ce5e3f 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -23,6 +23,7 @@ DEF_HELPER_4(ex, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) +DEF_HELPER_4(mvclu, i32, env, i32, i64, i32) DEF_HELPER_4(clcle, i32, env, i32, i64, i32) DEF_HELPER_4(clclu, i32, env, i32, i64, i32) DEF_HELPER_3(cegb, i64, env, s64, i32) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index a6aaf50..d16857a 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -580,6 +580,8 @@ C(0x0e00, MVCL,RR_a, Z, 0, 0, 0, 0, mvcl, 0) /* MOVE LONG EXTENDED */ C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0) +/* MOVE LONG UNICODE */ +C(0xeb8e, MVCLU, RSY_a, E2, 0, a2, 0, 0, mvclu, 0) /* MOVE NUMERICS */ C(0xd100, MVN, SS_a, Z, la1, a2, 0, 0, mvn, 0) /* MOVE PAGE */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 4a7c66c..581f107 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -606,7 +606,7 @@ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) static inline uint32_t do_mvcl(CPUS390XState *env, uint64_t *dest, uint64_t *destlen, uint64_t *src, uint64_t *srclen, - uint8_t pad, uintptr_t ra) + uint16_t pad, int wordsize, uintptr_t ra) { uint64_t len = MIN(*srclen, *destlen); uint32_t cc; @@ -627,9 +627,22 @@ static inline uint32_t do_mvcl(CPUS390XState *env, *destlen -= len; /* Pad the remaining area */ -fast_memset(env, *dest, pad, *destlen, ra); -*dest += *destlen; -*destlen = 0; +if (wordsize == 1) { +fast_memset(env, *dest, pad, *destlen, ra); +*dest += *destlen; +*destlen = 0; +} else { +/* If remaining length is odd, pad with odd byte first. */ +if (*destlen & 1) { +cpu_stb_data_ra(env, *dest, pad & 0xff, ra); +*dest += 1; +*destlen -= 1; +} +/* The remaining length is even, pad using words. */ +for (; *destlen; *dest += 2, *destlen -= 2) { +cpu_stw_data_ra(env, *dest, pad, ra); +} +} return cc; } @@ -645,7 +658,7 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) uint8_t pad = env->regs[r2 + 1] >> 24; uint32_t cc; -cc = do_mvcl(env, , , , , pad, ra); +cc = do_mvcl(env, , , , , pad, 1, ra); env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen); env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen); @@ -667,7 +680,29 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint8_t pad = a2; uint32_t cc; -cc = do_mvcl(env, , , , , pad, ra); +cc = do_mvcl(env, , , , , pad, 1, ra); + +set_length(env, r1 + 1, destlen); +set_length(env, r3 + 1, srclen); +set_address(env, r1, dest); +set_address(env, r3, src); + +return cc; +} + +/* move long unicode */ +uint32_t HELPER(mvclu)(CPUS390XState *env, uint32_t r1, uint64_t a2, + uint32_t r3) +{ +uintptr_t ra = GETPC(); +uint64_t destlen = get_length(env, r1 + 1); +uint64_t dest = get_address(env, r1); +uint64_t srclen = get_length(env, r3 + 1); +uint64_t src = get_address(env, r3); +uint16_t pad = a2; +uint32_t cc; + +cc = do_mvcl(env, , , , , pad, 2, ra); set_length(env, r1 + 1, destlen); set_length(env, r3 + 1, srclen); diff --git a/target/s390x/translate.c b/target/s390x/translate.c index d371d45..4f1a50e 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3041,6 +3041,27 @@ static ExitStatus op_mvcle(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_mvclu(DisasContext *s, DisasOps *o) +{ +int r1 = get_field(s->fields, r1); +int r3 = get_field(s->fields, r3); +TCGv_i32 t1, t3; + +/* r1 and r3 must be even. */ +if (r1 & 1 || r3 & 1) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} + +t1 = tcg_const_i32(r1); +t3 = tcg_const_i32(r3); +gen_helper_mvclu(cc_op, cpu_env, t1,
[Qemu-devel] [PULL v2 54/70] target/s390x: fix COMPARE LOGICAL LONG EXTENDED
From: Aurelien JarnoThere are multiple issues with the COMPARE LOGICAL LONG EXTENDED instruction: - The test between the two operands is inverted, leading to an inversion of the cc values 1 and 2. - The address and length of an operand continue to be decreased after reaching the end of this operand. These values are then wrong write back to the registers. - We should limit the amount of bytes to process, so that interrupts can be served correctly. At the same time rename dest into src1 and src into src3 to match the operand names and make the code less confusing. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-18-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 54 --- target/s390x/translate.c | 20 +- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 83c32c4..e30020c 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -666,35 +666,55 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { uintptr_t ra = GETPC(); -uint64_t destlen = get_length(env, r1 + 1); -uint64_t dest = get_address(env, r1); -uint64_t srclen = get_length(env, r3 + 1); -uint64_t src = get_address(env, r3); +uint64_t src1len = get_length(env, r1 + 1); +uint64_t src1 = get_address(env, r1); +uint64_t src3len = get_length(env, r3 + 1); +uint64_t src3 = get_address(env, r3); uint8_t pad = a2 & 0xff; +uint64_t len = MAX(src1len, src3len); uint32_t cc = 0; -if (!(destlen || srclen)) { +if (!len) { return cc; } -if (srclen > destlen) { -srclen = destlen; +/* Lest we fail to service interrupts in a timely manner, limit the + amount of work we're willing to do. For now, let's cap at 8k. */ +if (len > 0x2000) { +len = 0x2000; +cc = 3; } -for (; destlen || srclen; src++, dest++, destlen--, srclen--) { -uint8_t v1 = srclen ? cpu_ldub_data_ra(env, src, ra) : pad; -uint8_t v2 = destlen ? cpu_ldub_data_ra(env, dest, ra) : pad; -if (v1 != v2) { -cc = (v1 < v2) ? 1 : 2; +for (; len; len--) { +uint8_t v1 = pad; +uint8_t v3 = pad; + +if (src1len) { +v1 = cpu_ldub_data_ra(env, src1, ra); +} +if (src3len) { +v3 = cpu_ldub_data_ra(env, src3, ra); +} + +if (v1 != v3) { +cc = (v1 < v3) ? 1 : 2; break; } + +if (src1len) { +src1++; +src1len--; +} +if (src3len) { +src3++; +src3len--; +} } -set_length(env, r1 + 1, destlen); -/* can't use srclen here, we trunc'ed it */ -set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); -set_address(env, r1, dest); -set_address(env, r3, src); +set_length(env, r1 + 1, src1len); +set_length(env, r3 + 1, src3len); +set_address(env, r1, src1); +set_address(env, r3, src3); return cc; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index a21de09..ecd0a91 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1922,11 +1922,21 @@ static ExitStatus op_clc(DisasContext *s, DisasOps *o) static ExitStatus op_clcle(DisasContext *s, DisasOps *o) { -TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); -TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3); -tcg_temp_free_i32(r1); -tcg_temp_free_i32(r3); +int r1 = get_field(s->fields, r1); +int r3 = get_field(s->fields, r3); +TCGv_i32 t1, t3; + +/* r1 and r3 must be even. */ +if (r1 & 1 || r3 & 1) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} + +t1 = tcg_const_i32(r1); +t3 = tcg_const_i32(r3); +gen_helper_clcle(cc_op, cpu_env, t1, o->in2, t3); +tcg_temp_free_i32(t1); +tcg_temp_free_i32(t3); set_cc_static(s); return NO_EXIT; } -- 2.9.4
Re: [Qemu-devel] [PATCH] target/m68k: implement rtd
On 06/05/2017 03:00 AM, Laurent Vivier wrote: Add "Return and Deallocate" (rtd) instruction. RTD #d (SP) -> PC SP + 4 + d -> SP Signed-off-by: Laurent Vivier--- target/m68k/cpu.c | 2 ++ target/m68k/cpu.h | 1 + target/m68k/translate.c | 11 +++ 3 files changed, 14 insertions(+) Reviewed-by: Richard Henderson r~
[Qemu-devel] [PULL v2 58/70] target/s390x: implement COMPARE LOGICAL LONG UNICODE
From: Aurelien JarnoFor that we need to make program_interrupt available to qemu-user. Fortunately there is almost nothing to change as both kvm_enabled and CONFIG_KVM evaluate to false in that case. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-22-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 76 ++ target/s390x/misc_helper.c | 4 +-- target/s390x/translate.c | 22 ++ 5 files changed, 90 insertions(+), 15 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index a06e276..b672c3b 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -24,6 +24,7 @@ DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) DEF_HELPER_4(clcle, i32, env, i32, i64, i32) +DEF_HELPER_4(clclu, i32, env, i32, i64, i32) DEF_HELPER_3(cegb, i64, env, s64, i32) DEF_HELPER_3(cdgb, i64, env, s64, i32) DEF_HELPER_3(cxgb, i64, env, s64, i32) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index e30b1b9..a6aaf50 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -220,6 +220,8 @@ C(0x0f00, CLCL,RR_a, Z, 0, 0, 0, 0, clcl, 0) /* COMPARE LOGICAL LONG EXTENDED */ C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0) +/* COMPARE LOGICAL LONG UNICODE */ +C(0xeb8f, CLCLU, RSY_a, E2, 0, a2, 0, 0, clclu, 0) /* COMPARE LOGICAL CHARACTERS UNDER MASK */ C(0xbd00, CLM, RS_b, Z, r1_o, a2, 0, 0, clm, 0) C(0xeb21, CLMY,RSY_b, LD, r1_o, a2, 0, 0, clm, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 3b2ff09..4a7c66c 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -67,6 +67,32 @@ static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr) return len; } +/* Trigger a SPECIFICATION exception if an address or a length is not + naturally aligned. */ +static inline void check_alignment(CPUS390XState *env, uint64_t v, + int wordsize, uintptr_t ra) +{ +if (v % wordsize) { +CPUState *cs = CPU(s390_env_get_cpu(env)); +cpu_restore_state(cs, ra); +program_interrupt(env, PGM_SPECIFICATION, 6); +} +} + +/* Load a value from memory according to its size. */ +static inline uint64_t cpu_ldusize_data_ra(CPUS390XState *env, uint64_t addr, + int wordsize, uintptr_t ra) +{ +switch (wordsize) { +case 1: +return cpu_ldub_data_ra(env, addr, ra); +case 2: +return cpu_lduw_data_ra(env, addr, ra); +default: +abort(); +} +} + static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, uint32_t l, uintptr_t ra) { @@ -655,12 +681,14 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, static inline uint32_t do_clcl(CPUS390XState *env, uint64_t *src1, uint64_t *src1len, uint64_t *src3, uint64_t *src3len, - uint8_t pad, uint64_t limit, - uintptr_t ra) + uint16_t pad, uint64_t limit, + int wordsize, uintptr_t ra) { uint64_t len = MAX(*src1len, *src3len); uint32_t cc = 0; +check_alignment(env, *src1len | *src3len, wordsize, ra); + if (!len) { return cc; } @@ -672,15 +700,15 @@ static inline uint32_t do_clcl(CPUS390XState *env, cc = 3; } -for (; len; len--) { -uint8_t v1 = pad; -uint8_t v3 = pad; +for (; len; len -= wordsize) { +uint16_t v1 = pad; +uint16_t v3 = pad; if (*src1len) { -v1 = cpu_ldub_data_ra(env, *src1, ra); +v1 = cpu_ldusize_data_ra(env, *src1, wordsize, ra); } if (*src3len) { -v3 = cpu_ldub_data_ra(env, *src3, ra); +v3 = cpu_ldusize_data_ra(env, *src3, wordsize, ra); } if (v1 != v3) { @@ -689,12 +717,12 @@ static inline uint32_t do_clcl(CPUS390XState *env, } if (*src1len) { -*src1 += 1; -*src1len -= 1; +*src1 += wordsize; +*src1len -= wordsize; } if (*src3len) { -*src3 += 1; -*src3len -= 1; +*src3 += wordsize; +*src3len -= wordsize; } } @@ -713,7 +741,7 @@ uint32_t HELPER(clcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) uint8_t pad = env->regs[r2 + 1] >> 24; uint32_t cc; -cc = do_clcl(env, , , , , pad, -1,
[Qemu-devel] [PULL v2 53/70] target/s390x: improve 24-bit and 31-bit lengths read/write
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-17-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 47 +-- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 5f11e1e..83c32c4 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -407,6 +407,31 @@ static inline void set_address(CPUS390XState *env, int reg, uint64_t address) } } +static inline uint64_t wrap_length(CPUS390XState *env, uint64_t length) +{ +if (!(env->psw.mask & PSW_MASK_64)) { +/* 24-Bit and 31-Bit mode */ +length &= 0x7fff; +} +return length; +} + +static inline uint64_t get_length(CPUS390XState *env, int reg) +{ +return wrap_length(env, env->regs[reg]); +} + +static inline void set_length(CPUS390XState *env, int reg, uint64_t length) +{ +if (env->psw.mask & PSW_MASK_64) { +/* 64-Bit mode */ +env->regs[reg] = length; +} else { +/* 24-Bit and 31-Bit mode */ +env->regs[reg] = deposit64(env->regs[reg], 0, 32, length); +} +} + /* search string (c is byte to search, r2 is string, r1 end of string) */ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, uint64_t str) @@ -598,19 +623,14 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { uintptr_t ra = GETPC(); -uint64_t destlen = env->regs[r1 + 1]; +uint64_t destlen = get_length(env, r1 + 1); uint64_t dest = get_address(env, r1); -uint64_t srclen = env->regs[r3 + 1]; +uint64_t srclen = get_length(env, r3 + 1); uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint8_t v; uint32_t cc; -if (!(env->psw.mask & PSW_MASK_64)) { -destlen = (uint32_t)destlen; -srclen = (uint32_t)srclen; -} - if (destlen == srclen) { cc = 0; } else if (destlen < srclen) { @@ -632,10 +652,9 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, cpu_stb_data_ra(env, dest, pad, ra); } -env->regs[r1 + 1] = destlen; +set_length(env, r1 + 1 , destlen); /* can't use srclen here, we trunc'ed it */ -/* FIXME: 31-bit mode! */ -env->regs[r3 + 1] -= src - env->regs[r3]; +set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); set_address(env, r1, dest); set_address(env, r3, src); @@ -647,9 +666,9 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { uintptr_t ra = GETPC(); -uint64_t destlen = env->regs[r1 + 1]; +uint64_t destlen = get_length(env, r1 + 1); uint64_t dest = get_address(env, r1); -uint64_t srclen = env->regs[r3 + 1]; +uint64_t srclen = get_length(env, r3 + 1); uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint32_t cc = 0; @@ -671,9 +690,9 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, } } -env->regs[r1 + 1] = destlen; +set_length(env, r1 + 1, destlen); /* can't use srclen here, we trunc'ed it */ -env->regs[r3 + 1] -= src - env->regs[r3]; +set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); set_address(env, r1, dest); set_address(env, r3, src); -- 2.9.4
Re: [Qemu-devel] [PATCH v4 0/3] target/s390x: implement loads/store quadword
On 06/04/2017 01:20 PM, Aurelien Jarno wrote: This patchset implements the LOAD PAIR FROM QUADWORD and STORE PAIR TO QUADWORD instructions. The corresponding patches have been in my previous patchset and the pull request from Richard, but they failed to build on a host without atomic128 support. This new version fixes that. It has to be applied over the pull request as it makes uses of the check_alignment function. Finally the latest patch fixes a lack of alignement check in CDSG, discovered as I used it as an example about how to properly handle hosts without atomic128 support. Aurelien Jarno (3): target/s390x: implement LOAD PAIR FROM QUADWORD target/s390x: implement STORE PAIR TO QUADWORD target/s390x: check alignment in CDSG in the !CONFIG_ATOMIC128 case target/s390x/helper.h | 2 ++ target/s390x/insn-data.def | 4 target/s390x/mem_helper.c | 53 ++ target/s390x/translate.c | 13 4 files changed, 72 insertions(+) Thanks. Incorporated into my v2 pull. r~
[Qemu-devel] [PULL v2 57/70] target/s390x: improve MOVE LONG and MOVE LONG EXTENDED
From: Aurelien JarnoAs MVCL and MVCLE only differ by their operands, use a common do_mvcl helper. Optimize it calling fast_memmove and fast_memset. Correctly write back addresses. Check that r1 and r2/r3 registers are even. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-21-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 90 +-- target/s390x/translate.c | 40 +++-- 2 files changed, 70 insertions(+), 60 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 2326f0b..3b2ff09 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -576,49 +576,60 @@ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) } } -/* move long */ -uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) +/* move long helper */ +static inline uint32_t do_mvcl(CPUS390XState *env, + uint64_t *dest, uint64_t *destlen, + uint64_t *src, uint64_t *srclen, + uint8_t pad, uintptr_t ra) { -uintptr_t ra = GETPC(); -uint64_t destlen = env->regs[r1 + 1] & 0xff; -uint64_t dest = get_address(env, r1); -uint64_t srclen = env->regs[r2 + 1] & 0xff; -uint64_t src = get_address(env, r2); -uint8_t pad = env->regs[r2 + 1] >> 24; -uint8_t v; +uint64_t len = MIN(*srclen, *destlen); uint32_t cc; -if (destlen == srclen) { +if (*destlen == *srclen) { cc = 0; -} else if (destlen < srclen) { +} else if (*destlen < *srclen) { cc = 1; } else { cc = 2; } -if (srclen > destlen) { -srclen = destlen; -} +/* Copy the src array */ +fast_memmove(env, *dest, *src, len, ra); +*src += len; +*srclen -= len; +*dest += len; +*destlen -= len; -for (; destlen && srclen; src++, dest++, destlen--, srclen--) { -v = cpu_ldub_data_ra(env, src, ra); -cpu_stb_data_ra(env, dest, v, ra); -} +/* Pad the remaining area */ +fast_memset(env, *dest, pad, *destlen, ra); +*dest += *destlen; +*destlen = 0; -for (; destlen; dest++, destlen--) { -cpu_stb_data_ra(env, dest, pad, ra); -} +return cc; +} -env->regs[r1 + 1] = destlen; -/* can't use srclen here, we trunc'ed it */ -env->regs[r2 + 1] -= src - env->regs[r2]; +/* move long */ +uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) +{ +uintptr_t ra = GETPC(); +uint64_t destlen = env->regs[r1 + 1] & 0xff; +uint64_t dest = get_address(env, r1); +uint64_t srclen = env->regs[r2 + 1] & 0xff; +uint64_t src = get_address(env, r2); +uint8_t pad = env->regs[r2 + 1] >> 24; +uint32_t cc; + +cc = do_mvcl(env, , , , , pad, ra); + +env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen); +env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen); set_address(env, r1, dest); set_address(env, r2, src); return cc; } -/* move long extended another memcopy insn with more bells and whistles */ +/* move long extended */ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { @@ -627,34 +638,13 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint64_t dest = get_address(env, r1); uint64_t srclen = get_length(env, r3 + 1); uint64_t src = get_address(env, r3); -uint8_t pad = a2 & 0xff; -uint8_t v; +uint8_t pad = a2; uint32_t cc; -if (destlen == srclen) { -cc = 0; -} else if (destlen < srclen) { -cc = 1; -} else { -cc = 2; -} - -if (srclen > destlen) { -srclen = destlen; -} - -for (; destlen && srclen; src++, dest++, destlen--, srclen--) { -v = cpu_ldub_data_ra(env, src, ra); -cpu_stb_data_ra(env, dest, v, ra); -} - -for (; destlen; dest++, destlen--) { -cpu_stb_data_ra(env, dest, pad, ra); -} +cc = do_mvcl(env, , , , , pad, ra); -set_length(env, r1 + 1 , destlen); -/* can't use srclen here, we trunc'ed it */ -set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); +set_length(env, r1 + 1, destlen); +set_length(env, r3 + 1, srclen); set_address(env, r1, dest); set_address(env, r3, src); diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 2d47f1d..c131f67 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2979,22 +2979,42 @@ static ExitStatus op_mvcin(DisasContext *s, DisasOps *o) static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) { -TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); -TCGv_i32 r2 = tcg_const_i32(get_field(s->fields,
Re: [Qemu-devel] [PATCH v1] virtio-net: enable configurable tx queue size
On 06/05/2017 11:38 PM, Michael S. Tsirkin wrote: On Mon, Jun 05, 2017 at 04:57:29PM +0800, Wei Wang wrote: This patch enables the virtio-net tx queue size to be configurable between 256 and 1024 by the user. The queue size specified by the user should be power of 2. If "tx_queue_size" is not offered by the user, the default queue size, 1024, will be used. For the traditional QEMU backend, setting the tx queue size to be 1024 requires the guest virtio driver to support the VIRTIO_F_MAX_CHAIN_SIZE feature. This feature restricts the guest driver from chaining 1024 vring descriptors, which may cause the device side implementation to send more than 1024 iov to writev. VIRTIO_F_MAX_CHAIN_SIZE is a common transport feature added for all virtio devices. However, each device has the flexibility to set the max chain size to limit its driver to chain vring descriptors. Currently, the max chain size of the virtio-net device is set to 1023. In the case that the tx queue size is set to 1024 and the VIRTIO_F_MAX_CHAIN_SIZE feature is not supported by the guest driver, the tx queue size will be reconfigured to be 512. I'd like to see the reverse. Start with the current default. If VIRTIO_F_MAX_CHAIN_SIZE is negotiated, increase the queue size. OK, we can let the queue size start with 256, and how about increasing it to 1024 in the following two cases: 1) VIRTIO_F_MAX_CHAIN_SIZE is negotiated; or 2) the backend is vhost. Best, Wei
[Qemu-devel] [PULL v2 45/70] target/s390x: implement PACK
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-7-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 5 + target/s390x/mem_helper.c | 37 + target/s390x/translate.c | 8 4 files changed, 51 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 3f5a05d..c6fbc3b 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -75,6 +75,7 @@ DEF_HELPER_FLAGS_2(sqeb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) +DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 170b50e..f92bfde 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -639,6 +639,11 @@ C(0x9600, OI, SI,Z, m1_8u, i2_8u, new, m1_8, or, nz64) C(0xeb56, OIY, SIY, LD, m1_8u, i2_8u, new, m1_8, or, nz64) +/* PACK */ +/* Really format SS_b, but we pack both lengths into one argument + for the helper call, so we might as well leave one 8-bit field. */ +C(0xf200, PACK,SS_a, Z, la1, a2, 0, 0, pack, 0) + /* PREFETCH */ /* Implemented as nops of course. */ C(0xe336, PFD, RXY_b, GIE, 0, 0, 0, 0, 0, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index ddbebcd..850472e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -644,6 +644,43 @@ uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1, return len; } +void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int len_dest = len >> 4; +int len_src = len & 0xf; +uint8_t b; + +dest += len_dest; +src += len_src; + +/* last byte is special, it only flips the nibbles */ +b = cpu_ldub_data_ra(env, src, ra); +cpu_stb_data_ra(env, dest, (b << 4) | (b >> 4), ra); +src--; +len_src--; + +/* now pack every value */ +while (len_dest >= 0) { +b = 0; + +if (len_src > 0) { +b = cpu_ldub_data_ra(env, src, ra) & 0x0f; +src--; +len_src--; +} +if (len_src > 0) { +b |= cpu_ldub_data_ra(env, src, ra) << 4; +src--; +len_src--; +} + +len_dest--; +dest--; +cpu_stb_data_ra(env, dest, b, ra); +} +} + void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 854a66a..b3cc349 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3144,6 +3144,14 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_pack(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_pack(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_popcnt(DisasContext *s, DisasOps *o) { gen_helper_popcnt(o->out, o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 68/70] target/s390x: check alignment in CDSG in the !CONFIG_ATOMIC128 case
From: Aurelien JarnoThe CDSG instruction requires a 16-byte alignement, as expressed in the MO_ALIGN_16 passed to helper_atomic_cmpxchgo_be_mmu. In the non parallel case, use check_alignment to enforce this. Signed-off-by: Aurelien Jarno Message-Id: <20170604202034.16615-4-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index a8988e0..80caab9 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1262,6 +1262,8 @@ void HELPER(cdsg)(CPUS390XState *env, uint64_t addr, } else { uint64_t oldh, oldl; +check_alignment(env, addr, 16, ra); + oldh = cpu_ldq_data_ra(env, addr + 0, ra); oldl = cpu_ldq_data_ra(env, addr + 8, ra); -- 2.9.4
[Qemu-devel] [PULL v2 52/70] target/s390x: improve 24-bit and 31-bit addresses write
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-16-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 37 ++--- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index aba26be..5f11e1e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -384,6 +384,29 @@ static inline uint64_t get_address(CPUS390XState *env, int reg) return wrap_address(env, env->regs[reg]); } +static inline void set_address(CPUS390XState *env, int reg, uint64_t address) +{ +if (env->psw.mask & PSW_MASK_64) { +/* 64-Bit mode */ +env->regs[reg] = address; +} else { +if (!(env->psw.mask & PSW_MASK_32)) { +/* 24-Bit mode. According to the PoO it is implementation +dependent if bits 32-39 remain unchanged or are set to +zeros. Choose the former so that the function can also be +used for TRT. */ +env->regs[reg] = deposit64(env->regs[reg], 0, 24, address); +} else { +/* 31-Bit mode. According to the PoO it is implementation +dependent if bit 32 remains unchanged or is set to zero. +Choose the latter so that the function can also be used for +TRT. */ +address &= 0x7fff; +env->regs[reg] = deposit64(env->regs[reg], 0, 32, address); +} +} +} + /* search string (c is byte to search, r2 is string, r1 end of string) */ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, uint64_t str) @@ -564,8 +587,8 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) env->regs[r1 + 1] = destlen; /* can't use srclen here, we trunc'ed it */ env->regs[r2 + 1] -= src - env->regs[r2]; -env->regs[r1] = dest; -env->regs[r2] = src; +set_address(env, r1, dest); +set_address(env, r2, src); return cc; } @@ -613,8 +636,8 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, /* can't use srclen here, we trunc'ed it */ /* FIXME: 31-bit mode! */ env->regs[r3 + 1] -= src - env->regs[r3]; -env->regs[r1] = dest; -env->regs[r3] = src; +set_address(env, r1, dest); +set_address(env, r3, src); return cc; } @@ -651,8 +674,8 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, env->regs[r1 + 1] = destlen; /* can't use srclen here, we trunc'ed it */ env->regs[r3 + 1] -= src - env->regs[r3]; -env->regs[r1] = dest; -env->regs[r3] = src; +set_address(env, r1, dest); +set_address(env, r3, src); return cc; } @@ -858,7 +881,7 @@ static uint32_t do_helper_trt(CPUS390XState *env, uint32_t len, uint64_t array, uint8_t sbyte = cpu_ldub_data_ra(env, trans + byte, ra); if (sbyte != 0) { -env->regs[1] = array + i; +set_address(env, 1, array + i); env->regs[2] = deposit64(env->regs[2], 0, 8, sbyte); return (i == len) ? 2 : 1; } -- 2.9.4
[Qemu-devel] [PULL v2 42/70] target/s390x: implement local-TLB-clearing in IPTE
From: Aurelien JarnoAnd at the same time make IPTE SMP aware. Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-4-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 2 +- target/s390x/mem_helper.c | 21 + target/s390x/translate.c | 6 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index cc451c7..3f5a05d 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -111,7 +111,7 @@ DEF_HELPER_4(mvcs, i32, env, i64, i64, i64) DEF_HELPER_4(mvcp, i32, env, i64, i64, i64) DEF_HELPER_4(sigp, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_2(sacf, TCG_CALL_NO_WG, void, env, i64) -DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64) +DEF_HELPER_FLAGS_4(ipte, TCG_CALL_NO_RWG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(purge, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(lra, i64, env, i64) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 0ebd65d..ddbebcd 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1073,17 +1073,16 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) } /* invalidate pte */ -void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr) +void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr, + uint32_t m4) { CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t page = vaddr & TARGET_PAGE_MASK; uint64_t pte_addr, pte; -/* XXX broadcast to other CPUs */ - /* Compute the page table entry address */ pte_addr = (pto & _SEGMENT_ENTRY_ORIGIN); -pte_addr += (vaddr & _VADDR_PX) >> 9; +pte_addr += (vaddr & VADDR_PX) >> 9; /* Mark the page table entry as invalid */ pte = ldq_phys(cs->as, pte_addr); @@ -1092,13 +1091,19 @@ void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr) /* XXX we exploit the fact that Linux passes the exact virtual address here - it's not obliged to! */ -tlb_flush_page(cs, page); +/* XXX: the LC bit should be considered as 0 if the local-TLB-clearing + facility is not installed. */ +if (m4 & 1) { +tlb_flush_page(cs, page); +} else { +tlb_flush_page_all_cpus_synced(cs, page); +} /* XXX 31-bit hack */ -if (page & 0x8000) { -tlb_flush_page(cs, page & ~0x8000); +if (m4 & 1) { +tlb_flush_page(cs, page ^ 0x8000); } else { -tlb_flush_page(cs, page | 0x8000); +tlb_flush_page_all_cpus_synced(cs, page ^ 0x8000); } } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 67ddf1b..0a1b3b3 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2357,8 +2357,12 @@ static ExitStatus op_ipm(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static ExitStatus op_ipte(DisasContext *s, DisasOps *o) { +TCGv_i32 m4; + check_privileged(s); -gen_helper_ipte(cpu_env, o->in1, o->in2); +m4 = tcg_const_i32(get_field(s->fields, m4)); +gen_helper_ipte(cpu_env, o->in1, o->in2, m4); +tcg_temp_free_i32(m4); return NO_EXIT; } -- 2.9.4
[Qemu-devel] [PULL v2 51/70] target/s390x: improve 24-bit and 31-bit addresses read
From: Aurelien JarnoImprove fix_address to also handle the 24-bit mode. Rename fix_address to wrap_address to better explain what is changed. Replace the calls to get_address with x2 = 0 and b2 = 0 by call to wrap_address, leading to the removal of this function. Rename get_address_31fix into get_address. Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-15-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 71 +-- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 10754dd..aba26be 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -365,30 +365,23 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, return cc; } -static inline uint64_t fix_address(CPUS390XState *env, uint64_t a) +static inline uint64_t wrap_address(CPUS390XState *env, uint64_t a) { -/* 31-Bit mode */ if (!(env->psw.mask & PSW_MASK_64)) { -a &= 0x7fff; +if (!(env->psw.mask & PSW_MASK_32)) { +/* 24-Bit mode */ +a &= 0x00ff; +} else { +/* 31-Bit mode */ +a &= 0x7fff; +} } return a; } -static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2) -{ -uint64_t r = d2; -if (x2) { -r += env->regs[x2]; -} -if (b2) { -r += env->regs[b2]; -} -return fix_address(env, r); -} - -static inline uint64_t get_address_31fix(CPUS390XState *env, int reg) +static inline uint64_t get_address(CPUS390XState *env, int reg) { -return fix_address(env, env->regs[reg]); +return wrap_address(env, env->regs[reg]); } /* search string (c is byte to search, r2 is string, r1 end of string) */ @@ -399,8 +392,8 @@ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, uint32_t len; uint8_t v, c = r0; -str = fix_address(env, str); -end = fix_address(env, end); +str = wrap_address(env, str); +end = wrap_address(env, end); /* Assume for now that R2 is unmodified. */ env->retxl = str; @@ -434,8 +427,8 @@ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2) uint32_t len; c = c & 0xff; -s1 = fix_address(env, s1); -s2 = fix_address(env, s2); +s1 = wrap_address(env, s1); +s2 = wrap_address(env, s2); /* Lest we fail to service interrupts in a timely manner, limit the amount of work we're willing to do. For now, let's cap at 8k. */ @@ -481,8 +474,8 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s) uint32_t len; c = c & 0xff; -d = fix_address(env, d); -s = fix_address(env, s); +d = wrap_address(env, d); +s = wrap_address(env, s); /* Lest we fail to service interrupts in a timely manner, limit the amount of work we're willing to do. For now, let's cap at 8k. */ @@ -540,9 +533,9 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) { uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1] & 0xff; -uint64_t dest = get_address_31fix(env, r1); +uint64_t dest = get_address(env, r1); uint64_t srclen = env->regs[r2 + 1] & 0xff; -uint64_t src = get_address_31fix(env, r2); +uint64_t src = get_address(env, r2); uint8_t pad = env->regs[r2 + 1] >> 24; uint8_t v; uint32_t cc; @@ -583,9 +576,9 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, { uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1]; -uint64_t dest = env->regs[r1]; +uint64_t dest = get_address(env, r1); uint64_t srclen = env->regs[r3 + 1]; -uint64_t src = env->regs[r3]; +uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint8_t v; uint32_t cc; @@ -593,8 +586,6 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, if (!(env->psw.mask & PSW_MASK_64)) { destlen = (uint32_t)destlen; srclen = (uint32_t)srclen; -dest &= 0x7fff; -src &= 0x7fff; } if (destlen == srclen) { @@ -634,9 +625,9 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, { uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1]; -uint64_t dest = get_address_31fix(env, r1); +uint64_t dest = get_address(env, r1); uint64_t srclen = env->regs[r3 + 1]; -uint64_t src = get_address_31fix(env, r3); +uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint32_t cc = 0; @@ -1020,7 +1011,7 @@ uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) uint64_t abs_addr; int i; -
[Qemu-devel] [PULL v2 49/70] target/s390x: implement MOVE WITH OFFSET
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-13-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 4 target/s390x/mem_helper.c | 31 +++ target/s390x/translate.c | 8 4 files changed, 44 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 5780bb5..385ce9a 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -14,6 +14,7 @@ DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64) DEF_HELPER_4(srst, i64, env, i64, i64, i64) DEF_HELPER_4(clst, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64) +DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) DEF_HELPER_4(ex, void, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index cbb91bb..45aaf11 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -582,6 +582,10 @@ C(0xb254, MVPG,RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0) /* MOVE STRING */ C(0xb255, MVST,RRE, Z, r1_o, r2_o, 0, 0, mvst, 0) +/* MOVE WITH OFFSET */ +/* Really format SS_b, but we pack both lengths into one argument + for the helper call, so we might as well leave one 8-bit field. */ +C(0xf100, MVO, SS_a, Z, la1, a2, 0, 0, mvo, 0) /* MULTIPLY */ C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index f80b7a5..facac4b 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -256,6 +256,37 @@ void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) } } +/* move with offset */ +void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int len_dest = l >> 4; +int len_src = l & 0xf; +uint8_t byte_dest, byte_src; +int i; + +src += len_src; +dest += len_dest; + +/* Handle rightmost byte */ +byte_src = cpu_ldub_data_ra(env, src, ra); +byte_dest = cpu_ldub_data_ra(env, dest, ra); +byte_dest = (byte_dest & 0x0f) | (byte_src << 4); +cpu_stb_data_ra(env, dest, byte_dest, ra); + +/* Process remaining bytes from right to left */ +for (i = 1; i <= len_dest; i++) { +byte_dest = byte_src >> 4; +if (len_src - i >= 0) { +byte_src = cpu_ldub_data_ra(env, src - i, ra); +} else { +byte_src = 0; +} +byte_dest |= byte_src << 4; +cpu_stb_data_ra(env, dest - i, byte_dest, ra); +} +} + /* compare unsigned byte arrays */ static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2, uintptr_t ra) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 7b42c02..7be1c70 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2996,6 +2996,14 @@ static ExitStatus op_mvn(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_mvo(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_mvo(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) { gen_helper_mvpg(cc_op, cpu_env, regs[0], o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 66/70] target/s390x: implement LOAD PAIR FROM QUADWORD
From: Aurelien JarnoSigned-off-by: Aurelien Jarno Message-Id: <20170604202034.16615-2-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 27 +++ target/s390x/translate.c | 7 +++ 4 files changed, 37 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 11a545e..054ccd6 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -103,6 +103,7 @@ DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64) DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(stfl, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(stfle, i32, env, i64) +DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64) #ifndef CONFIG_USER_ONLY DEF_HELPER_3(servc, i32, env, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 9976d29..32dee40 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -517,6 +517,8 @@ /* LOAD PAIR DISJOINT */ D(0xc804, LPD, SSF, ILA, 0, 0, new_P, r3_P32, lpd, 0, MO_TEUL) D(0xc805, LPDG,SSF, ILA, 0, 0, new_P, r3_P64, lpd, 0, MO_TEQ) +/* LOAD PAIR FROM QUADWORD */ +C(0xe38f, LPQ, RXY_a, Z, 0, a2, r1_P, 0, lpq, 0) /* LOAD POSITIVE */ C(0x1000, LPR, RR_a, Z, 0, r2_32s, new, r1_32, abs, abs32) C(0xb900, LPGR,RRE, Z, 0, r2, r1, 0, abs, abs64) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index be89cc4..f48908c 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1665,6 +1665,33 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) } #endif +/* load pair from quadword */ +uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr) +{ +uintptr_t ra = GETPC(); +uint64_t hi, lo; + +if (parallel_cpus) { +#ifndef CONFIG_ATOMIC128 +cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); +#else +int mem_idx = cpu_mmu_index(env, false); +TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx); +Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra); +hi = int128_gethi(v); +lo = int128_getlo(v); +#endif +} else { +check_alignment(env, addr, 16, ra); + +hi = cpu_ldq_data_ra(env, addr + 0, ra); +lo = cpu_ldq_data_ra(env, addr + 8, ra); +} + +env->retxl = lo; +return hi; +} + /* Execute instruction. This instruction executes an insn modified with the contents of r1. It does not change the executed instruction in memory; it does not change the program counter. diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 9f3443e..10019ed 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2909,6 +2909,13 @@ static ExitStatus op_lpd(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_lpq(DisasContext *s, DisasOps *o) +{ +gen_helper_lpq(o->out, cpu_env, o->in2); +return_low128(o->out2); +return NO_EXIT; +} + #ifndef CONFIG_USER_ONLY static ExitStatus op_lura(DisasContext *s, DisasOps *o) { -- 2.9.4
[Qemu-devel] [PULL v2 43/70] target/s390x: implement TEST AND SET
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-5-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/insn-data.def | 3 +++ target/s390x/translate.c | 10 ++ 2 files changed, 13 insertions(+) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index f818437..0f70ace 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -810,6 +810,9 @@ /* SUPERVISOR CALL */ C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 0) +/* TEST AND SET */ +C(0x9300, TS, S, Z, 0, a2, 0, 0, ts, 0) + /* TEST DATA CLASS */ C(0xed10, TCEB,RXE, Z, e1, a2, 0, 0, tceb, 0) C(0xed11, TCDB,RXE, Z, f1_o, a2, 0, 0, tcdb, 0) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 0a1b3b3..2d45132 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4134,6 +4134,16 @@ static ExitStatus op_trt(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_ts(DisasContext *s, DisasOps *o) +{ +TCGv_i32 t1 = tcg_const_i32(0xff); +tcg_gen_atomic_xchg_i32(t1, o->in2, t1, get_mem_index(s), MO_UB); +tcg_gen_extract_i32(cc_op, t1, 7, 1); +tcg_temp_free_i32(t1); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_unpk(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -- 2.9.4
[Qemu-devel] [PULL v2 50/70] target/s390x: implement MOVE ZONES
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-14-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 13 + target/s390x/translate.c | 8 4 files changed, 24 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 385ce9a..a537e51 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -16,6 +16,7 @@ DEF_HELPER_4(clst, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) +DEF_HELPER_FLAGS_4(mvz, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) DEF_HELPER_4(ex, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 45aaf11..7fb2e25 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -586,6 +586,8 @@ /* Really format SS_b, but we pack both lengths into one argument for the helper call, so we might as well leave one 8-bit field. */ C(0xf100, MVO, SS_a, Z, la1, a2, 0, 0, mvo, 0) +/* MOVE ZONES */ +C(0xd300, MVZ, SS_a, Z, la1, a2, 0, 0, mvz, 0) /* MULTIPLY */ C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index facac4b..10754dd 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -287,6 +287,19 @@ void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) } } +/* move zones */ +void HELPER(mvz)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int i; + +for (i = 0; i <= l; i++) { +uint8_t b = cpu_ldub_data_ra(env, dest + i, ra) & 0x0f; +b |= cpu_ldub_data_ra(env, src + i, ra) & 0xf0; +cpu_stb_data_ra(env, dest + i, b, ra); +} +} + /* compare unsigned byte arrays */ static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2, uintptr_t ra) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 7be1c70..a21de09 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3019,6 +3019,14 @@ static ExitStatus op_mvst(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_mvz(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_mvz(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_mul(DisasContext *s, DisasOps *o) { tcg_gen_mul_i64(o->out, o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 63/70] target/s390x: implement UNPACK UNICODE
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-27-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 49 -- target/s390x/translate.c | 18 + 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index c21be50..9d4bf64 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -90,6 +90,7 @@ DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(unpka, TCG_CALL_NO_WG, i32, env, i64, i32, i64) +DEF_HELPER_FLAGS_4(unpku, TCG_CALL_NO_WG, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) DEF_HELPER_4(trt, i32, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 1782e2f..6aa0221 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -873,6 +873,8 @@ C(0xf300, UNPK,SS_a, Z, la1, a2, 0, 0, unpk, 0) /* UNPACK ASCII */ C(0xea00, UNPKA, SS_a, E2, la1, a2, 0, 0, unpka, 0) +/* UNPACK UNICODE */ +C(0xe200, UNPKU, SS_a, E2, la1, a2, 0, 0, unpku, 0) #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b87e417..402147e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -93,6 +93,23 @@ static inline uint64_t cpu_ldusize_data_ra(CPUS390XState *env, uint64_t addr, } } +/* Store a to memory according to its size. */ +static inline void cpu_stsize_data_ra(CPUS390XState *env, uint64_t addr, + uint64_t value, int wordsize, + uintptr_t ra) +{ +switch (wordsize) { +case 1: +cpu_stb_data_ra(env, addr, value, ra); +break; +case 2: +cpu_stw_data_ra(env, addr, value, ra); +break; +default: +abort(); +} +} + static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, uint32_t l, uintptr_t ra) { @@ -1008,10 +1025,10 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, } } -uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, - uint64_t src) +static inline uint32_t do_unpkau(CPUS390XState *env, uint64_t dest, + uint32_t destlen, int dsize, uint64_t src, + uintptr_t ra) { -uintptr_t ra = GETPC(); int i; uint32_t cc; uint8_t b; @@ -1020,7 +1037,7 @@ uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, /* The operands are processed from right to left. */ src += srclen - 1; -dest += destlen - 1; +dest += destlen - dsize; /* Check for the sign. */ b = cpu_ldub_data_ra(env, src, ra); @@ -1042,23 +1059,35 @@ uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, } /* Now pad every nibble with 0x30, advancing one nibble at a time. */ -for (i = 0; i < destlen; i++) { -if (i == 31) { -/* If length is 32 bytes, the leftmost byte is 0. */ +for (i = 0; i < destlen; i += dsize) { +if (i == (31 * dsize)) { +/* If length is 32/64 bytes, the leftmost byte is 0. */ b = 0; -} else if (i % 2) { +} else if (i % (2 * dsize)) { b = cpu_ldub_data_ra(env, src, ra); src--; } else { b >>= 4; } -cpu_stb_data_ra(env, dest, 0x30 + (b & 0xf), ra); -dest--; +cpu_stsize_data_ra(env, dest, 0x30 + (b & 0xf), dsize, ra); +dest -= dsize; } return cc; } +uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, + uint64_t src) +{ +return do_unpkau(env, dest, destlen, 1, src, GETPC()); +} + +uint32_t HELPER(unpku)(CPUS390XState *env, uint64_t dest, uint32_t destlen, + uint64_t src) +{ +return do_unpkau(env, dest, destlen, 2, src, GETPC()); +} + static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t trans, uintptr_t ra) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index cd5cbd1..bba9ce8 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4366,6 +4366,24 @@ static ExitStatus op_unpka(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_unpku(DisasContext
[Qemu-devel] [PULL v2 46/70] target/s390x: implement COMPARE AND SIGNAL
From: Aurelien JarnoThese functions differ from COMPARE by generating an exception for a QNaN input. Use the non quiet version of floatXX_compare. Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-10-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/fpu_helper.c | 27 +++ target/s390x/helper.h | 3 +++ target/s390x/insn-data.def | 6 ++ target/s390x/translate.c | 21 + 4 files changed, 57 insertions(+) diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c index e604e9f..26f124f 100644 --- a/target/s390x/fpu_helper.c +++ b/target/s390x/fpu_helper.c @@ -585,6 +585,33 @@ uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3) return RET128(ret); } +/* 32-bit FP compare and signal */ +uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2) +{ +int cmp = float32_compare(f1, f2, >fpu_status); +handle_exceptions(env, GETPC()); +return float_comp_to_cc(env, cmp); +} + +/* 64-bit FP compare and signal */ +uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) +{ +int cmp = float64_compare(f1, f2, >fpu_status); +handle_exceptions(env, GETPC()); +return float_comp_to_cc(env, cmp); +} + +/* 128-bit FP compare and signal */ +uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al, + uint64_t bh, uint64_t bl) +{ +int cmp = float128_compare(make_float128(ah, al), + make_float128(bh, bl), + >fpu_status); +handle_exceptions(env, GETPC()); +return float_comp_to_cc(env, cmp); +} + /* 32-bit FP multiply and add */ uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, uint64_t f2, uint64_t f3) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index c6fbc3b..86e2bc1 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -49,6 +49,9 @@ DEF_HELPER_FLAGS_3(lexb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64) DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64) DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64) +DEF_HELPER_FLAGS_3(keb, TCG_CALL_NO_WG, i32, env, i64, i64) +DEF_HELPER_FLAGS_3(kdb, TCG_CALL_NO_WG, i32, env, i64, i64) +DEF_HELPER_FLAGS_5(kxb, TCG_CALL_NO_WG, i32, env, i64, i64, i64, i64) DEF_HELPER_FLAGS_3(cgeb, TCG_CALL_NO_WG, i64, env, i64, i32) DEF_HELPER_FLAGS_3(cgdb, TCG_CALL_NO_WG, i64, env, i64, i32) DEF_HELPER_FLAGS_4(cgxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index f92bfde..39fcce5 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -154,6 +154,12 @@ C(0xb349, CXBR,RRE, Z, x1_o, x2_o, 0, 0, cxb, 0) C(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0) C(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0) +/* COMPARE AND SIGNAL */ +C(0xb308, KEBR,RRE, Z, e1, e2, 0, 0, keb, 0) +C(0xb318, KDBR,RRE, Z, f1_o, f2_o, 0, 0, kdb, 0) +C(0xb348, KXBR,RRE, Z, x1_o, x2_o, 0, 0, kxb, 0) +C(0xed08, KEB, RXE, Z, e1, m2_32u, 0, 0, keb, 0) +C(0xed18, KDB, RXE, Z, f1_o, m2_64, 0, 0, kdb, 0) /* COMPARE IMMEDIATE */ C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32) C(0xc20c, CGFI,RIL_a, EI, r1, i2, 0, 0, 0, cmps64) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index b3cc349..0a35eed 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2374,6 +2374,27 @@ static ExitStatus op_iske(DisasContext *s, DisasOps *o) } #endif +static ExitStatus op_keb(DisasContext *s, DisasOps *o) +{ +gen_helper_keb(cc_op, cpu_env, o->in1, o->in2); +set_cc_static(s); +return NO_EXIT; +} + +static ExitStatus op_kdb(DisasContext *s, DisasOps *o) +{ +gen_helper_kdb(cc_op, cpu_env, o->in1, o->in2); +set_cc_static(s); +return NO_EXIT; +} + +static ExitStatus op_kxb(DisasContext *s, DisasOps *o) +{ +gen_helper_kxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_laa(DisasContext *s, DisasOps *o) { /* The real output is indeed the original value in memory; -- 2.9.4
[Qemu-devel] [PULL v2 48/70] target/s390x: implement MOVE NUMERICS
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-12-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 13 + target/s390x/translate.c | 8 4 files changed, 24 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 4b6c756..5780bb5 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -13,6 +13,7 @@ DEF_HELPER_FLAGS_3(divs64, TCG_CALL_NO_WG, s64, env, s64, s64) DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64) DEF_HELPER_4(srst, i64, env, i64, i64, i64) DEF_HELPER_4(clst, i64, env, i64, i64, i64) +DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) DEF_HELPER_4(ex, void, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index c1303d6..cbb91bb 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -576,6 +576,8 @@ C(0x0e00, MVCL,RR_a, Z, 0, 0, 0, 0, mvcl, 0) /* MOVE LONG EXTENDED */ C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0) +/* MOVE NUMERICS */ +C(0xd100, MVN, SS_a, Z, la1, a2, 0, 0, mvn, 0) /* MOVE PAGE */ C(0xb254, MVPG,RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0) /* MOVE STRING */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 6faaadd..f80b7a5 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -243,6 +243,19 @@ void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) } } +/* move numerics */ +void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int i; + +for (i = 0; i <= l; i++) { +uint8_t v = cpu_ldub_data_ra(env, dest + i, ra) & 0xf0; +v |= cpu_ldub_data_ra(env, src + i, ra) & 0x0f; +cpu_stb_data_ra(env, dest + i, v, ra); +} +} + /* compare unsigned byte arrays */ static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2, uintptr_t ra) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index a9b96e7..7b42c02 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2988,6 +2988,14 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o) } #endif +static ExitStatus op_mvn(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_mvn(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) { gen_helper_mvpg(cc_op, cpu_env, regs[0], o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 41/70] target/s390x: remove some Linux assumptions from IPTE
From: Aurelien JarnoSigned-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-3-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/cpu.h| 2 ++ target/s390x/mem_helper.c | 17 ++--- target/s390x/mmu_helper.c | 2 -- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index fdb2f50..a4d31df 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -1035,6 +1035,8 @@ struct sysib_322 { #define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */ #define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */ +#define VADDR_PX0xff000 /* page index bits */ + #define _PAGE_RO0x200/* HW read-only bit */ #define _PAGE_INVALID 0x400/* HW invalid bit*/ #define _PAGE_RES0 0x800/* bit must be zero */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index e35571e..0ebd65d 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1073,19 +1073,22 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) } /* invalidate pte */ -void HELPER(ipte)(CPUS390XState *env, uint64_t pte_addr, uint64_t vaddr) +void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr) { CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t page = vaddr & TARGET_PAGE_MASK; -uint64_t pte = 0; +uint64_t pte_addr, pte; /* XXX broadcast to other CPUs */ -/* XXX Linux is nice enough to give us the exact pte address. - According to spec we'd have to find it out ourselves */ -/* XXX Linux is fine with overwriting the pte, the spec requires - us to only set the invalid bit */ -stq_phys(cs->as, pte_addr, pte | _PAGE_INVALID); +/* Compute the page table entry address */ +pte_addr = (pto & _SEGMENT_ENTRY_ORIGIN); +pte_addr += (vaddr & _VADDR_PX) >> 9; + +/* Mark the page table entry as invalid */ +pte = ldq_phys(cs->as, pte_addr); +pte |= _PAGE_INVALID; +stq_phys(cs->as, pte_addr, pte); /* XXX we exploit the fact that Linux passes the exact virtual address here - it's not obliged to! */ diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index 31eb9ef..501e390 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -143,8 +143,6 @@ static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr, return 0; } -#define VADDR_PX0xff000 /* Page index bits */ - /* Decode segment table entry */ static int mmu_translate_segment(CPUS390XState *env, target_ulong vaddr, uint64_t asc, uint64_t st_entry, -- 2.9.4
[Qemu-devel] [PULL v2 62/70] target/s390x: implement UNPACK ASCII
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-26-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 51 ++ target/s390x/translate.c | 17 4 files changed, 71 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index cda7f7f..c21be50 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -89,6 +89,7 @@ DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) +DEF_HELPER_FLAGS_4(unpka, TCG_CALL_NO_WG, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) DEF_HELPER_4(trt, i32, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 1b487c3..1782e2f 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -871,6 +871,8 @@ /* Really format SS_b, but we pack both lengths into one argument for the helper call, so we might as well leave one 8-bit field. */ C(0xf300, UNPK,SS_a, Z, la1, a2, 0, 0, unpk, 0) +/* UNPACK ASCII */ +C(0xea00, UNPKA, SS_a, E2, la1, a2, 0, 0, unpka, 0) #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 218f1ab..b87e417 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1008,6 +1008,57 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, } } +uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, + uint64_t src) +{ +uintptr_t ra = GETPC(); +int i; +uint32_t cc; +uint8_t b; +/* The source operand is always 16 bytes long. */ +const int srclen = 16; + +/* The operands are processed from right to left. */ +src += srclen - 1; +dest += destlen - 1; + +/* Check for the sign. */ +b = cpu_ldub_data_ra(env, src, ra); +src--; +switch (b & 0xf) { +case 0xa: +case 0xc: +case 0xe ... 0xf: +cc = 0; /* plus */ +break; +case 0xb: +case 0xd: +cc = 1; /* minus */ +break; +default: +case 0x0 ... 0x9: +cc = 3; /* invalid */ +break; +} + +/* Now pad every nibble with 0x30, advancing one nibble at a time. */ +for (i = 0; i < destlen; i++) { +if (i == 31) { +/* If length is 32 bytes, the leftmost byte is 0. */ +b = 0; +} else if (i % 2) { +b = cpu_ldub_data_ra(env, src, ra); +src--; +} else { +b >>= 4; +} +cpu_stb_data_ra(env, dest, 0x30 + (b & 0xf), ra); +dest--; +} + +return cc; +} + static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t trans, uintptr_t ra) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 7e01c40..cd5cbd1 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4349,6 +4349,23 @@ static ExitStatus op_unpk(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_unpka(DisasContext *s, DisasOps *o) +{ +int l1 = get_field(s->fields, l1) + 1; +TCGv_i32 l; + +/* The length must not exceed 32 bytes. */ +if (l1 > 32) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} +l = tcg_const_i32(l1); +gen_helper_unpka(cc_op, cpu_env, o->addr1, l, o->in2); +tcg_temp_free_i32(l); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_xc(DisasContext *s, DisasOps *o) { int d1 = get_field(s->fields, d1); -- 2.9.4
[Qemu-devel] [PULL v2 39/70] target/s390x/cpu_models: Allow some additional feature bits for the "qemu" CPU
From: Thomas HuthCurrently we only present the plain z900 feature bits to the guest, but QEMU already emulates some additional features (but not all of the next CPU generation, so we can not use the next CPU level as default yet). Since newer Linux kernels are checking the feature bits and refuse to work if a required feature is missing, it would be nice to have a way to present more of the supported features when we are running with the "qemu" CPU. This patch now adds the supported features to the "full_feat" bitmap, so that additional features can be enabled on the command line now, for example with: qemu-system-s390x -cpu qemu,stfle=true,ldisp=true,eimm=true,stckf=true Acked-by: David Hildenbrand Reviewed-by: Aurelien Jarno Signed-off-by: Thomas Huth Message-Id: <1495704132-5675-1-git-send-email-th...@redhat.com> Signed-off-by: Richard Henderson --- target/s390x/cpu_models.c | 34 +++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 8d27363..e5e005a 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -658,6 +658,30 @@ static void check_compatibility(const S390CPUModel *max_model, "available in the configuration: "); } +/** + * The base TCG CPU model "qemu" is based on the z900. However, we already + * can also emulate some additional features of later CPU generations, so + * we add these additional feature bits here. + */ +static void add_qemu_cpu_model_features(S390FeatBitmap fbm) +{ +static const int feats[] = { +S390_FEAT_STFLE, +S390_FEAT_EXTENDED_IMMEDIATE, +S390_FEAT_LONG_DISPLACEMENT, +S390_FEAT_LONG_DISPLACEMENT_FAST, +S390_FEAT_STORE_CLOCK_FAST, +S390_FEAT_GENERAL_INSTRUCTIONS_EXT, +S390_FEAT_EXECUTE_EXT, +S390_FEAT_STFLE_45, +}; +int i; + +for (i = 0; i < ARRAY_SIZE(feats); i++) { +set_bit(feats[i], fbm); +} +} + static S390CPUModel *get_max_cpu_model(Error **errp) { static S390CPUModel max_model; @@ -670,10 +694,11 @@ static S390CPUModel *get_max_cpu_model(Error **errp) if (kvm_enabled()) { kvm_s390_get_host_cpu_model(_model, errp); } else { -/* TCG emulates a z900 */ +/* TCG emulates a z900 (with some optional additional features) */ max_model.def = _cpu_defs[0]; bitmap_copy(max_model.features, max_model.def->default_feat, S390_FEAT_MAX); +add_qemu_cpu_model_features(max_model.features); } if (!*errp) { cached = true; @@ -925,11 +950,14 @@ static void s390_host_cpu_model_initfn(Object *obj) static void s390_qemu_cpu_model_initfn(Object *obj) { +static S390CPUDef s390_qemu_cpu_defs; S390CPU *cpu = S390_CPU(obj); cpu->model = g_malloc0(sizeof(*cpu->model)); -/* TCG emulates a z900 */ -cpu->model->def = _cpu_defs[0]; +/* TCG emulates a z900 (with some optional additional features) */ +memcpy(_qemu_cpu_defs, _cpu_defs[0], sizeof(s390_qemu_cpu_defs)); +add_qemu_cpu_model_features(s390_qemu_cpu_defs.full_feat); +cpu->model->def = _qemu_cpu_defs; bitmap_copy(cpu->model->features, cpu->model->def->default_feat, S390_FEAT_MAX); } -- 2.9.4
[Qemu-devel] [PULL v2 44/70] target/s390x: implement TEST ADDRESSING MODE
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-6-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/insn-data.def | 3 +++ target/s390x/translate.c | 10 ++ 2 files changed, 13 insertions(+) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 0f70ace..170b50e 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -810,6 +810,9 @@ /* SUPERVISOR CALL */ C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 0) +/* TEST ADDRESSING MODE */ +C(0x010b, TAM, E, Z, 0, 0, 0, 0, tam, 0) + /* TEST AND SET */ C(0x9300, TS, S, Z, 0, a2, 0, 0, ts, 0) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 2d45132..854a66a 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4068,6 +4068,16 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o) return EXIT_NORETURN; } +static ExitStatus op_tam(DisasContext *s, DisasOps *o) +{ +int cc = 0; + +cc |= (s->tb->flags & FLAG_MASK_64) ? 2 : 0; +cc |= (s->tb->flags & FLAG_MASK_32) ? 1 : 0; +gen_op_movi_cc(s, cc); +return NO_EXIT; +} + static ExitStatus op_tceb(DisasContext *s, DisasOps *o) { gen_helper_tceb(cc_op, cpu_env, o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 36/70] target/s390x: End the TB after EXECUTE
This split will be required for implementing EXECUTE properly. Do this now as a separate step to aid comparison of before and after TB listings. Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/mem_helper.c | 54 --- target/s390x/translate.c | 6 +- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 4b96c27..d57d5b1 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1234,6 +1234,7 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) S390CPU *cpu = s390_env_get_cpu(env); uint64_t insn = cpu_lduw_code(env, addr); uint8_t opc = insn >> 8; +uint32_t cc; /* Or in the contents of R1[56:63]. */ insn |= r1 & 0xff; @@ -1263,42 +1264,46 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) b2 = extract64(insn, 28, 4); d1 = extract64(insn, 32, 12); d2 = extract64(insn, 16, 12); + +cc = env->cc_op; switch (opc & 0xf) { case 0x2: do_helper_mvc(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2), 0); -return; +break; case 0x4: -env->cc_op = do_helper_nc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_nc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; case 0x5: -env->cc_op = do_helper_clc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_clc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; case 0x6: -env->cc_op = do_helper_oc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_oc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; case 0x7: -env->cc_op = do_helper_xc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_xc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; case 0xc: do_helper_tr(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2), 0); -return; +break; case 0xd: -env->cc_op = do_helper_trt(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_trt(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; +default: +goto abort; } } else if (opc == 0x0a) { /* supervisor call */ env->int_svc_code = extract64(insn, 48, 8); env->int_svc_ilen = ilen; helper_exception(env, EXCP_SVC); -return; +g_assert_not_reached(); } else if (opc == 0xbf) { uint32_t r1, r3, b2, d2; @@ -1306,10 +1311,15 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) r3 = extract64(insn, 48, 4); b2 = extract64(insn, 44, 4); d2 = extract64(insn, 32, 12); -env->cc_op = helper_icm(env, r1, get_address(env, 0, b2, d2), r3); -return; +cc = helper_icm(env, r1, get_address(env, 0, b2, d2), r3); +} else { + abort: +cpu_abort(CPU(cpu), + "EXECUTE on instruction prefix 0x%x not implemented\n", + opc); +g_assert_not_reached(); } -cpu_abort(CPU(cpu), "EXECUTE on instruction prefix 0x%x not implemented\n", - opc); +env->cc_op = cc; +env->psw.addr += ilen; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 5c7e5c1..b6b9d75 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1168,6 +1168,8 @@ typedef enum { the PC (for whatever reason), so there's no need to do it again on exiting the TB. */ EXIT_PC_UPDATED, +/* We have updated the PC and CC values. */ +EXIT_PC_CC_UPDATED, /* We are exiting the TB, but have neither emitted a goto_tb, nor updated the PC for the next instruction to be executed. */ EXIT_PC_STALE, @@ -2221,7 +2223,7 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
[Qemu-devel] [PULL v2 38/70] target/s390x: Re-implement a few EXECUTE target insns directly
While the previous patch is required for proper conformance, the vast majority of target insns are MVC and XC for implementing memmove and memset respectively. The next most common are CLC, TR, and SVC. Implementing these (and a few others for which we already have an implementation) directly is faster than going through full translation to a TB. Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/mem_helper.c | 66 --- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 3a77edc..e35571e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -200,31 +200,30 @@ uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest, } /* memmove */ -static void do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest, - uint64_t src, uintptr_t ra) +static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src, uintptr_t ra) { uint32_t i; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); +/* mvc and memmove do not behave the same when areas overlap! */ /* mvc with source pointing to the byte after the destination is the same as memset with the first source byte */ if (dest == src + 1) { fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l + 1, ra); -return; -} - -/* mvc and memmove do not behave the same when areas overlap! */ -if (dest < src || src + l < dest) { +} else if (dest < src || src + l < dest) { fast_memmove(env, dest, src, l + 1, ra); -return; +} else { +/* slow version with byte accesses which always work */ +for (i = 0; i <= l; i++) { +uint8_t x = cpu_ldub_data_ra(env, src + i, ra); +cpu_stb_data_ra(env, dest + i, x, ra); +} } -/* slow version with byte accesses which always work */ -for (i = 0; i <= l; i++) { -cpu_stb_data_ra(env, dest + i, cpu_ldub_data_ra(env, src + i, ra), ra); -} +return env->cc_op; } void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) @@ -692,8 +691,8 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, } } -static void do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, - uint64_t trans, uintptr_t ra) +static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans, uintptr_t ra) { uint32_t i; @@ -702,12 +701,14 @@ static void do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, uint8_t new_byte = cpu_ldub_data_ra(env, trans + byte, ra); cpu_stb_data_ra(env, array + i, new_byte, ra); } + +return env->cc_op; } void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t trans) { -return do_helper_tr(env, len, array, trans, GETPC()); +do_helper_tr(env, len, array, trans, GETPC()); } uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, @@ -1221,6 +1222,41 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) g_assert_not_reached(); } +/* The very most common cases can be sped up by avoiding a new TB. */ +if ((opc & 0xf0) == 0xd0) { +typedef uint32_t (*dx_helper)(CPUS390XState *, uint32_t, uint64_t, + uint64_t, uintptr_t); +static const dx_helper dx[16] = { +[0x2] = do_helper_mvc, +[0x4] = do_helper_nc, +[0x5] = do_helper_clc, +[0x6] = do_helper_oc, +[0x7] = do_helper_xc, +[0xc] = do_helper_tr, +[0xd] = do_helper_trt, +}; +dx_helper helper = dx[opc & 0xf]; + +if (helper) { +uint32_t l = extract64(insn, 48, 8); +uint32_t b1 = extract64(insn, 44, 4); +uint32_t d1 = extract64(insn, 32, 12); +uint32_t b2 = extract64(insn, 28, 4); +uint32_t d2 = extract64(insn, 16, 12); +uint64_t a1 = get_address(env, 0, b1, d1); +uint64_t a2 = get_address(env, 0, b2, d2); + +env->cc_op = helper(env, l, a1, a2, 0); +env->psw.addr += ilen; +return; +} +} else if (opc == 0x0a) { +env->int_svc_code = extract64(insn, 48, 8); +env->int_svc_ilen = ilen; +helper_exception(env, EXCP_SVC); +g_assert_not_reached(); +} + /* Record the insn we want to execute as well as the ilen to use during the execution of the target insn. This will also ensure that ex_value is non-zero, which flags that we are in a state -- 2.9.4
[Qemu-devel] [PULL v2 61/70] target/s390x: implement PACK UNICODE
From: Aurelien JarnoUse a common helper with PACK ASCII as the differences are limited to the stride of the source operand. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-25-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 30 +- target/s390x/translate.c | 16 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 61f3ead..cda7f7f 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -87,6 +87,7 @@ DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) +DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index a5063a4..1b487c3 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -667,6 +667,8 @@ C(0xf200, PACK,SS_a, Z, la1, a2, 0, 0, pack, 0) /* PACK ASCII */ C(0xe900, PKA, SS_f, E2, la1, a2, 0, 0, pka, 0) +/* PACK UNICODE */ +C(0xe100, PKU, SS_f, E2, la1, a2, 0, 0, pku, 0) /* PREFETCH */ /* Implemented as nops of course. */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 4cf96c8..218f1ab 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -914,10 +914,9 @@ void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) } } -void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, - uint32_t srclen) +static inline void do_pkau(CPUS390XState *env, uint64_t dest, uint64_t src, + uint32_t srclen, int ssize, uintptr_t ra) { -uintptr_t ra = GETPC(); int i; /* The destination operand is always 16 bytes long. */ const int destlen = 16; @@ -932,16 +931,16 @@ void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, /* Start with a positive sign */ if (i == 0) { b = 0xc; -} else if (srclen > 1) { +} else if (srclen > ssize) { b = cpu_ldub_data_ra(env, src, ra) & 0x0f; -src--; -srclen--; +src -= ssize; +srclen -= ssize; } -if (srclen > 1) { +if (srclen > ssize) { b |= cpu_ldub_data_ra(env, src, ra) << 4; -src--; -srclen--; +src -= ssize; +srclen -= ssize; } cpu_stb_data_ra(env, dest, b, ra); @@ -949,6 +948,19 @@ void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, } } + +void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, + uint32_t srclen) +{ +do_pkau(env, dest, src, srclen, 1, GETPC()); +} + +void HELPER(pku)(CPUS390XState *env, uint64_t dest, uint64_t src, + uint32_t srclen) +{ +do_pkau(env, dest, src, srclen, 2, GETPC()); +} + void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 4939311..7e01c40 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3315,6 +3315,22 @@ static ExitStatus op_pka(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_pku(DisasContext *s, DisasOps *o) +{ +int l2 = get_field(s->fields, l2) + 1; +TCGv_i32 l; + +/* The length must be even and should not exceed 64 bytes. */ +if ((l2 & 1) || (l2 > 64)) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} +l = tcg_const_i32(l2); +gen_helper_pku(cpu_env, o->addr1, o->in2, l); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_popcnt(DisasContext *s, DisasOps *o) { gen_helper_popcnt(o->out, o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 33/70] target/s390x: Use atomic operations for COMPARE SWAP PURGE
Also provide the cross-cpu tlb flushing required by the PoO. Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/helper.h | 2 +- target/s390x/insn-data.def | 2 +- target/s390x/mem_helper.c | 32 target/s390x/translate.c | 42 ++ 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 3819409..cc451c7 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -107,13 +107,13 @@ DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64) DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64) DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64) DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_NO_RWG, i32, env, i64) -DEF_HELPER_3(csp, i32, env, i32, i64) DEF_HELPER_4(mvcs, i32, env, i64, i64, i64) DEF_HELPER_4(mvcp, i32, env, i64, i64, i64) DEF_HELPER_4(sigp, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_2(sacf, TCG_CALL_NO_WG, void, env, i64) DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64) DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_1(purge, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(lra, i64, env, i64) DEF_HELPER_FLAGS_2(lura, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_2(lurag, TCG_CALL_NO_WG, i64, env, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 3c3541c..4c91f30 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -837,7 +837,7 @@ #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ -C(0xb250, CSP, RRE, Z, 0, ra2, 0, 0, csp, 0) +D(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL) /* DIAGNOSE (KVM hypercall) */ C(0x8300, DIAG,RSI, Z, 0, 0, 0, 0, diag, 0) /* INSERT STORAGE KEY EXTENDED */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index fa03129..4b96c27 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1056,30 +1056,6 @@ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2) return re >> 1; } -/* compare and swap and purge */ -uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint64_t r2) -{ -S390CPU *cpu = s390_env_get_cpu(env); -uint32_t cc; -uint32_t o1 = env->regs[r1]; -uint64_t a2 = r2 & ~3ULL; -uint32_t o2 = cpu_ldl_data(env, a2); - -if (o1 == o2) { -cpu_stl_data(env, a2, env->regs[(r1 + 1) & 15]); -if (r2 & 0x3) { -/* flush TLB / ALB */ -tlb_flush(CPU(cpu)); -} -cc = 0; -} else { -env->regs[r1] = (env->regs[r1] & 0xULL) | o2; -cc = 1; -} - -return cc; -} - uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) { uintptr_t ra = GETPC(); @@ -1161,6 +1137,14 @@ void HELPER(ptlb)(CPUS390XState *env) tlb_flush(CPU(cpu)); } +/* flush global tlb */ +void HELPER(purge)(CPUS390XState *env) +{ +S390CPU *cpu = s390_env_get_cpu(env); + +tlb_flush_all_cpus_synced(CPU(cpu)); +} + /* load using real address */ uint64_t HELPER(lura)(CPUS390XState *env, uint64_t addr) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 78c14ef..711b9c9 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2006,11 +2006,45 @@ static ExitStatus op_cdsg(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static ExitStatus op_csp(DisasContext *s, DisasOps *o) { -TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); +TCGMemOp mop = s->insn->data; +TCGv_i64 addr, old, cc; +TCGLabel *lab = gen_new_label(); + +/* Note that in1 = R1 (zero-extended expected value), + out = R1 (original reg), out2 = R1+1 (new value). */ + check_privileged(s); -gen_helper_csp(cc_op, cpu_env, r1, o->in2); -tcg_temp_free_i32(r1); -set_cc_static(s); +addr = tcg_temp_new_i64(); +old = tcg_temp_new_i64(); +tcg_gen_andi_i64(addr, o->in2, -1ULL << (mop & MO_SIZE)); +tcg_gen_atomic_cmpxchg_i64(old, addr, o->in1, o->out2, + get_mem_index(s), mop | MO_ALIGN); +tcg_temp_free_i64(addr); + +/* Are the memory and expected values (un)equal? */ +cc = tcg_temp_new_i64(); +tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in1, old); +tcg_gen_extrl_i64_i32(cc_op, cc); + +/* Write back the output now, so that it happens before the + following branch, so that we don't need local temps. */ +if ((mop & MO_SIZE) == MO_32) { +tcg_gen_deposit_i64(o->out, o->out, old, 0, 32); +} else { +tcg_gen_mov_i64(o->out, old); +} +tcg_temp_free_i64(old); + +/* If the comparison was equal, and the LSB of R2 was set, + then we need to flush the TLB (for all cpus). */ +tcg_gen_xori_i64(cc, cc, 1); +tcg_gen_and_i64(cc, cc, o->in2); +tcg_gen_brcondi_i64(TCG_COND_EQ, cc, 0, lab); +
[Qemu-devel] [PULL v2 56/70] target/s390x: fix adj_len_to_page
From: Aurelien Jarnoadj_len_to_page doesn't return the correct result when the address is already page aligned and the length is bigger than a page. Fix that. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-20-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 4ed0b65..2326f0b 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -61,7 +61,7 @@ static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr) { #ifndef CONFIG_USER_ONLY if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) { -return -addr & ~TARGET_PAGE_MASK; +return -(addr | TARGET_PAGE_MASK); } #endif return len; -- 2.9.4
[Qemu-devel] [PULL v2 37/70] target/s390x: Implement EXECUTE via new TranslationBlock
Previously, helper_ex would construct the insn and then implement the insn via direct calls other helpers. This was sufficient to boot Linux but that is all. It is easy enough to go the whole nine yards by stashing state for EXECUTE within the cpu, and then rely on a new TB to be created that properly and completely interprets the insn. Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/cpu.h| 4 +- target/s390x/helper.c | 5 ++ target/s390x/machine.c| 19 target/s390x/mem_helper.c | 118 +- target/s390x/translate.c | 80 ++- 5 files changed, 85 insertions(+), 141 deletions(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index f463113..fdb2f50 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -107,6 +107,8 @@ typedef struct CPUS390XState { uint64_t cc_dst; uint64_t cc_vr; +uint64_t ex_value; + uint64_t __excp_addr; uint64_t psa; @@ -393,7 +395,7 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) { *pc = env->psw.addr; -*cs_base = 0; +*cs_base = env->ex_value; *flags = ((env->psw.mask >> 32) & ~FLAG_MASK_CC) | ((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0); } diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 4f8aadf..291db72 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -642,6 +642,11 @@ bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request) S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = >env; +if (env->ex_value) { +/* Execution of the target insn is indivisible from + the parent EXECUTE insn. */ +return false; +} if (env->psw.mask & PSW_MASK_EXT) { s390_cpu_do_interrupt(cs); return true; diff --git a/target/s390x/machine.c b/target/s390x/machine.c index 8503fa1..8f908bb 100644 --- a/target/s390x/machine.c +++ b/target/s390x/machine.c @@ -34,6 +34,7 @@ static int cpu_post_load(void *opaque, int version_id) return 0; } + static void cpu_pre_save(void *opaque) { S390CPU *cpu = opaque; @@ -156,6 +157,23 @@ const VMStateDescription vmstate_riccb = { } }; +static bool exval_needed(void *opaque) +{ +S390CPU *cpu = opaque; +return cpu->env.ex_value != 0; +} + +const VMStateDescription vmstate_exval = { +.name = "cpu/exval", +.version_id = 1, +.minimum_version_id = 1, +.needed = exval_needed, +.fields = (VMStateField[]) { +VMSTATE_UINT64(env.ex_value, S390CPU), +VMSTATE_END_OF_LIST() +} +}; + const VMStateDescription vmstate_s390_cpu = { .name = "cpu", .post_load = cpu_post_load, @@ -188,6 +206,7 @@ const VMStateDescription vmstate_s390_cpu = { _fpu, _vregs, _riccb, +_exval, NULL }, }; diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index d57d5b1..3a77edc 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -435,37 +435,6 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s) return d + len; } -static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address, - uint32_t mask) -{ -int pos = 24; /* top of the lower half of r1 */ -uint64_t rmask = 0xff00ULL; -uint8_t val = 0; -int ccd = 0; -uint32_t cc = 0; - -while (mask) { -if (mask & 8) { -env->regs[r1] &= ~rmask; -val = cpu_ldub_data(env, address); -if ((val & 0x80) && !ccd) { -cc = 1; -} -ccd = 1; -if (val && cc == 0) { -cc = 2; -} -env->regs[r1] |= (uint64_t)val << pos; -address++; -} -mask = (mask << 1) & 0xf; -pos -= 8; -rmask >>= 8; -} - -return cc; -} - /* load access registers r1 to r3 from memory at a2 */ void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { @@ -1222,19 +1191,17 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) } #endif -/* execute instruction - this instruction executes an insn modified with the contents of r1 - it does not change the executed instruction in memory - it does not change the program counter - in other words: tricky... - currently implemented by interpreting the cases it is most commonly used. +/* Execute instruction. This instruction executes an insn modified with + the contents of r1. It does not change the executed instruction in memory; + it does not change the program counter. + + Perform this by recording the modified instruction in env->ex_value. + This will be noticed by
[Qemu-devel] [PULL v2 35/70] target/s390x: Save current ilen during translation
Use this saved value instead of recomputing from next_pc difference. Reviewed-by: David HildenbrandReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/translate.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 737b577..5c7e5c1 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -58,6 +58,7 @@ struct DisasContext { const DisasInsn *insn; DisasFields *fields; uint64_t pc, next_pc; +uint32_t ilen; enum cc_op cc_op; bool singlestep_enabled; }; @@ -349,7 +350,7 @@ static void gen_program_exception(DisasContext *s, int code) tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code)); tcg_temp_free_i32(tmp); -tmp = tcg_const_i32(s->next_pc - s->pc); +tmp = tcg_const_i32(s->ilen); tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen)); tcg_temp_free_i32(tmp); @@ -2212,7 +2213,7 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o) v1 = regs[r1]; } -ilen = tcg_const_i32(s->next_pc - s->pc); +ilen = tcg_const_i32(s->ilen); gen_helper_ex(cpu_env, ilen, v1, o->in2); tcg_temp_free_i32(ilen); @@ -4057,7 +4058,7 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o) tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code)); tcg_temp_free_i32(t); -t = tcg_const_i32(s->next_pc - s->pc); +t = tcg_const_i32(s->ilen); tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen)); tcg_temp_free_i32(t); @@ -5196,6 +5197,7 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s, op = (insn >> 8) & 0xff; ilen = get_ilen(op); s->next_pc = s->pc + ilen; +s->ilen = ilen; switch (ilen) { case 2: -- 2.9.4
[Qemu-devel] [PULL v2 31/70] target/s390x: Fix some helper_ex problems
(1) The OR of the low bits or R1 into INSN were not being done consistently; it was forgotten along all but the SVC path. (2) The setting of ILEN was wrong on SVC path for EXRL. (3) The data load for ICM read too much. Fix these by consolidating data load at the beginning, using get_ilen to control the number of bytes loaded, and ORing in the byte from R1. Use extract64 from the full aligned insn to extract arguments. Pass in ILEN rather than RET as the more natural way to give the required data along the SVC path. Modify ENV->CC_OP directly rather than include it in the functional interface. Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/helper.h | 2 +- target/s390x/mem_helper.c | 135 +- target/s390x/translate.c | 8 +-- 3 files changed, 78 insertions(+), 67 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index ea35834..3819409 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -14,7 +14,7 @@ DEF_HELPER_4(srst, i64, env, i64, i64, i64) DEF_HELPER_4(clst, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) -DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64) +DEF_HELPER_4(ex, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index a73d486..fa03129 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1245,76 +1245,87 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) in other words: tricky... currently implemented by interpreting the cases it is most commonly used. */ -uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, -uint64_t addr, uint64_t ret) +void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) { S390CPU *cpu = s390_env_get_cpu(env); -uint16_t insn = cpu_lduw_code(env, addr); - -HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr, - insn); -if ((insn & 0xf0ff) == 0xd000) { -uint32_t l, insn2, b1, b2, d1, d2; - -l = v1 & 0xff; -insn2 = cpu_ldl_code(env, addr + 2); -b1 = (insn2 >> 28) & 0xf; -b2 = (insn2 >> 12) & 0xf; -d1 = (insn2 >> 16) & 0xfff; -d2 = insn2 & 0xfff; -switch (insn & 0xf00) { -case 0x200: +uint64_t insn = cpu_lduw_code(env, addr); +uint8_t opc = insn >> 8; + +/* Or in the contents of R1[56:63]. */ +insn |= r1 & 0xff; + +/* Load the rest of the instruction. */ +insn <<= 48; +switch (get_ilen(opc)) { +case 2: +break; +case 4: +insn |= (uint64_t)cpu_lduw_code(env, addr + 2) << 32; +break; +case 6: +insn |= (uint64_t)(uint32_t)cpu_ldl_code(env, addr + 2) << 16; +break; +default: +g_assert_not_reached(); +} + +HELPER_LOG("%s: addr 0x%lx insn 0x%" PRIx64 "\n", __func__, addr, insn); + +if ((opc & 0xf0) == 0xd0) { +uint32_t l, b1, b2, d1, d2; + +l = extract64(insn, 48, 8); +b1 = extract64(insn, 44, 4); +b2 = extract64(insn, 28, 4); +d1 = extract64(insn, 32, 12); +d2 = extract64(insn, 16, 12); +switch (opc & 0xf) { +case 0x2: do_helper_mvc(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2), 0); -break; -case 0x400: -cc = do_helper_nc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -break; -case 0x500: -cc = do_helper_clc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -break; -case 0x600: -cc = do_helper_oc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -break; -case 0x700: -cc = do_helper_xc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -break; -case 0xc00: +return; +case 0x4: +env->cc_op = do_helper_nc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +return; +case 0x5: +env->cc_op = do_helper_clc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +return; +case 0x6: +env->cc_op = do_helper_oc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +
[Qemu-devel] [PULL v2 32/70] target/s390x: Fix EXECUTE with R1==0
The PoO specifies that when R1==0, no ORing into the insn loaded from storage takes place. Load a zero for this case. Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/insn-data.def | 4 ++-- target/s390x/translate.c | 14 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index cac0f51..3c3541c 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -327,9 +327,9 @@ C(0xeb57, XIY, SIY, LD, m1_8u, i2_8u, new, m1_8, xor, nz64) /* EXECUTE */ -C(0x4400, EX, RX_a, Z, r1_o, a2, 0, 0, ex, 0) +C(0x4400, EX, RX_a, Z, 0, a2, 0, 0, ex, 0) /* EXECUTE RELATIVE LONG */ -C(0xc600, EXRL,RIL_b, EE, r1_o, ri2, 0, 0, ex, 0) +C(0xc600, EXRL,RIL_b, EE, 0, ri2, 0, 0, ex, 0) /* EXTRACT ACCESS */ C(0xb24f, EAR, RRE, Z, 0, 0, new, r1_32, ear, 0) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index c1162a1..78c14ef 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2164,15 +2164,27 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o) MVC inside of memcpy, which needs a helper call anyway. So perhaps this doesn't bear thinking about any further. */ +int r1 = get_field(s->fields, r1); TCGv_i32 ilen; +TCGv_i64 v1; update_psw_addr(s); gen_op_calc_cc(s); +if (r1 == 0) { +v1 = tcg_const_i64(0); +} else { +v1 = regs[r1]; +} + ilen = tcg_const_i32(s->next_pc - s->pc); -gen_helper_ex(cpu_env, ilen, o->in1, o->in2); +gen_helper_ex(cpu_env, ilen, v1, o->in2); tcg_temp_free_i32(ilen); +if (r1 == 0) { +tcg_temp_free_i64(v1); +} + return NO_EXIT; } -- 2.9.4
[Qemu-devel] [PULL v2 47/70] target/s390x: implement MOVE INVERSE
From: Aurelien JarnoReviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-11-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 12 target/s390x/translate.c | 8 4 files changed, 23 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 86e2bc1..4b6c756 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -3,6 +3,7 @@ DEF_HELPER_FLAGS_4(nc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_FLAGS_4(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvc, TCG_CALL_NO_WG, void, env, i32, i64, i64) +DEF_HELPER_FLAGS_4(mvcin, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_3(mvcl, i32, env, i32, i32) DEF_HELPER_FLAGS_4(clm, TCG_CALL_NO_WG, i32, env, i32, i32, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 39fcce5..c1303d6 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -570,6 +570,8 @@ C(0xe548, MVGHI, SIL, GIE, la1, i2, 0, m1_64, mov2, 0) C(0x9200, MVI, SI,Z, la1, i2, 0, m1_8, mov2, 0) C(0xeb52, MVIY,SIY, LD, la1, i2, 0, m1_8, mov2, 0) +/* MOVE INVERSE */ +C(0xe800, MVCIN, SS_a, Z, la1, a2, 0, 0, mvcin, 0) /* MOVE LONG */ C(0x0e00, MVCL,RR_a, Z, 0, 0, 0, 0, mvcl, 0) /* MOVE LONG EXTENDED */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 850472e..6faaadd 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -231,6 +231,18 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) do_helper_mvc(env, l, dest, src, GETPC()); } +/* move inverse */ +void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int i; + +for (i = 0; i <= l; i++) { +uint8_t v = cpu_ldub_data_ra(env, src - i, ra); +cpu_stb_data_ra(env, dest + i, v, ra); +} +} + /* compare unsigned byte arrays */ static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2, uintptr_t ra) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 0a35eed..a9b96e7 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2938,6 +2938,14 @@ static ExitStatus op_mvc(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_mvcin(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_mvcin(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); -- 2.9.4
[Qemu-devel] [PULL v2 29/70] target/s390x: Use unwind data for helper_lra
Fix saving exception_index around mmu_translate; eliminate a dead store. Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/mem_helper.c | 6 +++--- target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index a8c85c9..17d8257 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1208,17 +1208,17 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) { CPUState *cs = CPU(s390_env_get_cpu(env)); uint32_t cc = 0; -int old_exc = cs->exception_index; uint64_t asc = env->psw.mask & PSW_MASK_ASC; uint64_t ret; -int flags; +int old_exc, flags; /* XXX incomplete - has more corner cases */ if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) { +cpu_restore_state(cs, GETPC()); program_interrupt(env, PGM_SPECIAL_OP, 2); } -cs->exception_index = old_exc; +old_exc = cs->exception_index; if (mmu_translate(env, addr, 0, asc, , , true)) { cc = 3; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index cafcecb..80b08b9 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2565,7 +2565,6 @@ static ExitStatus op_lctlg(DisasContext *s, DisasOps *o) static ExitStatus op_lra(DisasContext *s, DisasOps *o) { check_privileged(s); -potential_page_fault(s); gen_helper_lra(o->out, cpu_env, o->in2); set_cc_static(s); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL v2 30/70] target/s390x: Use unwind data for helper_mvcs/mvcp
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 8 ++-- target/s390x/translate.c | 2 -- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 17d8257..a73d486 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1082,6 +1082,7 @@ uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint64_t r2) uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) { +uintptr_t ra = GETPC(); int cc = 0, i; HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", @@ -1095,7 +1096,8 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) /* XXX replace w/ memcpy */ for (i = 0; i < l; i++) { -cpu_stb_secondary(env, a1 + i, cpu_ldub_primary(env, a2 + i)); +uint8_t x = cpu_ldub_primary_ra(env, a2 + i, ra); +cpu_stb_secondary_ra(env, a1 + i, x, ra); } return cc; @@ -1103,6 +1105,7 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) { +uintptr_t ra = GETPC(); int cc = 0, i; HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", @@ -1116,7 +1119,8 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) /* XXX replace w/ memcpy */ for (i = 0; i < l; i++) { -cpu_stb_primary(env, a1 + i, cpu_ldub_secondary(env, a2 + i)); +uint8_t x = cpu_ldub_secondary_ra(env, a2 + i, ra); +cpu_stb_primary_ra(env, a1 + i, x, ra); } return cc; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 80b08b9..e99fbd9 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2894,7 +2894,6 @@ static ExitStatus op_mvcp(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, l1); check_privileged(s); -potential_page_fault(s); gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2); set_cc_static(s); return NO_EXIT; @@ -2904,7 +2903,6 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, l1); check_privileged(s); -potential_page_fault(s); gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2); set_cc_static(s); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL v2 28/70] target/s390x: Use unwind data for helper_tprot
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 1 - target/s390x/translate.c | 1 - 2 files changed, 2 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 7df2e53..a8c85c9 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -970,7 +970,6 @@ uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2) { /* XXX implement */ - return 0; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 16e39d3..cafcecb 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4054,7 +4054,6 @@ static ExitStatus op_testblock(DisasContext *s, DisasOps *o) static ExitStatus op_tprot(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_tprot(cc_op, o->addr1, o->in2); set_cc_static(s); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL v2 40/70] target/s390x: remove dead code in translate.c
From: Aurelien JarnoReviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-2-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/translate.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 0406f22..67ddf1b 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -5472,10 +5472,7 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb) gen_io_start(); } -status = NO_EXIT; -if (status == NO_EXIT) { -status = translate_one(env, ); -} +status = translate_one(env, ); /* If we reach a page boundary, are single stepping, or exhaust instruction count, stop generation. */ -- 2.9.4
[Qemu-devel] [PULL v2 27/70] target/s390x: Use unwind data for helper_testblock
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 3 +++ target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b64c04e..7df2e53 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -939,6 +939,7 @@ void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) { +uintptr_t ra = GETPC(); CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t abs_addr; int i; @@ -947,12 +948,14 @@ uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) abs_addr = mmu_real2abs(env, real_addr) & TARGET_PAGE_MASK; if (!address_space_access_valid(_space_memory, abs_addr, TARGET_PAGE_SIZE, true)) { +cpu_restore_state(cs, ra); program_interrupt(env, PGM_ADDRESSING, 4); return 1; } /* Check low-address protection */ if ((env->cregs[0] & CR0_LOWPROT) && real_addr < 0x2000) { +cpu_restore_state(cs, ra); program_interrupt(env, PGM_PROTECTION, 4); return 1; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 2f15329..16e39d3 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4047,7 +4047,6 @@ static ExitStatus op_tcxb(DisasContext *s, DisasOps *o) static ExitStatus op_testblock(DisasContext *s, DisasOps *o) { check_privileged(s); -potential_page_fault(s); gen_helper_testblock(cc_op, cpu_env, o->in2); set_cc_static(s); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL v2 18/70] target/s390x: Use unwind data for helper_clcle
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 6 +++--- target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 8a095ad..f5a3044 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -595,12 +595,12 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1]; uint64_t dest = get_address_31fix(env, r1); uint64_t srclen = env->regs[r3 + 1]; uint64_t src = get_address_31fix(env, r3); uint8_t pad = a2 & 0xff; -uint8_t v1 = 0, v2 = 0; uint32_t cc = 0; if (!(destlen || srclen)) { @@ -612,8 +612,8 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, } for (; destlen || srclen; src++, dest++, destlen--, srclen--) { -v1 = srclen ? cpu_ldub_data(env, src) : pad; -v2 = destlen ? cpu_ldub_data(env, dest) : pad; +uint8_t v1 = srclen ? cpu_ldub_data_ra(env, src, ra) : pad; +uint8_t v2 = destlen ? cpu_ldub_data_ra(env, dest, ra) : pad; if (v1 != v2) { cc = (v1 < v2) ? 1 : 2; break; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index eaa3adc..600b76d 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1920,7 +1920,6 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -potential_page_fault(s); gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL v2 23/70] target/s390x: Use unwind data for helper_trt
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 28 target/s390x/translate.c | 1 - 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index fd6dbf7..ff12777 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -781,25 +781,29 @@ uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, return array + i; } -uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array, - uint64_t trans) +static uint32_t do_helper_trt(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans, uintptr_t ra) { -uint32_t cc = 0; -int i; +uint32_t i; for (i = 0; i <= len; i++) { -uint8_t byte = cpu_ldub_data(env, array + i); -uint8_t sbyte = cpu_ldub_data(env, trans + byte); +uint8_t byte = cpu_ldub_data_ra(env, array + i, ra); +uint8_t sbyte = cpu_ldub_data_ra(env, trans + byte, ra); if (sbyte != 0) { env->regs[1] = array + i; -env->regs[2] = (env->regs[2] & ~0xff) | sbyte; -cc = (i == len) ? 2 : 1; -break; +env->regs[2] = deposit64(env->regs[2], 0, 8, sbyte); +return (i == len) ? 2 : 1; } } -return cc; +return 0; +} + +uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans) +{ +return do_helper_trt(env, len, array, trans, GETPC()); } void HELPER(cdsg)(CPUS390XState *env, uint64_t addr, @@ -1275,8 +1279,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2), 0); return cc; case 0xd00: -cc = helper_trt(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); +cc = do_helper_trt(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; default: goto abort; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index d42896f..c95adcd 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4087,7 +4087,6 @@ static ExitStatus op_tre(DisasContext *s, DisasOps *o) static ExitStatus op_trt(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_trt(cc_op, cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); -- 2.9.4
[Qemu-devel] [PULL v2 34/70] target/s390x: Implement CSPG
Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/insn-data.def | 1 + target/s390x/translate.c | 1 + 2 files changed, 2 insertions(+) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 4c91f30..f818437 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -838,6 +838,7 @@ #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ D(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL) +D(0xb98a, CSPG,RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ) /* DIAGNOSE (KVM hypercall) */ C(0x8300, DIAG,RSI, Z, 0, 0, 0, 0, diag, 0) /* INSERT STORAGE KEY EXTENDED */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 711b9c9..737b577 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1200,6 +1200,7 @@ typedef enum DisasFacility { FAC_SFLE, /* store facility list extended */ FAC_ILA,/* interlocked access facility 1 */ FAC_LPP,/* load-program-parameter */ +FAC_DAT_ENH,/* DAT-enhancement */ } DisasFacility; struct DisasInsn { -- 2.9.4
[Qemu-devel] [PULL v2 26/70] target/s390x: Use unwind data for helper_stctl
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 10 ++ target/s390x/translate.c | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 614cdb2..b64c04e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -907,11 +907,12 @@ void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { -int i; +uintptr_t ra = GETPC(); uint64_t dest = a2; +uint32_t i; for (i = r1;; i = (i + 1) % 16) { -cpu_stq_data(env, dest, env->cregs[i]); +cpu_stq_data_ra(env, dest, env->cregs[i], ra); dest += sizeof(uint64_t); if (i == r3) { @@ -922,11 +923,12 @@ void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { -int i; +uintptr_t ra = GETPC(); uint64_t dest = a2; +uint32_t i; for (i = r1;; i = (i + 1) % 16) { -cpu_stl_data(env, dest, env->cregs[i]); +cpu_stl_data_ra(env, dest, env->cregs[i], ra); dest += sizeof(uint32_t); if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 3a98c57..2f15329 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3617,7 +3617,6 @@ static ExitStatus op_stctg(DisasContext *s, DisasOps *o) TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); check_privileged(s); -potential_page_fault(s); gen_helper_stctg(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); @@ -3629,7 +3628,6 @@ static ExitStatus op_stctl(DisasContext *s, DisasOps *o) TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); check_privileged(s); -potential_page_fault(s); gen_helper_stctl(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL v2 17/70] target/s390x: Use unwind data for helper_mvcle
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 7 --- target/s390x/translate.c | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 49cfc9b..8a095ad 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -544,6 +544,7 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1]; uint64_t dest = env->regs[r1]; uint64_t srclen = env->regs[r3 + 1]; @@ -572,12 +573,12 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, } for (; destlen && srclen; src++, dest++, destlen--, srclen--) { -v = cpu_ldub_data(env, src); -cpu_stb_data(env, dest, v); +v = cpu_ldub_data_ra(env, src, ra); +cpu_stb_data_ra(env, dest, v, ra); } for (; destlen; dest++, destlen--) { -cpu_stb_data(env, dest, pad); +cpu_stb_data_ra(env, dest, pad, ra); } env->regs[r1 + 1] = destlen; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index e3c5ba1..eaa3adc 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2887,7 +2887,6 @@ static ExitStatus op_mvcle(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -potential_page_fault(s); gen_helper_mvcle(cc_op, cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL v2 25/70] target/s390x: Use unwind data for helper_lctl
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 9 + target/s390x/translate.c | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 68e3817..614cdb2 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -878,18 +878,19 @@ void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); S390CPU *cpu = s390_env_get_cpu(env); bool PERchanged = false; -int i; uint64_t src = a2; -uint32_t val; +uint32_t i; for (i = r1;; i = (i + 1) % 16) { -val = cpu_ldl_data(env, src); +uint32_t val = cpu_ldl_data_ra(env, src, ra); if ((uint32_t)env->cregs[i] != val && i >= 9 && i <= 11) { PERchanged = true; } -env->cregs[i] = (env->cregs[i] & 0xULL) | val; +env->cregs[i] = deposit64(env->cregs[i], 0, 32, val); +HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%x\n", i, src, val); src += sizeof(uint32_t); if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 2386c41..3a98c57 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2545,7 +2545,6 @@ static ExitStatus op_lctl(DisasContext *s, DisasOps *o) TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); check_privileged(s); -potential_page_fault(s); gen_helper_lctl(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL v2 22/70] target/s390x: Use unwind data for helper_tre
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 15 --- target/s390x/translate.c | 1 - 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b37a963..fd6dbf7 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -744,9 +744,11 @@ void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, uint64_t len, uint64_t trans) { +uintptr_t ra = GETPC(); uint8_t end = env->regs[0] & 0xff; uint64_t l = len; uint64_t i; +uint32_t cc = 0; if (!(env->psw.mask & PSW_MASK_64)) { array &= 0x7fff; @@ -757,25 +759,24 @@ uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, amount of work we're willing to do. For now, let's cap at 8k. */ if (l > 0x2000) { l = 0x2000; -env->cc_op = 3; -} else { -env->cc_op = 0; +cc = 3; } for (i = 0; i < l; i++) { uint8_t byte, new_byte; -byte = cpu_ldub_data(env, array + i); +byte = cpu_ldub_data_ra(env, array + i, ra); if (byte == end) { -env->cc_op = 1; +cc = 1; break; } -new_byte = cpu_ldub_data(env, trans + byte); -cpu_stb_data(env, array + i, new_byte); +new_byte = cpu_ldub_data_ra(env, trans + byte, ra); +cpu_stb_data_ra(env, array + i, new_byte, ra); } +env->cc_op = cc; env->retxl = len - i; return array + i; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index e4da94d..d42896f 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4078,7 +4078,6 @@ static ExitStatus op_tr(DisasContext *s, DisasOps *o) static ExitStatus op_tre(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_tre(o->out, cpu_env, o->out, o->out2, o->in2); return_low128(o->out2); set_cc_static(s); -- 2.9.4
[Qemu-devel] [PULL v2 21/70] target/s390x: Use unwind data for helper_tr
Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/mem_helper.c | 25 +++-- target/s390x/translate.c | 1 - 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 0701e10..b37a963 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -723,19 +723,24 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, } } -void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, -uint64_t trans) +static void do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans, uintptr_t ra) { -int i; +uint32_t i; for (i = 0; i <= len; i++) { -uint8_t byte = cpu_ldub_data(env, array + i); -uint8_t new_byte = cpu_ldub_data(env, trans + byte); - -cpu_stb_data(env, array + i, new_byte); +uint8_t byte = cpu_ldub_data_ra(env, array + i, ra); +uint8_t new_byte = cpu_ldub_data_ra(env, trans + byte, ra); +cpu_stb_data_ra(env, array + i, new_byte, ra); } } +void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, +uint64_t trans) +{ +return do_helper_tr(env, len, array, trans, GETPC()); +} + uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, uint64_t len, uint64_t trans) { @@ -1265,9 +1270,9 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2), 0); break; case 0xc00: -helper_tr(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); -break; +do_helper_tr(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +return cc; case 0xd00: cc = helper_trt(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2)); diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 10262f5..e4da94d 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4070,7 +4070,6 @@ static ExitStatus op_tprot(DisasContext *s, DisasOps *o) static ExitStatus op_tr(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_tr(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); -- 2.9.4
[Qemu-devel] [PULL v2 07/70] target/s390x: Use unwind data for helper_mvc
Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/mem_helper.c | 30 ++ target/s390x/translate.c | 1 - 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b71437a..78a9ac1 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -91,7 +91,7 @@ static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, } static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src, - uint32_t l) + uint32_t l, uintptr_t ra) { int mmu_idx = cpu_mmu_index(env, false); @@ -110,7 +110,7 @@ static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src, /* We failed to get access to one or both whole pages. The next read or write access will likely fill the QEMU TLB for the next iteration. */ -cpu_stb_data(env, dest, cpu_ldub_data(env, src)); +cpu_stb_data_ra(env, dest, cpu_ldub_data_ra(env, src, ra), ra); src++; dest++; l--; @@ -200,32 +200,38 @@ uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest, } /* memmove */ -void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +static void do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src, uintptr_t ra) { -int i = 0; +uint32_t i; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); /* mvc with source pointing to the byte after the destination is the same as memset with the first source byte */ -if (dest == (src + 1)) { -fast_memset(env, dest, cpu_ldub_data(env, src), l + 1, 0); +if (dest == src + 1) { +fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l + 1, ra); return; } /* mvc and memmove do not behave the same when areas overlap! */ -if ((dest < src) || (src + l < dest)) { -fast_memmove(env, dest, src, l + 1); +if (dest < src || src + l < dest) { +fast_memmove(env, dest, src, l + 1, ra); return; } /* slow version with byte accesses which always work */ for (i = 0; i <= l; i++) { -cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i)); +cpu_stb_data_ra(env, dest + i, cpu_ldub_data_ra(env, src + i, ra), ra); } } +void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +do_helper_mvc(env, l, dest, src, GETPC()); +} + /* compare unsigned byte arrays */ uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) { @@ -388,7 +394,7 @@ void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) { /* XXX missing r0 handling */ env->cc_op = 0; -fast_memmove(env, r1, r2, TARGET_PAGE_SIZE); +fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, 0); } /* string copy (c is string terminator) */ @@ -1223,8 +1229,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, d2 = insn2 & 0xfff; switch (insn & 0xf00) { case 0x200: -helper_mvc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); +do_helper_mvc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; case 0x400: cc = do_helper_nc(env, l, get_address(env, 0, b1, d1), diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 2c26308..a9502cc 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2871,7 +2871,6 @@ static ExitStatus op_movx(DisasContext *s, DisasOps *o) static ExitStatus op_mvc(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_mvc(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL v2 24/70] target/s390x: Use unwind data for helper_lctlg
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 8 target/s390x/translate.c | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index ff12777..68e3817 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -848,20 +848,20 @@ void HELPER(cdsg)(CPUS390XState *env, uint64_t addr, #if !defined(CONFIG_USER_ONLY) void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); S390CPU *cpu = s390_env_get_cpu(env); bool PERchanged = false; -int i; uint64_t src = a2; -uint64_t val; +uint32_t i; for (i = r1;; i = (i + 1) % 16) { -val = cpu_ldq_data(env, src); +uint64_t val = cpu_ldq_data_ra(env, src, ra); if (env->cregs[i] != val && i >= 9 && i <= 11) { PERchanged = true; } env->cregs[i] = val; HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n", - i, src, env->cregs[i]); + i, src, val); src += sizeof(uint64_t); if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index c95adcd..2386c41 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2557,7 +2557,6 @@ static ExitStatus op_lctlg(DisasContext *s, DisasOps *o) TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); check_privileged(s); -potential_page_fault(s); gen_helper_lctlg(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL v2 19/70] target/s390x: Use unwind data for helper_cksm
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 11 ++- target/s390x/translate.c | 1 - 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index f5a3044..d4ee364 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -633,6 +633,7 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1, uint64_t src, uint64_t src_len) { +uintptr_t ra = GETPC(); uint64_t max_len, len; uint64_t cksm = (uint32_t)r1; @@ -642,21 +643,21 @@ uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1, /* Process full words as available. */ for (len = 0; len + 4 <= max_len; len += 4, src += 4) { -cksm += (uint32_t)cpu_ldl_data(env, src); +cksm += (uint32_t)cpu_ldl_data_ra(env, src, ra); } switch (max_len - len) { case 1: -cksm += cpu_ldub_data(env, src) << 24; +cksm += cpu_ldub_data_ra(env, src, ra) << 24; len += 1; break; case 2: -cksm += cpu_lduw_data(env, src) << 16; +cksm += cpu_lduw_data_ra(env, src, ra) << 16; len += 2; break; case 3: -cksm += cpu_lduw_data(env, src) << 16; -cksm += cpu_ldub_data(env, src + 2) << 8; +cksm += cpu_lduw_data_ra(env, src, ra) << 16; +cksm += cpu_ldub_data_ra(env, src + 2, ra) << 8; len += 3; break; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 600b76d..40965ea 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1871,7 +1871,6 @@ static ExitStatus op_cksm(DisasContext *s, DisasOps *o) int r2 = get_field(s->fields, r2); TCGv_i64 len = tcg_temp_new_i64(); -potential_page_fault(s); gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]); set_cc_static(s); return_low128(o->out); -- 2.9.4
[Qemu-devel] [PULL v2 20/70] target/s390x: Use unwind data for helper_unpk
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 9 + target/s390x/translate.c | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index d4ee364..0701e10 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -679,6 +679,7 @@ uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1, void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) { +uintptr_t ra = GETPC(); int len_dest = len >> 4; int len_src = len & 0xf; uint8_t b; @@ -688,8 +689,8 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, src += len_src; /* last byte is special, it only flips the nibbles */ -b = cpu_ldub_data(env, src); -cpu_stb_data(env, dest, (b << 4) | (b >> 4)); +b = cpu_ldub_data_ra(env, src, ra); +cpu_stb_data_ra(env, dest, (b << 4) | (b >> 4), ra); src--; len_src--; @@ -699,7 +700,7 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint8_t cur_byte = 0; if (len_src > 0) { -cur_byte = cpu_ldub_data(env, src); +cur_byte = cpu_ldub_data_ra(env, src, ra); } len_dest--; @@ -718,7 +719,7 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, /* zone bits */ cur_byte |= 0xf0; -cpu_stb_data(env, dest, cur_byte); +cpu_stb_data_ra(env, dest, cur_byte, ra); } } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 40965ea..10262f5 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4099,7 +4099,6 @@ static ExitStatus op_trt(DisasContext *s, DisasOps *o) static ExitStatus op_unpk(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_unpk(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL v2 13/70] target/s390x: Use unwind data for helper_mvst
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 5 +++-- target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 1c36a47..e4bfc6e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -409,6 +409,7 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) /* string copy (c is string terminator) */ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s) { +uintptr_t ra = GETPC(); uint32_t len; c = c & 0xff; @@ -418,8 +419,8 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s) /* Lest we fail to service interrupts in a timely manner, limit the amount of work we're willing to do. For now, let's cap at 8k. */ for (len = 0; len < 0x2000; ++len) { -uint8_t v = cpu_ldub_data(env, s + len); -cpu_stb_data(env, d + len, v); +uint8_t v = cpu_ldub_data_ra(env, s + len, ra); +cpu_stb_data_ra(env, d + len, v, ra); if (v == c) { /* Complete. Set CC=1 and advance R1. */ env->cc_op = 1; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index ae29889..d41a0fd 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2928,7 +2928,6 @@ static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) static ExitStatus op_mvst(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return_low128(o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 15/70] target/s390x: Use unwind data for helper_stam
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 3 ++- target/s390x/translate.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 88e817a..2acc984 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -485,10 +485,11 @@ void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) /* store access registers r1 to r3 in memory at a2 */ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); int i; for (i = r1;; i = (i + 1) % 16) { -cpu_stl_data(env, a2, env->aregs[i]); +cpu_stl_data_ra(env, a2, env->aregs[i], ra); a2 += 4; if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 16477fc..4ae949a 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3867,7 +3867,6 @@ static ExitStatus op_stam(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -potential_page_fault(s); gen_helper_stam(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL v2 08/70] target/s390x: Use unwind data for helper_clc
Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/mem_helper.c | 29 + target/s390x/translate.c | 1 - 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 78a9ac1..50689bb 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -233,32 +233,37 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) } /* compare unsigned byte arrays */ -uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) +static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, + uint64_t s2, uintptr_t ra) { -int i; -unsigned char x, y; -uint32_t cc; +uint32_t i; +uint32_t cc = 0; HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n", __func__, l, s1, s2); + for (i = 0; i <= l; i++) { -x = cpu_ldub_data(env, s1 + i); -y = cpu_ldub_data(env, s2 + i); +uint8_t x = cpu_ldub_data_ra(env, s1 + i, ra); +uint8_t y = cpu_ldub_data_ra(env, s2 + i, ra); HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y); if (x < y) { cc = 1; -goto done; +break; } else if (x > y) { cc = 2; -goto done; +break; } } -cc = 0; - done: + HELPER_LOG("\n"); return cc; } +uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) +{ +return do_helper_clc(env, l, s1, s2, GETPC()); +} + /* compare logical under mask */ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, uint64_t addr) @@ -1237,8 +1242,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2), 0); break; case 0x500: -cc = helper_clc(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); +cc = do_helper_clc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; case 0x600: cc = do_helper_oc(env, l, get_address(env, 0, b1, d1), diff --git a/target/s390x/translate.c b/target/s390x/translate.c index a9502cc..c47b818 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1906,7 +1906,6 @@ static ExitStatus op_clc(DisasContext *s, DisasOps *o) tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s)); break; default: -potential_page_fault(s); vl = tcg_const_i32(l); gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2); tcg_temp_free_i32(vl); -- 2.9.4
[Qemu-devel] [PULL v2 16/70] target/s390x: Use unwind data for helper_mvcl
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 7 --- target/s390x/translate.c | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 2acc984..49cfc9b 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -501,6 +501,7 @@ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) /* move long */ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) { +uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1] & 0xff; uint64_t dest = get_address_31fix(env, r1); uint64_t srclen = env->regs[r2 + 1] & 0xff; @@ -522,12 +523,12 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) } for (; destlen && srclen; src++, dest++, destlen--, srclen--) { -v = cpu_ldub_data(env, src); -cpu_stb_data(env, dest, v); +v = cpu_ldub_data_ra(env, src, ra); +cpu_stb_data_ra(env, dest, v, ra); } for (; destlen; dest++, destlen--) { -cpu_stb_data(env, dest, pad); +cpu_stb_data_ra(env, dest, pad, ra); } env->regs[r1 + 1] = destlen; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 4ae949a..e3c5ba1 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2876,7 +2876,6 @@ static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); -potential_page_fault(s); gen_helper_mvcl(cc_op, cpu_env, r1, r2); tcg_temp_free_i32(r1); tcg_temp_free_i32(r2); -- 2.9.4
[Qemu-devel] [PULL v2 14/70] target/s390x: Use unwind data for helper_lam
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 3 ++- target/s390x/translate.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index e4bfc6e..88e817a 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -469,10 +469,11 @@ static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address, /* load access registers r1 to r3 from memory at a2 */ void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); int i; for (i = r1;; i = (i + 1) % 16) { -env->aregs[i] = cpu_ldl_data(env, a2); +env->aregs[i] = cpu_ldl_data_ra(env, a2, ra); a2 += 4; if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index d41a0fd..16477fc 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2626,7 +2626,6 @@ static ExitStatus op_lam(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -potential_page_fault(s); gen_helper_lam(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL v2 10/70] target/s390x: Use unwind data for helper_srst
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 3 ++- target/s390x/translate.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 3e75cae..33d83e5 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -327,6 +327,7 @@ static inline uint64_t get_address_31fix(CPUS390XState *env, int reg) uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, uint64_t str) { +uintptr_t ra = GETPC(); uint32_t len; uint8_t v, c = r0; @@ -344,7 +345,7 @@ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, env->cc_op = 2; return end; } -v = cpu_ldub_data(env, str + len); +v = cpu_ldub_data_ra(env, str + len, ra); if (v == c) { /* Character found. Set R1 to the location; R2 is unmodified. */ env->cc_op = 1; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index d4c5fa3..9fc5b31 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3977,7 +3977,6 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o) static ExitStatus op_srst(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return_low128(o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 06/70] target/s390x: Use unwind data for helper_xc
Reviewed-by: Aurelien JarnoSigned-off-by: Richard Henderson --- target/s390x/mem_helper.c | 44 target/s390x/translate.c | 1 - 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b4b50d1..b71437a 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -57,7 +57,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, #endif /* Reduce the length so that addr + len doesn't cross a page boundary. */ -static inline uint64_t adj_len_to_page(uint64_t len, uint64_t addr) +static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr) { #ifndef CONFIG_USER_ONLY if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) { @@ -68,7 +68,7 @@ static inline uint64_t adj_len_to_page(uint64_t len, uint64_t addr) } static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, -uint32_t l) +uint32_t l, uintptr_t ra) { int mmu_idx = cpu_mmu_index(env, false); @@ -76,14 +76,14 @@ static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, void *p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx); if (p) { /* Access to the whole page in write mode granted. */ -int l_adj = adj_len_to_page(l, dest); +uint32_t l_adj = adj_len_to_page(l, dest); memset(p, byte, l_adj); dest += l_adj; l -= l_adj; } else { /* We failed to get access to the whole page. The next write access will likely fill the QEMU TLB for the next iteration. */ -cpu_stb_data(env, dest, byte); +cpu_stb_data_ra(env, dest, byte, ra); dest++; l--; } @@ -100,7 +100,7 @@ static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src, void *dest_p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx); if (src_p && dest_p) { /* Access to both whole pages granted. */ -int l_adj = adj_len_to_page(l, src); +uint32_t l_adj = adj_len_to_page(l, src); l_adj = adj_len_to_page(l_adj, dest); memmove(dest_p, src_p, l_adj); src += l_adj; @@ -144,30 +144,34 @@ uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest, } /* xor on array */ -uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest, -uint64_t src) +static uint32_t do_helper_xc(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src, uintptr_t ra) { -int i; -unsigned char x; -uint32_t cc = 0; +uint32_t i; +uint8_t c = 0; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); /* xor with itself is the same as memset(0) */ if (src == dest) { -fast_memset(env, dest, 0, l + 1); +fast_memset(env, dest, 0, l + 1, ra); return 0; } for (i = 0; i <= l; i++) { -x = cpu_ldub_data(env, dest + i) ^ cpu_ldub_data(env, src + i); -if (x) { -cc = 1; -} -cpu_stb_data(env, dest + i, x); +uint8_t x = cpu_ldub_data_ra(env, src + i, ra); +x ^= cpu_ldub_data_ra(env, dest + i, ra); +c |= x; +cpu_stb_data_ra(env, dest + i, x, ra); } -return cc; +return c != 0; +} + +uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest, +uint64_t src) +{ +return do_helper_xc(env, l, dest, src, GETPC()); } /* or on array */ @@ -206,7 +210,7 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) /* mvc with source pointing to the byte after the destination is the same as memset with the first source byte */ if (dest == (src + 1)) { -fast_memset(env, dest, cpu_ldub_data(env, src), l + 1); +fast_memset(env, dest, cpu_ldub_data(env, src), l + 1, 0); return; } @@ -1235,8 +1239,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2), 0); break; case 0x700: -cc = helper_xc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); +cc = do_helper_xc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; case 0xc00: helper_tr(env, l, get_address(env, 0, b1, d1), diff --git a/target/s390x/translate.c b/target/s390x/translate.c index b1c1047..2c26308 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4165,7 +4165,6 @@ static ExitStatus op_xc(DisasContext *s, DisasOps *o) /* But in general we'll defer to a
[Qemu-devel] [PULL v2 11/70] target/s390x: Use unwind data for helper_clst
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 5 +++-- target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 33d83e5..af2801e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -362,6 +362,7 @@ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, /* unsigned string compare (c is string terminator) */ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2) { +uintptr_t ra = GETPC(); uint32_t len; c = c & 0xff; @@ -371,8 +372,8 @@ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2) /* Lest we fail to service interrupts in a timely manner, limit the amount of work we're willing to do. For now, let's cap at 8k. */ for (len = 0; len < 0x2000; ++len) { -uint8_t v1 = cpu_ldub_data(env, s1 + len); -uint8_t v2 = cpu_ldub_data(env, s2 + len); +uint8_t v1 = cpu_ldub_data_ra(env, s1 + len, ra); +uint8_t v2 = cpu_ldub_data_ra(env, s2 + len, ra); if (v1 == v2) { if (v1 == c) { /* Equal. CC=0, and don't advance the registers. */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 9fc5b31..b87755e 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1942,7 +1942,6 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o) static ExitStatus op_clst(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return_low128(o->in2); -- 2.9.4
[Qemu-devel] [PULL v2 09/70] target/s390x: Use unwind data for helper_clm
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 11 ++- target/s390x/translate.c | 1 - 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 50689bb..3e75cae 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -268,16 +268,16 @@ uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, uint64_t addr) { -uint8_t r, d; -uint32_t cc; +uintptr_t ra = GETPC(); +uint32_t cc = 0; HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1, mask, addr); -cc = 0; + while (mask) { if (mask & 8) { -d = cpu_ldub_data(env, addr); -r = (r1 & 0xff00UL) >> 24; +uint8_t d = cpu_ldub_data_ra(env, addr, ra); +uint8_t r = extract32(r1, 24, 8); HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d, addr); if (r < d) { @@ -292,6 +292,7 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, mask = (mask << 1) & 0xf; r1 <<= 8; } + HELPER_LOG("\n"); return cc; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index c47b818..d4c5fa3 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1933,7 +1933,6 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o) TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); TCGv_i32 t1 = tcg_temp_new_i32(); tcg_gen_extrl_i64_i32(t1, o->in1); -potential_page_fault(s); gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2); set_cc_static(s); tcg_temp_free_i32(t1); -- 2.9.4
[Qemu-devel] [PULL v2 12/70] target/s390x: Use unwind data for helper_mvpg
Reviewed-by: Thomas HuthReviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/helper.h | 2 +- target/s390x/mem_helper.c | 9 + target/s390x/translate.c | 3 +-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 1fae191..ea35834 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -12,7 +12,7 @@ DEF_HELPER_FLAGS_3(divs64, TCG_CALL_NO_WG, s64, env, s64, s64) DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64) DEF_HELPER_4(srst, i64, env, i64, i64, i64) DEF_HELPER_4(clst, i64, env, i64, i64, i64) -DEF_HELPER_4(mvpg, void, env, i64, i64, i64) +DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64) DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index af2801e..1c36a47 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -398,11 +398,12 @@ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2) } /* move page */ -void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) +uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) { -/* XXX missing r0 handling */ -env->cc_op = 0; -fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, 0); +/* ??? missing r0 handling, which includes access keys, but more + importantly optional suppression of the exception! */ +fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, GETPC()); +return 0; /* data moved */ } /* string copy (c is string terminator) */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index b87755e..ae29889 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2921,8 +2921,7 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o) static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) { -potential_page_fault(s); -gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2); +gen_helper_mvpg(cc_op, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return NO_EXIT; } -- 2.9.4