Re: [Qemu-devel] [RFC] q35/mch: implement extended TSEG sizes

2017-06-06 Thread Gerd Hoffmann
  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

2017-06-06 Thread Greg Kurz
On Wed, 7 Jun 2017 09:45:06 +1000
David Gibson  wrote:

> 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()

2017-06-06 Thread Mao Zhongyi

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

2017-06-06 Thread Anatol Pomozov
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

2017-06-06 Thread Launchpad Bug Tracker
[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

2017-06-06 Thread no-reply
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

2017-06-06 Thread Launchpad Bug Tracker
[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

2017-06-06 Thread Launchpad Bug Tracker
[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

2017-06-06 Thread Launchpad Bug Tracker
[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

2017-06-06 Thread Launchpad Bug Tracker
[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

2017-06-06 Thread Peter Xu
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

2017-06-06 Thread Jason Wang
From: Mao Zhongyi 

None 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

2017-06-06 Thread Jason Wang
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

2017-06-06 Thread Jason Wang
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

2017-06-06 Thread Peter Xu
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

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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)

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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()

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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

2017-06-06 Thread David Gibson
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-06-06 Thread QingFeng Hao



在 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 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?


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

2017-06-06 Thread Peter Xu
On Tue, Jun 06, 2017 at 07:33:45PM +0200, Juan Quintela wrote:
> Peter Xu  wrote:
> > 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

2017-06-06 Thread Mao Zhongyi

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

2017-06-06 Thread Mao Zhongyi

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 Zhongyi 


We 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

2017-06-06 Thread Richard Henderson

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

2017-06-06 Thread Richard Henderson
From: David Hildenbrand 

We 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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Signed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Signed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Signed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

As 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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

There 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

2017-06-06 Thread Richard Henderson

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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

For 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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson

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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

As 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

2017-06-06 Thread Wei Wang

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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

The 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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

And 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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Improve 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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Signed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

These 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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Signed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
From: Thomas Huth 

Currently 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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
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 Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
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 Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Use 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

2017-06-06 Thread Richard Henderson
Also provide the cross-cpu tlb flushing required by the PoO.

Reviewed-by: Aurelien Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

adj_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

2017-06-06 Thread Richard Henderson
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 Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
Use this saved value instead of recomputing from next_pc difference.

Reviewed-by: David Hildenbrand 
Reviewed-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

2017-06-06 Thread Richard Henderson
(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 Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
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 Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
Fix saving exception_index around mmu_translate; eliminate a dead store.

Reviewed-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 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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
From: Aurelien Jarno 

Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Aurelien Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Aurelien Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Aurelien Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Aurelien Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Aurelien Jarno 
Signed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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

2017-06-06 Thread Richard Henderson
Reviewed-by: Thomas Huth 
Reviewed-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




  1   2   3   4   5   >