Re: [Qemu-devel] [RFC PATCH V3 0/3] filter-rewriter: introduce filter-rewriter

2016-07-26 Thread Zhang Chen



On 07/27/2016 10:50 AM, Jason Wang wrote:



On 2016年07月27日 10:32, Zhang Chen wrote:

Hi~ all~~

Anyone have some comments for this series?


Will have a look at this.

Btw. I wonder how this is tested, do we need a unit test for this?


COLO-compare and filter-rewriter works normal depend on colo-frame.
So, When colo-frame be merged I will send a colo-proxy unit test
for all filter-mirror,filter-redirector,colo-compare,filter-rewriter.






We need more comments to improve COLO codes.


Thanks

Zhang Chen


On 07/05/2016 06:29 PM, Zhang Chen wrote:

Filter-rewriter is a part of COLO project.
So this patch set depend on colo-compare.


Interesting, I thought it can co-work with comparing, and the 
communication were done through socket now. So I think technically the 
filter itself could work without COLO?


Filter-rewriter can run without COLO, but it no sense for other people.
rewriter need TX tcp packet differ with RX tcp packet...
In normal qemu we can't get the environment same with COLO.





It will rewrite some of secondary packet to make
secondary guest's connection established successfully.
In this module we will rewrite tcp packet's ack to the secondary
from primary,and rewrite tcp packet's seq to the primary from
secondary.

v3:
   - fix typo
   - add conn->syn_flag
   - add some comments
   - remove conn_list_lock
   - fix offset set bug


I think you can remove RFC in the next version so we can try to merge 
it after one or several other iterations.


OK~~ I will remove RFC in colo-compare and filter-rewriter.

Thanks for your review~~
Zhang Chen



Thanks



v2:
   - add more comments about packet flows
   - add some trace-event
   - add seq offset ( = secondary_seq - primary_seq)

v1:
   - initial patch

Zhang Chen (3):
   filter-rewriter: introduce filter-rewriter initialization
   filter-rewriter: track connection and parse packet
   filter-rewriter: rewrite tcp packet to keep secondary connection

  net/Makefile.objs |   1 +
  net/colo-base.c   |   2 +
  net/colo-base.h   |   7 ++
  net/filter-rewriter.c | 262 
++

  qemu-options.hx   |  13 +++
  trace-events  |   5 +
  vl.c  |   3 +-
  7 files changed, 292 insertions(+), 1 deletion(-)
  create mode 100644 net/filter-rewriter.c







.



--
Thanks
zhangchen






[Qemu-devel] [PATCH 1/1] spapr: Prevent boot CPU core removal

2016-07-26 Thread Bharata B Rao
Boot CPU is assumed to be always present in QEMU code. So
until that assumptions are gone, deny removal request.
In another words, QEMU won't support boot CPU core hot-unplug.

Signed-off-by: Bharata B Rao 
---
 hw/ppc/spapr_cpu_core.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 5a132bf..0dadf48 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -133,6 +133,11 @@ void spapr_core_unplug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 sPAPRDRConnectorClass *drck;
 Error *local_err = NULL;
 
+if (index == 0) {
+error_setg(errp, "Boot CPU core is unpluggable");
+return;
+}
+
 g_assert(drc);
 
 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
-- 
2.7.4




Re: [Qemu-devel] Segfault with coalesced mmio and boot CPU removal

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 10:01:41AM +0530, Bharata B Rao wrote:
> On Wed, Jul 27, 2016 at 08:22:51AM +0530, Bharata B Rao wrote:
> > Hi,
> > 
> > Coalesced mmio buffer is part of vCPU 0's kvm_run mmap'ed area
> > and with the introduction of CPU hotplug, vCPU 0 can be removed on
> > PowerPC leading to the below seen segfault in QEMU.
> > 
> > 
> > This happens because during CPU removal, though we park the kvm_fd
> > corresponding to the removed vCPU thread, we unmap the kvm_run (and
> > hence coalesced mmio ring).
> > 
> 
> > What would be the best way to fix this ? Is disassociating 
> > coalesced_mmio_ring
> > from vCPU 0's kvm_run the correct solution ?
> 
> May be PowerPC too should do what x86 does like below for now ?

I think that's what we need to do short term.  In the 2.8 timeframe,
separating the mmio ring out from the vcpu state sounds like a good
idea, but I don't really know how complicated that will be.

> 
> commit 73360e27850b213327011f7e22e03865b8c0dd5b
> Author: Igor Mammedov 
> Date:   Mon Jul 18 10:31:22 2016 +0200
> 
> pc: Forbid BSP removal
> 
> Boot CPU is assumed to always present in QEMU code, so
> untile that assumptions are gone, deny removal request,
> In another words QEMU won't support BSP hot-unplug.
> 

-- 
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 V5 0/7] pxb: fix 64-bit MMIO allocation

2016-07-26 Thread Michael S. Tsirkin
On Wed, Jul 27, 2016 at 07:27:11AM +0300, Marcel Apfelbaum wrote:
> On 07/26/2016 09:30 PM, Michael S. Tsirkin wrote:
> > On Sun, Jul 17, 2016 at 07:53:07PM +0300, Marcel Apfelbaum wrote:
> > > 
> > > v4 -> v5:
> > >   Addressed the pull request issues: (Peter Maydell)
> > >   See: https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg00882.html
> > >   - cland warning -> "hw/pci/pci.c:196:23: runtime error: shift exponent 
> > > -1 is negative":
> > > The PCIe Root port was not initialized properly, the interrupt pin 
> > > was left 0. This
> > > is a long standing issue exposed by the new test. (Patch 1/7)
> > >   - 'make check' fails on 32-bit:
> > >  Fix it by changing the ivshmem mem size from 4G
> > >  to 1G, since 4G is not a valid value on 32-bit archs. (Patch 2/7)
> > >  (4G is truncated to 0 on 32-bit systems)
> > >   - Rebased on mst's pci branch.
> > >   Since all the new changes are not related to the series, I kept the 
> > > existing
> > >   "Reviewed-by"/"Tested-by" signatures.
> > 
> 
> Hi Michael,
> 
> > Applied,
> 
> Thanks!
> 
> Can you please apply also '[PATCH V3] hw/virtio-pci: fix virtio behaviour'?
> (https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg04744.html)
> 
> I think it worth having it in QEMU 2.7.
> 
>  but dropped tests for now - from experience they are too likely
> > to break on weird platforms.
> > Pls post new tests after 2.7.
> > 
> 
> Sure, I'll do that.
> 
> > Also, I would really like to see options to speed tests up.
> > How about running them under kvm?
> > There are a couple of minor acpi differences when running with kvm,
> > we'll need to white-list them in some way.
> > 
> 
> Sure, we can do kvm 'variant' maybe for for 2.8.


Yes but without maintaining two variants o expected files please.


> Thanks,
> Marcel
> 
> > 
> > 
> 
> > > v3 -> v4:
> > >  Addressed Igor's comments (thanks for the productive review!)
> > >  - Split pxb test patch (previously patch 3/3) into the test itself 
> > > (patch 1/6) and the blobs (patch 6/6).
> > >  - New patch declaring pxb/pxb-pxie as not hot-pluggable.
> > > - Note that it does not solve the DSDT issue, but it is a 
> > > prerequisite for the next patch.
> > >  - New patch solving the DSDT issue spotted by Igor.
> > >  - Using V=1 DIFF=diff make check does make it easier to review the 
> > > ACPI changes, thanks.
> > >  - Patches 4 and 5 untouched (previously patches 1/3 and 2/3)
> > > 
> > > v2 -> v3:
> > >  - split original series "pci: better support for 64-bit MMIO allocation" 
> > > into 2 series:
> > > - this is the first part dealing with correct 64-bit MMIO ACPI 
> > > computation
> > > - the second one will include 64-bit MMIO reservation for PCI hotplug
> > >  - Add pxb/pxb-pcie tests (Igor) - See diffs below (*)
> > >  - Re-based on latest master.
> > > 
> > > v1 -> v2:
> > >  - resolved some styling issues (Laszlo)
> > >  - rebase on latest master (Laszlo)
> > > 
> > > 
> > > 
> > > 64-bit BARs allocations fix for devices behind PXBs/PXB-PCIEs.
> > > 
> > > In build_crs() the calculation and merging of the ranges already happens
> > > in 64-bit, but the entry boundaries are silently truncated to 32-bit in 
> > > the
> > > call to aml_dword_memory(). Fix it by handling the 64-bit MMIO ranges 
> > > separately.
> > > 
> > > 
> > > Thank you,
> > > Marcel
> > > 
> > > Marcel Apfelbaum (7):
> > >   hw/pcie-root-port: Fix PCIe root port initialization
> > >   tests/acpi: add pxb/pxb-pcie tests
> > >   hw/pxb: declare pxb devices as not hot-pluggable
> > >   hw/acpi: fix a DSDT table issue when a pxb is present.
> > >   acpi: refactor pxb crs computation
> > >   hw/apci: handle 64-bit MMIO regions correctly
> > >   tests/acpi: Add pxb/pxb-pcie tests blobs
> > > 
> > >  hw/i386/acpi-build.c   | 131 
> > > -
> > >  hw/pci-bridge/ioh3420.c|   1 +
> > >  hw/pci-bridge/pci_expander_bridge.c|   2 +
> > >  tests/acpi-test-data/pc/DSDT.pxb   | Bin 0 -> 6286 bytes
> > >  tests/acpi-test-data/q35/DSDT.pxb_pcie | Bin 0 -> 9098 bytes
> > >  tests/bios-tables-test.c   |  37 ++
> > >  6 files changed, 135 insertions(+), 36 deletions(-)
> > >  create mode 100644 tests/acpi-test-data/pc/DSDT.pxb
> > >  create mode 100644 tests/acpi-test-data/q35/DSDT.pxb_pcie
> > > 
> > > --
> > > 2.4.3
> 



Re: [Qemu-devel] [PATCH 16/32] ppc: Rework NIP updates vs. exception generation

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:19 +1000, David Gibson wrote:
> twi etc will generally resume from the next instruction if they trap,
> yes?  In which case I'm a bit confused by the nip - 4.  But possibly I
> just haven't correctly followed all the nip update logic changed by
> this patch.

>From the ISA (Program Check interrupt)

Trap
A Trap type Program interrupt is generated when
any of the
conditions specified in a Trap instruction
is met.

The following registers are set:
SRR0
For all Program interrupts except a Float-
ing-Point Enabled Exception type Program
interrupt, set to the effective address of the
instruction that caused the corresponding
exception.

Cheers,
Ben.




Re: [Qemu-devel] Segfault with coalesced mmio and boot CPU removal

2016-07-26 Thread Bharata B Rao
On Wed, Jul 27, 2016 at 08:22:51AM +0530, Bharata B Rao wrote:
> Hi,
> 
> Coalesced mmio buffer is part of vCPU 0's kvm_run mmap'ed area
> and with the introduction of CPU hotplug, vCPU 0 can be removed on
> PowerPC leading to the below seen segfault in QEMU.
> 
> 
> This happens because during CPU removal, though we park the kvm_fd
> corresponding to the removed vCPU thread, we unmap the kvm_run (and
> hence coalesced mmio ring).
> 

> What would be the best way to fix this ? Is disassociating coalesced_mmio_ring
> from vCPU 0's kvm_run the correct solution ?

May be PowerPC too should do what x86 does like below for now ?

commit 73360e27850b213327011f7e22e03865b8c0dd5b
Author: Igor Mammedov 
Date:   Mon Jul 18 10:31:22 2016 +0200

pc: Forbid BSP removal

Boot CPU is assumed to always present in QEMU code, so
untile that assumptions are gone, deny removal request,
In another words QEMU won't support BSP hot-unplug.




Re: [Qemu-devel] [PATCH V5 0/7] pxb: fix 64-bit MMIO allocation

2016-07-26 Thread Marcel Apfelbaum

On 07/26/2016 09:30 PM, Michael S. Tsirkin wrote:

On Sun, Jul 17, 2016 at 07:53:07PM +0300, Marcel Apfelbaum wrote:


v4 -> v5:
  Addressed the pull request issues: (Peter Maydell)
  See: https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg00882.html
  - cland warning -> "hw/pci/pci.c:196:23: runtime error: shift exponent -1 is 
negative":
The PCIe Root port was not initialized properly, the interrupt pin was left 
0. This
is a long standing issue exposed by the new test. (Patch 1/7)
  - 'make check' fails on 32-bit:
 Fix it by changing the ivshmem mem size from 4G
 to 1G, since 4G is not a valid value on 32-bit archs. (Patch 2/7)
 (4G is truncated to 0 on 32-bit systems)
  - Rebased on mst's pci branch.
  Since all the new changes are not related to the series, I kept the existing
  "Reviewed-by"/"Tested-by" signatures.




Hi Michael,


Applied,


Thanks!

Can you please apply also '[PATCH V3] hw/virtio-pci: fix virtio behaviour'?
(https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg04744.html)

I think it worth having it in QEMU 2.7.

 but dropped tests for now - from experience they are too likely

to break on weird platforms.
Pls post new tests after 2.7.



Sure, I'll do that.


Also, I would really like to see options to speed tests up.
How about running them under kvm?
There are a couple of minor acpi differences when running with kvm,
we'll need to white-list them in some way.



Sure, we can do kvm 'variant' maybe for for 2.8.

Thanks,
Marcel







v3 -> v4:
 Addressed Igor's comments (thanks for the productive review!)
 - Split pxb test patch (previously patch 3/3) into the test itself (patch 1/6) 
and the blobs (patch 6/6).
 - New patch declaring pxb/pxb-pxie as not hot-pluggable.
- Note that it does not solve the DSDT issue, but it is a prerequisite for 
the next patch.
 - New patch solving the DSDT issue spotted by Igor.
 - Using V=1 DIFF=diff make check does make it easier to review the ACPI 
changes, thanks.
 - Patches 4 and 5 untouched (previously patches 1/3 and 2/3)

v2 -> v3:
 - split original series "pci: better support for 64-bit MMIO allocation" into 
2 series:
- this is the first part dealing with correct 64-bit MMIO ACPI computation
- the second one will include 64-bit MMIO reservation for PCI hotplug
 - Add pxb/pxb-pcie tests (Igor) - See diffs below (*)
 - Re-based on latest master.

v1 -> v2:
 - resolved some styling issues (Laszlo)
 - rebase on latest master (Laszlo)



64-bit BARs allocations fix for devices behind PXBs/PXB-PCIEs.

In build_crs() the calculation and merging of the ranges already happens
in 64-bit, but the entry boundaries are silently truncated to 32-bit in the
call to aml_dword_memory(). Fix it by handling the 64-bit MMIO ranges 
separately.


Thank you,
Marcel

Marcel Apfelbaum (7):
  hw/pcie-root-port: Fix PCIe root port initialization
  tests/acpi: add pxb/pxb-pcie tests
  hw/pxb: declare pxb devices as not hot-pluggable
  hw/acpi: fix a DSDT table issue when a pxb is present.
  acpi: refactor pxb crs computation
  hw/apci: handle 64-bit MMIO regions correctly
  tests/acpi: Add pxb/pxb-pcie tests blobs

 hw/i386/acpi-build.c   | 131 -
 hw/pci-bridge/ioh3420.c|   1 +
 hw/pci-bridge/pci_expander_bridge.c|   2 +
 tests/acpi-test-data/pc/DSDT.pxb   | Bin 0 -> 6286 bytes
 tests/acpi-test-data/q35/DSDT.pxb_pcie | Bin 0 -> 9098 bytes
 tests/bios-tables-test.c   |  37 ++
 6 files changed, 135 insertions(+), 36 deletions(-)
 create mode 100644 tests/acpi-test-data/pc/DSDT.pxb
 create mode 100644 tests/acpi-test-data/q35/DSDT.pxb_pcie

--
2.4.3





Re: [Qemu-devel] [PATCH v3 0/2] vhost-user: Extend protocol to receive replies on any command.

2016-07-26 Thread Michael S. Tsirkin
On Mon, Jul 25, 2016 at 02:27:18PM +0400, Marc-André Lureau wrote:
> Hi
> 
> On Mon, Jul 25, 2016 at 10:41 AM, Prerna  wrote:
> >
> >
> > On Thu, Jul 7, 2016 at 12:04 PM, Prerna Saxena 
> > wrote:
> >>
> >> From: Prerna Saxena 
> >>
> >> The current vhost-user protocol requires the client to send responses to
> >> only a
> >> few commands. For the remaining commands, it is impossible for QEMU to
> >> know the
> >> status of the requested operation -- ie, did it succeed? If so, by what
> >> time?
> >>
> >> This is inconvenient, and can also lead to races. As an example:
> >>  [..snip..]
> >>
> >> References:
> >> v1 : https://lists.gnu.org/archive/html/qemu-devel/2016-06/msg07152.html
> >> v2 : https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg00048.html
> >>
> >>
> >> Prerna Saxena (2):
> >>   vhost-user: Introduce a new protocol feature REPLY_ACK.
> >>   vhost-user: Attempt to fix a race with set_mem_table.
> >>
> >>  docs/specs/vhost-user.txt |  44 +++
> >>  hw/virtio/vhost-user.c| 133
> >> ++
> >>  2 files changed, 130 insertions(+), 47 deletions(-)
> >>
> >
> > Ping !
> > Michael, MarcAndre, Did you have a chance to look at this patch series?
> >
> 
> That's not going to make it in 2.7 I am afraid.

It's a bugfix so - depends on how quickly can comments be addressed.

-- 
MST



Re: [Qemu-devel] [PATCH] util: Relax assertion in iov_copy()

2016-07-26 Thread Michael S. Tsirkin
On Mon, Jul 25, 2016 at 02:43:35PM +0300, Shmulik Ladkani wrote:
> From: Shmulik Ladkani 
> 
> In cases where iov_copy() is passed with zero 'bytes' argument and a
> non-zero 'offset' argument, nothing gets copied - as expected.
> 
> However since no copy iterations are performed, 'offset' is left
> unaltered, leading to the final assert(offset == 0) to fail.
> 
> Relax the assertion: if j (number of dst elements assigned) is zero, no
> need to err.
> 
> Only if j!=0 (some dst elements assigned) AND offset!=0 we should err.
> 
> Signed-off-by: Shmulik Ladkani 

Reviewed-by: Michael S. Tsirkin 

> ---
>  util/iov.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> Flow that led to the assertion was:
>   net_tx_pkt_rebuild_payload()
> iov_copy(... , pkt->payload_len)
> 
> where pkt->payload_len was correctly calculated to be 0 (a packet
> carrying just ipv4 header, without any payload).
> 
> An alternative is to place the below code, early in iov_copy():
> if (!bytes)
> return 0;
> 
> diff --git a/util/iov.c b/util/iov.c
> index 003fcce..17de52d 100644
> --- a/util/iov.c
> +++ b/util/iov.c
> @@ -260,7 +260,7 @@ unsigned iov_copy(struct iovec *dst_iov, unsigned int 
> dst_iov_cnt,
>  bytes -= len;
>  offset = 0;
>  }
> -assert(offset == 0);
> +assert(j == 0 || offset == 0);
>  return j;
>  }
>  
> -- 
> 1.9.1
> 



Re: [Qemu-devel] [PATCH 32/32] ppc: Speed up load/store multiple

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:47 +1000, David Gibson wrote:
> > +#if defined(HOST_WORDS_BIGENDIAN)
> > +    memcpy(>gpr[reg], src, adjlen);
> > +    reg += (adjlen >> 2);
> > +    addr = addr_add(env, addr, adjlen);
> > +#else
> > +    while(adjlen) {
> > +    env->gpr[reg++] = bswap32(*(src++));
> > +    adjlen -= 4;
> > +    addr = addr_add(env, addr, 4);
> > +    }
> > +#endif
> 
> Would it improve this any further to do the memcpy() unconditionally,
> then byteswap the GPRs in-place for the LE host case?

I thought about it and decided probably not. It's not a big enough
memcpy to matter I suspect. And it keeps the code simpler.

Cheers,
Ben.



Re: [Qemu-devel] [PATCH 26/32] ppc: Speed up dcbz

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:36 +1000, David Gibson wrote:
> > -    do_dcbz(env, addr, dcbz_size, GETPC());
> > +    /* Try fast path translate */
> > +    haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, env->dmmu_idx);
> 
> It worries me slightly that this doesn't take any length to verify.  I
> guess it's ok in practice, because memory blocks will always be at
> least cache line size aligned.

It's safe ;-)

The translate returns a qemu page size address which is always 4K.

We don't need to verify  because we just aligned the address to the
cache block size which is always smaller than 4k. So we can't
possibly be crossing a page boundary.

(grep for tlb_vaddr_to_host in target-s390 for other examples of use
of tlb_vaddr_to_host).

Cheers,
Ben.




Re: [Qemu-devel] [PATCH 25/32] ppc: Handle unconditional (always/never) traps at translation time

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:33 +1000, David Gibson wrote:
> 
> Should you be returning true here?
> 
> Without it, IIUC, the functions below will generate the unconditional
> trap, then generate more code to actually test the condition and trap
> again.

You are right, we generate dead code, will fix.

Cheers,
Ben.

> > 
> > +}
> > +return false;
> > +}
> > +
> >  /* tw */
> >  static void gen_tw(DisasContext *ctx)
> >  {
> > -TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
> > +TCGv_i32 t0;
> > +
> > +if (check_unconditional_trap(ctx)) {
> > +return;
> > +}
> > +t0 = tcg_const_i32(TO(ctx->opcode));
> >  gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)],
> > cpu_gpr[rB(ctx->opcode)],
> >    t0);
> >  tcg_temp_free_i32(t0);
> > @@ -3372,8 +3391,14 @@ static void gen_tw(DisasContext *ctx)
> >  /* twi */
> >  static void gen_twi(DisasContext *ctx)
> >  {
> > -TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
> > -TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
> > +TCGv t0;
> > +TCGv_i32 t1;
> > +
> > +if (check_unconditional_trap(ctx)) {
> > +return;
> > +}
> > +t0 = tcg_const_tl(SIMM(ctx->opcode));
> > +t1 = tcg_const_i32(TO(ctx->opcode));
> >  gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
> >  tcg_temp_free(t0);
> >  tcg_temp_free_i32(t1);
> > @@ -3383,7 +3408,12 @@ static void gen_twi(DisasContext *ctx)
> >  /* td */
> >  static void gen_td(DisasContext *ctx)
> >  {
> > -TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
> > +TCGv_i32 t0;
> > +
> > +if (check_unconditional_trap(ctx)) {
> > +return;
> > +}
> > +t0 = tcg_const_i32(TO(ctx->opcode));
> >  gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)],
> > cpu_gpr[rB(ctx->opcode)],
> >    t0);
> >  tcg_temp_free_i32(t0);
> > @@ -3392,8 +3422,14 @@ static void gen_td(DisasContext *ctx)
> >  /* tdi */
> >  static void gen_tdi(DisasContext *ctx)
> >  {
> > -TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
> > -TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
> > +TCGv t0;
> > +TCGv_i32 t1;
> > +
> > +if (check_unconditional_trap(ctx)) {
> > +return;
> > +}
> > +t0 = tcg_const_tl(SIMM(ctx->opcode));
> > +t1 = tcg_const_i32(TO(ctx->opcode));
> >  gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
> >  tcg_temp_free(t0);
> >  tcg_temp_free_i32(t1);
> 


Re: [Qemu-devel] [PATCH 24/32] ppc: Make alignment exceptions suck less

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:30 +1000, David Gibson wrote:
> On Wed, Jul 27, 2016 at 08:21:18AM +1000, Benjamin Herrenschmidt
> wrote:
> > 
> > The current alignment exception generation tries to load the opcode
> > to put in DSISR from a context where a cpu_ldl_code() is really not
> > a good idea. It might fault and longjmp out and that's not
> > something
> > we want happening here.
> > 
> > Instead, pass the releavant opcode bits via the error_code.
> > 
> > There are a couple of cases of alignment interrupts that won't set
> > anything, the ones coming from access to direct store segments, but
> > that doesn't happen in practice, nobody used direct store segments
> > and they are gone from newer chips.
> 
> Do I understand correctly that this isn't actually new?  This was
> already wrong for direct store segments, you've just noted it?

No, it was *supposeldy* working by loading the opcode to set DSISR
but I'm breaking it. It's not safe to try to load the opcode from
the exception helper, it can cause us to longjmp into lalaland.

If we really care, we could fix it differently by making the
translation code load the opcode to pass it up to us like the generated
code does. The translation code is run in a context that can safely
exit via longjmp, so in that case, if the opcode load fails, it will
just generate an ISI and try again.

However I can't find anything that actually uses direct store segments
so can't be bothered.

Cheers,
Ben.

> > 
> > 
> > Signed-off-by: Benjamin Herrenschmidt 
> > ---
> >  target-ppc/excp_helper.c | 9 +
> >  target-ppc/translate.c   | 2 +-
> >  2 files changed, 6 insertions(+), 5 deletions(-)
> > 
> > diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> > index c31bbad..9a26578 100644
> > --- a/target-ppc/excp_helper.c
> > +++ b/target-ppc/excp_helper.c
> > @@ -260,11 +260,12 @@ static inline void powerpc_excp(PowerPCCPU
> > *cpu, int excp_model, int excp)
> >  }
> >  break;
> >  case POWERPC_EXCP_ALIGN: /* Alignment
> > exception  */
> > -/* XXX: this is false */
> >  /* Get rS/rD and rA from faulting opcode */
> > -/* Broken for LE mode */
> > -env->spr[SPR_DSISR] |= (cpu_ldl_code(env, env->nip)
> > -& 0x03FF) >> 16;
> > +/* Note: the opcode fields will not be set properly for a
> > direct
> > + * store load/store, but nobody cares as nobody actually
> > uses
> > + * direct store segments.
> > + */
> > +env->spr[SPR_DSISR] |= (env->error_code & 0x03FF) >>
> > 16;
> >  break;
> >  case POWERPC_EXCP_PROGRAM:   /* Program
> > exception*/
> >  switch (env->error_code & ~0xF) {
> > diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> > index ddfec33..9af3f5f 100644
> > --- a/target-ppc/translate.c
> > +++ b/target-ppc/translate.c
> > @@ -2202,7 +2202,7 @@ static inline void
> > gen_check_align(DisasContext *ctx, TCGv EA, int mask)
> >  tcg_gen_andi_tl(t0, EA, mask);
> >  tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
> >  t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
> > -t2 = tcg_const_i32(0);
> > +t2 = tcg_const_i32(ctx->opcode & 0x03FF);
> >  gen_update_nip(ctx, ctx->nip - 4);
> >  gen_helper_raise_exception_err(cpu_env, t1, t2);
> >  tcg_temp_free_i32(t1);
> 


Re: [Qemu-devel] [PATCH 21/32] ppc: Don't update NIP on conditional trap instructions

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:26 +1000, David Gibson wrote:
> On Wed, Jul 27, 2016 at 08:21:15AM +1000, Benjamin Herrenschmidt
> wrote:
> > 
> > This is no longer necessary as the helpers will properly retrieve
> > the return address when needed.
> 
> Is this right?  Don't the tw etc. instructions continue on rather
> than retrying if an exception occurs?

What do you mean ? I'm not sure I understand...

Cheers,
Ben.

> > 
> > 
> > Signed-off-by: Benjamin Herrenschmidt 
> > ---
> >  target-ppc/excp_helper.c | 6 --
> >  target-ppc/translate.c   | 8 
> >  2 files changed, 4 insertions(+), 10 deletions(-)
> > 
> > diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> > index 570d188..c31bbad 100644
> > --- a/target-ppc/excp_helper.c
> > +++ b/target-ppc/excp_helper.c
> > @@ -1031,7 +1031,8 @@ void helper_tw(CPUPPCState *env, target_ulong
> > arg1, target_ulong arg2,
> >    ((int32_t)arg1 == (int32_t)arg2 && (flags &
> > 0x04)) ||
> >    ((uint32_t)arg1 < (uint32_t)arg2 && (flags &
> > 0x02)) ||
> >    ((uint32_t)arg1 > (uint32_t)arg2 && (flags &
> > 0x01) {
> > -raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> > POWERPC_EXCP_TRAP);
> > +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> > +   POWERPC_EXCP_TRAP, GETPC());
> >  }
> >  }
> >  
> > @@ -1044,7 +1045,8 @@ void helper_td(CPUPPCState *env, target_ulong
> > arg1, target_ulong arg2,
> >    ((int64_t)arg1 == (int64_t)arg2 && (flags &
> > 0x04)) ||
> >    ((uint64_t)arg1 < (uint64_t)arg2 && (flags &
> > 0x02)) ||
> >    ((uint64_t)arg1 > (uint64_t)arg2 && (flags &
> > 0x01) {
> > -raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> > POWERPC_EXCP_TRAP);
> > +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> > +   POWERPC_EXCP_TRAP, GETPC());
> >  }
> >  }
> >  #endif
> > diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> > index 8f5afba..7163b19 100644
> > --- a/target-ppc/translate.c
> > +++ b/target-ppc/translate.c
> > @@ -3365,8 +3365,6 @@ static void gen_sc(DisasContext *ctx)
> >  static void gen_tw(DisasContext *ctx)
> >  {
> >  TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
> > -/* Update the nip since this might generate a trap exception
> > */
> > -gen_update_nip(ctx, ctx->nip - 4);
> >  gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)],
> > cpu_gpr[rB(ctx->opcode)],
> >    t0);
> >  tcg_temp_free_i32(t0);
> > @@ -3377,8 +3375,6 @@ static void gen_twi(DisasContext *ctx)
> >  {
> >  TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
> >  TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
> > -/* Update the nip since this might generate a trap exception
> > */
> > -gen_update_nip(ctx, ctx->nip - 4);
> >  gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
> >  tcg_temp_free(t0);
> >  tcg_temp_free_i32(t1);
> > @@ -3389,8 +3385,6 @@ static void gen_twi(DisasContext *ctx)
> >  static void gen_td(DisasContext *ctx)
> >  {
> >  TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
> > -/* Update the nip since this might generate a trap exception
> > */
> > -gen_update_nip(ctx, ctx->nip - 4);
> >  gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)],
> > cpu_gpr[rB(ctx->opcode)],
> >    t0);
> >  tcg_temp_free_i32(t0);
> > @@ -3401,8 +3395,6 @@ static void gen_tdi(DisasContext *ctx)
> >  {
> >  TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
> >  TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
> > -/* Update the nip since this might generate a trap exception
> > */
> > -gen_update_nip(ctx, ctx->nip - 4);
> >  gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
> >  tcg_temp_free(t0);
> >  tcg_temp_free_i32(t1);
> 


Re: [Qemu-devel] [PATCH 18/32] ppc: Don't update NIP in DCR access routines

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:21 +1000, David Gibson wrote:
> On Wed, Jul 27, 2016 at 08:21:12AM +1000, Benjamin Herrenschmidt
> wrote:
> > 
> > This is no longer necessary as the helpers will properly retrieve
> > the return address when needed
> 
> Well, the helpers are only fixed in this patch IIUC.

Yes, all these "Don't update NIP" patches do both the helper and the
removal of the NIP fixup. I can reword the messages if you have a
better wording.
> > 
> > 
> > Signed-off-by: Benjamin Herrenschmidt 
> > ---
> >  target-ppc/timebase_helper.c | 23 +--
> >  target-ppc/translate.c   | 12 
> >  2 files changed, 13 insertions(+), 22 deletions(-)
> > 
> > diff --git a/target-ppc/timebase_helper.c b/target-
> > ppc/timebase_helper.c
> > index a07faa4..73363e0 100644
> > --- a/target-ppc/timebase_helper.c
> > +++ b/target-ppc/timebase_helper.c
> > @@ -19,6 +19,7 @@
> >  #include "qemu/osdep.h"
> >  #include "cpu.h"
> >  #include "exec/helper-proto.h"
> > +#include "exec/exec-all.h"
> >  #include "qemu/log.h"
> >  
> >  /*
> > /
> > @@ -143,15 +144,16 @@ target_ulong helper_load_dcr(CPUPPCState
> > *env, target_ulong dcrn)
> >  
> >  if (unlikely(env->dcr_env == NULL)) {
> >  qemu_log_mask(LOG_GUEST_ERROR, "No DCR environment\n");
> > -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> > -   POWERPC_EXCP_INVAL |
> > -   POWERPC_EXCP_INVAL_INVAL);
> > +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> > +   POWERPC_EXCP_INVAL |
> > +   POWERPC_EXCP_INVAL_INVAL, GETPC());
> >  } else if (unlikely(ppc_dcr_read(env->dcr_env,
> >   (uint32_t)dcrn, ) != 0))
> > {
> >  qemu_log_mask(LOG_GUEST_ERROR, "DCR read error %d %03x\n",
> >    (uint32_t)dcrn, (uint32_t)dcrn);
> > -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> > -   POWERPC_EXCP_INVAL |
> > POWERPC_EXCP_PRIV_REG);
> > +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> > +   POWERPC_EXCP_INVAL |
> > +   POWERPC_EXCP_PRIV_REG, GETPC());
> >  }
> >  return val;
> >  }
> > @@ -160,14 +162,15 @@ void helper_store_dcr(CPUPPCState *env,
> > target_ulong dcrn, target_ulong val)
> >  {
> >  if (unlikely(env->dcr_env == NULL)) {
> >  qemu_log_mask(LOG_GUEST_ERROR, "No DCR environment\n");
> > -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> > -   POWERPC_EXCP_INVAL |
> > -   POWERPC_EXCP_INVAL_INVAL);
> > +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> > +   POWERPC_EXCP_INVAL |
> > +   POWERPC_EXCP_INVAL_INVAL, GETPC());
> >  } else if (unlikely(ppc_dcr_write(env->dcr_env,
> > (uint32_t)dcrn,
> >    (uint32_t)val) != 0)) {
> >  qemu_log_mask(LOG_GUEST_ERROR, "DCR write error %d
> > %03x\n",
> >    (uint32_t)dcrn, (uint32_t)dcrn);
> > -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> > -   POWERPC_EXCP_INVAL |
> > POWERPC_EXCP_PRIV_REG);
> > +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> > +   POWERPC_EXCP_INVAL |
> > +   POWERPC_EXCP_PRIV_REG, GETPC());
> >  }
> >  }
> > diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> > index 84bcb09..f0e0ec6 100644
> > --- a/target-ppc/translate.c
> > +++ b/target-ppc/translate.c
> > @@ -5262,8 +5262,6 @@ static void gen_mfdcr(DisasContext *ctx)
> >  TCGv dcrn;
> >  
> >  CHK_SV;
> > -/* NIP cannot be restored if the memory exception comes from
> > an helper */
> > -gen_update_nip(ctx, ctx->nip - 4);
> >  dcrn = tcg_const_tl(SPR(ctx->opcode));
> >  gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
> >  tcg_temp_free(dcrn);
> > @@ -5279,8 +5277,6 @@ static void gen_mtdcr(DisasContext *ctx)
> >  TCGv dcrn;
> >  
> >  CHK_SV;
> > -/* NIP cannot be restored if the memory exception comes from
> > an helper */
> > -gen_update_nip(ctx, ctx->nip - 4);
> >  dcrn = tcg_const_tl(SPR(ctx->opcode));
> >  gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
> >  tcg_temp_free(dcrn);
> > @@ -5295,8 +5291,6 @@ static void gen_mfdcrx(DisasContext *ctx)
> >  GEN_PRIV;
> >  #else
> >  CHK_SV;
> > -/* NIP cannot be restored if the memory exception comes from
> > an helper */
> > -gen_update_nip(ctx, ctx->nip - 4);
> >  gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
> >  cpu_gpr[rA(ctx->opcode)]);
> > 

Re: [Qemu-devel] [PATCH 16/32] ppc: Rework NIP updates vs. exception generation

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:19 +1000, David Gibson wrote:
> On Wed, Jul 27, 2016 at 08:21:10AM +1000, Benjamin Herrenschmidt
> wrote:
> > 
> > We make env->nip almost always point to the faulting instruction,
> > thus avoiding a mess of "store_current" vs "store_next" in the
> > exception handling. The syscall exception knows to move the PC by
> > 4 and that's really about it.
> > 
> > This actually fixes a number of cases where the translator was
> > setting env->nip to ctx->nip - 4 (ie. the *current* instruction)
> > but the program check exception handler would branch to
> > "store_current" which applies another -4 offset.
> > 
> > Signed-off-by: Benjamin Herrenschmidt  
> I'm having a fair bit of trouble wrapping my head around this.  Still
> comments on a couple of small matters.

Because the original code was a bloody mess ? :-)

Basically, we make sure that we either don't set env->nip (because the
helper will use the TB scan mechanism based on the return address) or
we set it to the address of the instruction that caused the fault
*always*.

Then, in powerpc_excp, we just put that in SRR1 with one exception, the
syscall, where by spec, it has to be on the next instruction.

To fully understand this, you need to know that when the generator of
an instruction is called, ctx->nip has already been moved to the
next instruction (+4).

Cheers,
Ben.

> > 
> > ---
> >  linux-user/main.c|  12 ++--
> >  target-ppc/excp_helper.c | 148 ++-
> > 
> >  target-ppc/translate.c   |  59 +++
> >  3 files changed, 96 insertions(+), 123 deletions(-)
> > 
> > diff --git a/linux-user/main.c b/linux-user/main.c
> > index 462e820..1d149dc 100644
> > --- a/linux-user/main.c
> > +++ b/linux-user/main.c
> > @@ -1814,7 +1814,7 @@ void cpu_loop(CPUPPCState *env)
> >    env->error_code);
> >  break;
> >  }
> > -info._sifields._sigfault._addr = env->nip - 4;
> > +info._sifields._sigfault._addr = env->nip;
> >  queue_signal(env, info.si_signo, );
> >  break;
> >  case POWERPC_EXCP_FPU:  /* Floating-point unavailable
> > exception  */
> > @@ -1822,7 +1822,7 @@ void cpu_loop(CPUPPCState *env)
> >  info.si_signo = TARGET_SIGILL;
> >  info.si_errno = 0;
> >  info.si_code = TARGET_ILL_COPROC;
> > -info._sifields._sigfault._addr = env->nip - 4;
> > +info._sifields._sigfault._addr = env->nip;
> >  queue_signal(env, info.si_signo, );
> >  break;
> >  case POWERPC_EXCP_SYSCALL:  /* System call
> > exception */
> > @@ -1834,7 +1834,7 @@ void cpu_loop(CPUPPCState *env)
> >  info.si_signo = TARGET_SIGILL;
> >  info.si_errno = 0;
> >  info.si_code = TARGET_ILL_COPROC;
> > -info._sifields._sigfault._addr = env->nip - 4;
> > +info._sifields._sigfault._addr = env->nip;
> >  queue_signal(env, info.si_signo, );
> >  break;
> >  case POWERPC_EXCP_DECR: /* Decrementer
> > exception */
> > @@ -1862,7 +1862,7 @@ void cpu_loop(CPUPPCState *env)
> >  info.si_signo = TARGET_SIGILL;
> >  info.si_errno = 0;
> >  info.si_code = TARGET_ILL_COPROC;
> > -info._sifields._sigfault._addr = env->nip - 4;
> > +info._sifields._sigfault._addr = env->nip;
> >  queue_signal(env, info.si_signo, );
> >  break;
> >  case POWERPC_EXCP_EFPDI:/* Embedded floating-point
> > data IRQ  */
> > @@ -1926,7 +1926,7 @@ void cpu_loop(CPUPPCState *env)
> >  info.si_signo = TARGET_SIGILL;
> >  info.si_errno = 0;
> >  info.si_code = TARGET_ILL_COPROC;
> > -info._sifields._sigfault._addr = env->nip - 4;
> > +info._sifields._sigfault._addr = env->nip;
> >  queue_signal(env, info.si_signo, );
> >  break;
> >  case POWERPC_EXCP_PIT:  /* Programmable interval timer
> > IRQ   */
> > @@ -2001,9 +2001,9 @@ void cpu_loop(CPUPPCState *env)
> >   env->gpr[5], env->gpr[6], env-
> > >gpr[7],
> >   env->gpr[8], 0, 0);
> >  if (ret == -TARGET_ERESTARTSYS) {
> > -env->nip -= 4;
> >  break;
> >  }
> > +env->nip += 4;
> >  if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
> >  /* Returning from a successful sigreturn syscall.
> > Avoid corrupting register state.  */
> > diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> > index 563c7bc..570d188 100644
> > --- a/target-ppc/excp_helper.c
> > +++ b/target-ppc/excp_helper.c
> > @@ -198,7 +198,7 @@ static inline void powerpc_excp(PowerPCCPU
> > *cpu, int 

Re: [Qemu-devel] [PATCH 13/32] ppc: Don't update NIP in lswi/lswx/stswi/stswx

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:04 +1000, David Gibson wrote:
> On Wed, Jul 27, 2016 at 08:21:07AM +1000, Benjamin Herrenschmidt
> wrote:
> > Instead, pass GETPC() result to the corresponding helpers. This
> > requires a bit of fiddling to get the PC (hopefully) right in
> > the case where we generate a program check, though the hacks there
> > are temporary, a subsequent patch will clean this all up by always
> > having the nip already set to the right instruction when taking
> > the fault.
> 
> Where are cpu_ldub_data() and cpu_ldub_data_ra() defined?  I assume
> it's via macro somewhere, since I couldn't find it with a grep.

Yeah all that stuff is defined via macros in

include/exec/cpu_ldst.h and cpu_ldst_template.h




Re: [Qemu-devel] [PATCH 12/32] ppc: FP exceptions are always precise

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 12:00 +1000, David Gibson wrote:
> On Wed, Jul 27, 2016 at 08:21:06AM +1000, Benjamin Herrenschmidt
> wrote:
> > 
> > We don't implement imprecise FP exceptions and using store_current
> > which sets SRR1 to the *previous* instruction never makes sense
> > for these. So let's be truthful and make them precise, which is
> > allowed by the architecture.
> 
> I don't see any store_correct in the altered code, so the description
> doesn't quite make sense to me.

The existing program check default to store_current. We want
store_next.

The labels are misnamed, I fix that in a subsequent patch.
store_current means use the "current" ctx->nip which is usually
pointing to the *next* instruction ;-) (though not always).

It's all very messy and fixing that is  what a susequent patch in the
series does.

> > 
> > 
> > Signed-off-by: Benjamin Herrenschmidt 
> > ---
> >  target-ppc/excp_helper.c | 11 ++-
> >  target-ppc/translate.c   |  1 -
> >  2 files changed, 6 insertions(+), 6 deletions(-)
> > 
> > diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> > index f4b115e..91fdf4b 100644
> > --- a/target-ppc/excp_helper.c
> > +++ b/target-ppc/excp_helper.c
> > @@ -274,12 +274,13 @@ static inline void powerpc_excp(PowerPCCPU
> > *cpu, int excp_model, int excp)
> >  env->error_code = 0;
> >  return;
> >  }
> > +
> > +/* FP exceptions always have NIP pointing to the
> > faulting
> > + * instruction, so always use store_next and claim we
> > are
> > + * precise in the MSR.
> > + */
> >  msr |= 0x0010;
> > -if (msr_fe0 == msr_fe1) {
> > -goto store_next;
> > -}
> > -msr |= 0x0001;
> > -break;
> > +goto store_next;
> >  case POWERPC_EXCP_INVAL:
> >  LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n",
> > env->nip);
> >  msr |= 0x0008;
> > diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> > index cb4e313..a05fed7 100644
> > --- a/target-ppc/translate.c
> > +++ b/target-ppc/translate.c
> > @@ -2846,7 +2846,6 @@ static void
> > gen_conditional_store(DisasContext *ctx, TCGv EA,
> >    int reg, int size)
> >  {
> >  TCGv t0 = tcg_temp_new();
> > -uint32_t save_exception = ctx->exception;
> 
> Also, this appears to be an unrelated change.
> 
> > 
> >  tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
> >  tcg_gen_movi_tl(t0, (size << 5) | reg);
> 


Re: [Qemu-devel] [PATCH 10/32] ppc: Make float_check_status() pass the return address

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 11:57 +1000, David Gibson wrote:
> > -void helper_float_check_status(CPUPPCState *env)
> > +static __attribute__((noinline)) void
> do_float_check_status(CPUPPCState *env,
> > +   
> uintptr_t raddr)
> 
> Why do you need to force this to be non-inline?

I don't. It just that gcc inlines too much shit :-)

In fact I had a patch at some point that made a whole pile of stuff in
translate.c non-inline and that reduced the size of it by about 100K

But yeah, I can drop it for now, it's irrelevant to the point of the
patch.

Cheers,
ben.



Re: [Qemu-devel] [PATCH 02/32] ppc: Provide basic raise_exception_* functions

2016-07-26 Thread Benjamin Herrenschmidt
On Wed, 2016-07-27 at 11:50 +1000, David Gibson wrote:
> 
> > +void raise_exception_err(CPUPPCState *env, uint32_t exception,
> > + uint32_t error_code)
> > +{
> > +raise_exception_err_ra(env, exception, error_code, 0);
> > +}
> > +
> > +void raise_exception(CPUPPCState *env, uint32_t exception)
> > +{
> > +raise_exception_err_ra(env, exception, 0, 0);
> > +}
> > +
> > +void raise_exception_ra(CPUPPCState *env, uint32_t exception,
> > +uintptr_t raddr)
> > +{
> > +raise_exception_err_ra(env, exception, 0, 0);
> 
> This should pass raddr as the last argument, shouldn't it?

Yes. The fact that I didn't notice the breakage shows how few things
actually care about those exceptions being precise ;-) I'll respin the
patch. Thanks.

Cheers,
Ben.



[Qemu-devel] [Bug 1581936] Re: Frozen Windows 7 VMs with VGA CVE-2016-3712 fix (2.6.0 and 2.5.1.1)

2016-07-26 Thread tkr
So this is fixed upstream, in Fedora and ARCH. Can we expect a fix for
xenial? This is quite a show stopper.

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1581936

Title:
  Frozen Windows 7 VMs with VGA CVE-2016-3712 fix (2.6.0 and 2.5.1.1)

Status in QEMU:
  Confirmed

Bug description:
  Hi,

  As already posted on the QEMU devel list [1] I stumbled upon a problem
  with QEMU in version 2.5.1.1 and 2.6.0.

  the VM shows Windows loading
  files for the installation, then the "Starting Windows" screen appears
  here it hangs and never continues.

  Changing the "-vga" option to cirrus solves this, the installation can
  proceed and finish. When changing back to std (or also qxl, vmware) the
  installed VM also hangs on the "Starting Windows" screen while qemu
  showing a little but no excessive load.

  This phenomena appears also with QEMU 2.6.0 but not with 2.6.0-rc4, a
  git bisect shows fd3c136b3e1482cd0ec7285d6bc2a3e6a62c38d7 (vga: make
  sure vga register setup for vbe stays intact (CVE-2016-3712)) as the
  culprit for this regression, as its a fix for a DoS its not an option to
  just revert it, I guess.

  The bisect log is:

  git bisect start
  # bad: [bfc766d38e1fae5767d43845c15c79ac8fa6d6af] Update version for v2.6.0 
release
  git bisect bad bfc766d38e1fae5767d43845c15c79ac8fa6d6af
  # good: [975eb6a547f809608ccb08c221552f11af25] Update version for 
v2.6.0-rc4 release
  git bisect good 975eb6a547f809608ccb08c221552f11af25
  # good: [2068192dcccd8a80dddfcc8df6164cf9c26e0fc4] vga: update vga register 
setup on vbe changes
  git bisect good 2068192dcccd8a80dddfcc8df6164cf9c26e0fc4
  # bad: [53db932604dfa7bb9241d132e0173894cf54261c] Merge remote-tracking 
branch 'remotes/kraxel/tags/pull-vga-20160509-1' into staging
  git bisect bad 53db932604dfa7bb9241d132e0173894cf54261c
  # bad: [fd3c136b3e1482cd0ec7285d6bc2a3e6a62c38d7] vga: make sure vga register 
setup for vbe stays intact (CVE-2016-3712).
  git bisect bad fd3c136b3e1482cd0ec7285d6bc2a3e6a62c38d7
  # first bad commit: [fd3c136b3e1482cd0ec7285d6bc2a3e6a62c38d7] vga: make sure 
vga register setup for vbe stays intact (CVE-2016-3712).

  
  I could reproduce that with QEMU 2.5.1 and QEMU 2.6 on a Debian derivate
  (Promox VE) with 4.4 Kernel and also with QEMU 2.6 on an Arch Linux
  System with a 4.5 Kernel, so it should not be host distro depended. Both
  machines have Intel x86_64 processors.
  The problem should be reproducible with said Versions or a build from
  git including the above mentioned commit (fd3c136) by starting a VM with
  an Windows 7 ISO, e.g.:

  Freezing installation (as vga defaults to std I marked it as optional):
  ./x86_64-softmmu/qemu-system-x86_64 -boot d -cdrom win7.iso -m 1024 [-vga 
(std|qxl|vmware)]

  Working installation:
  ./x86_64-softmmu/qemu-system-x86_64 -boot d -cdrom win7.iso -m 1024 -vga 
cirrus

  If someone has already an installed Windows 7 VM this behaviour should be
  also observable when trying to start it with the new versions of QEMU.

  Noteworthy may be that Windows 10 is working, I do not had time to get
  other Windows versions and test them, I'll do that as soon as possible.
  Various Linux system also seems do work fine, at least I did not ran
  into an issue there yet.

  I also tried testing with SeaBIOS and OVMF as firmware, as initially I
  had no idea what broke, both lead to the same result - without the 
  CVE-2016-3712 fix they both work, with not.
  Further, KVM enabled and disabled does not make any difference.

  
  [1] http://lists.nongnu.org/archive/html/qemu-devel/2016-05/msg02416.html

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1581936/+subscriptions



[Qemu-devel] A question about tb_next_offset[2]

2016-07-26 Thread Kartik Ramkrishnan
Hello all,

   I am running an i386 binary in user mode using qemu.

   In the code, I am looking for the next location that the simulated
program counter jumps to when a TranslationBlock completes execution. This
address should be the guest address, not the address on the host.

I found a variable called tb_next_offset[2] in 'struct TranslationBlock' in
exec-all.h ,  which says (offset of original jump target). It sounds like
the jump offset can be added to the target code's last address to obtain
the new PC value.

Am I interpreting tb_next offset's meaning correctly ? I am also confused
about how I should concatenate the two elements in the array in order to
get the jump offset.

Thanks,

Kartik.


[Qemu-devel] Segfault with coalesced mmio and boot CPU removal

2016-07-26 Thread Bharata B Rao
Hi,

Coalesced mmio buffer is part of vCPU 0's kvm_run mmap'ed area
and with the introduction of CPU hotplug, vCPU 0 can be removed on
PowerPC leading to the below seen segfault in QEMU.

0x100a1d34 in kvm_flush_coalesced_mmio_buffer ()
at qemu/kvm-all.c:1828
1828while (ring->first != ring->last) {

#0  0x100a1d34 in kvm_flush_coalesced_mmio_buffer ()
at qemu/kvm-all.c:1828
#1  0x100160e0 in qemu_flush_coalesced_mmio_buffer ()
at qemu/exec.c:1206
#2  0x100a961c in memory_region_transaction_begin ()
at qemu/memory.c:904
#3  0x100add90 in memory_region_set_enabled (mr=0x3fff96420310, 
enabled=false)
at qemu/memory.c:1974
#4  0x104577b0 in pci_default_write_config (d=0x3fff96420010, addr=4, 
val_in=258, 
l=2) at hw/pci/pci.c:1340
#5  0x10465d0c in pci_host_config_write_common (pci_dev=0x3fff96420010, 
addr=4, 
limit=4096, val=258, len=2) at hw/pci/pci_host.c:66
#6  0x10170500 in finish_write_pci_config (spapr=0x10fc6290, 
buid=576460752840294400, addr=4, size=2, val=258, rets=20547656)
at qemu/hw/ppc/spapr_pci.c:199
#7  0x10170620 in rtas_ibm_write_pci_config (cpu=0x3fffac590010, 
spapr=0x10fc6290, 
token=8215, nargs=5, args=20547636, nret=1, rets=20547656)
at qemu/hw/ppc/spapr_pci.c:223
#8  0x1016e540 in spapr_rtas_call (cpu=0x3fffac590010, 
spapr=0x10fc6290, token=8215, 
nargs=5, args=20547636, nret=1, rets=20547656)
at qemu/hw/ppc/spapr_rtas.c:675
#9  0x10167dfc in h_rtas (cpu=0x3fffac590010, spapr=0x10fc6290, 
opcode=61440, 
args=0x3fffac570030) at qemu/hw/ppc/spapr_hcall.c:665
#10 0x101693ec in spapr_hypercall (cpu=0x3fffac590010, opcode=61440, 
args=0x3fffac570030) at qemu/hw/ppc/spapr_hcall.c:1094
#11 0x1026c82c in kvm_arch_handle_exit (cs=0x3fffac590010, 
run=0x3fffac57)
at qemu/target-ppc/kvm.c:1731
#12 0x100a246c in kvm_cpu_exec (cpu=0x3fffac590010)
at qemu/kvm-all.c:2005
#13 0x1007d8d4 in qemu_kvm_cpu_thread_fn (arg=0x3fffac590010) 

This happens because during CPU removal, though we park the kvm_fd
corresponding to the removed vCPU thread, we unmap the kvm_run (and
hence coalesced mmio ring).

What would be the best way to fix this ? Is disassociating coalesced_mmio_ring
from vCPU 0's kvm_run the correct solution ?

Regards,
Bharata.




Re: [Qemu-devel] [RFC PATCH V3 0/3] filter-rewriter: introduce filter-rewriter

2016-07-26 Thread Jason Wang



On 2016年07月27日 10:32, Zhang Chen wrote:

Hi~ all~~

Anyone have some comments for this series?


Will have a look at this.

Btw. I wonder how this is tested, do we need a unit test for this?



We need more comments to improve COLO codes.


Thanks

Zhang Chen


On 07/05/2016 06:29 PM, Zhang Chen wrote:

Filter-rewriter is a part of COLO project.
So this patch set depend on colo-compare.


Interesting, I thought it can co-work with comparing, and the 
communication were done through socket now. So I think technically the 
filter itself could work without COLO?



It will rewrite some of secondary packet to make
secondary guest's connection established successfully.
In this module we will rewrite tcp packet's ack to the secondary
from primary,and rewrite tcp packet's seq to the primary from
secondary.

v3:
   - fix typo
   - add conn->syn_flag
   - add some comments
   - remove conn_list_lock
   - fix offset set bug


I think you can remove RFC in the next version so we can try to merge it 
after one or several other iterations.


Thanks



v2:
   - add more comments about packet flows
   - add some trace-event
   - add seq offset ( = secondary_seq - primary_seq)

v1:
   - initial patch

Zhang Chen (3):
   filter-rewriter: introduce filter-rewriter initialization
   filter-rewriter: track connection and parse packet
   filter-rewriter: rewrite tcp packet to keep secondary connection

  net/Makefile.objs |   1 +
  net/colo-base.c   |   2 +
  net/colo-base.h   |   7 ++
  net/filter-rewriter.c | 262 
++

  qemu-options.hx   |  13 +++
  trace-events  |   5 +
  vl.c  |   3 +-
  7 files changed, 292 insertions(+), 1 deletion(-)
  create mode 100644 net/filter-rewriter.c








Re: [Qemu-devel] [PATCH 26/32] ppc: Speed up dcbz

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:20AM +1000, Benjamin Herrenschmidt wrote:
> Use tlb_vaddr_to_host to do a fast path single translate for
> the whole cache line. Also make the reservation check match
> the entire range.
> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/mem_helper.c | 46 +-
>  target-ppc/translate.c  | 11 ---
>  2 files changed, 29 insertions(+), 28 deletions(-)
> 
> diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
> index 92a594c..6548715 100644
> --- a/target-ppc/mem_helper.c
> +++ b/target-ppc/mem_helper.c
> @@ -141,35 +141,39 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, 
> uint32_t nb,
>  }
>  }
>  
> -static void do_dcbz(CPUPPCState *env, target_ulong addr, int 
> dcache_line_size,
> -uintptr_t raddr)
> +void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode)
>  {
> -int i;
> -
> -addr &= ~(dcache_line_size - 1);
> -for (i = 0; i < dcache_line_size; i += 4) {
> -cpu_stl_data_ra(env, addr + i, 0, raddr);
> -}
> -if (env->reserve_addr == addr) {
> -env->reserve_addr = (target_ulong)-1ULL;
> -}
> -}
> -
> -void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t is_dcbzl)
> -{
> -int dcbz_size = env->dcache_line_size;
> +target_ulong mask, dcbz_size = env->dcache_line_size;
> +uint32_t i;
> +void *haddr;
>  
>  #if defined(TARGET_PPC64)
> -if (!is_dcbzl &&
> -(env->excp_model == POWERPC_EXCP_970) &&
> -((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) {
> +/* Check for dcbz vs dcbzl on 970 */
> +if (env->excp_model == POWERPC_EXCP_970 &&
> +!(opcode & 0x0020) && ((env->spr[SPR_970_HID5] >> 7) & 0x3) == 
> 1) {
>  dcbz_size = 32;
>  }
>  #endif
>  
> -/* XXX add e500mc support */
> +/* Align address */
> +mask = ~(dcbz_size - 1);
> +addr &= mask;
> +
> +/* Check reservation */
> +if ((env->reserve_addr & mask) == (addr & mask))  {
> +env->reserve_addr = (target_ulong)-1ULL;
> +}
>  
> -do_dcbz(env, addr, dcbz_size, GETPC());
> +/* Try fast path translate */
> +haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, env->dmmu_idx);

It worries me slightly that this doesn't take any length to verify.  I
guess it's ok in practice, because memory blocks will always be at
least cache line size aligned.

> +if (haddr) {
> +memset(haddr, 0, dcbz_size);
> +} else {
> +/* Slow path */
> +for (i = 0; i < dcbz_size; i += 8) {
> +cpu_stq_data_ra(env, addr + i, 0, GETPC());
> +}
> +}
>  }
>  
>  void helper_icbi(CPUPPCState *env, target_ulong addr)
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 57a891b..5288e02 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -3851,18 +3851,15 @@ static void gen_dcbtls(DisasContext *ctx)
>  static void gen_dcbz(DisasContext *ctx)
>  {
>  TCGv tcgv_addr;
> -TCGv_i32 tcgv_is_dcbzl;
> -int is_dcbzl = ctx->opcode & 0x0020 ? 1 : 0;
> +TCGv_i32 tcgv_op;
>  
>  gen_set_access_type(ctx, ACCESS_CACHE);
>  tcgv_addr = tcg_temp_new();
> -tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);
> -
> +tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000);
>  gen_addr_reg_index(ctx, tcgv_addr);
> -gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_is_dcbzl);
> -
> +gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_op);
>  tcg_temp_free(tcgv_addr);
> -tcg_temp_free_i32(tcgv_is_dcbzl);
> +tcg_temp_free_i32(tcgv_op);
>  }
>  
>  /* dst / dstt */

-- 
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 13/32] ppc: Don't update NIP in lswi/lswx/stswi/stswx

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:07AM +1000, Benjamin Herrenschmidt wrote:
> Instead, pass GETPC() result to the corresponding helpers. This
> requires a bit of fiddling to get the PC (hopefully) right in
> the case where we generate a program check, though the hacks there
> are temporary, a subsequent patch will clean this all up by always
> having the nip already set to the right instruction when taking
> the fault.

Where are cpu_ldub_data() and cpu_ldub_data_ra() defined?  I assume
it's via macro somewhere, since I couldn't find it with a grep.

> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/excp_helper.c |  8 
>  target-ppc/mem_helper.c  | 26 --
>  target-ppc/translate.c   | 18 --
>  3 files changed, 32 insertions(+), 20 deletions(-)
> 
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index 91fdf4b..563c7bc 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -285,6 +285,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>  LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
>  msr |= 0x0008;
>  env->spr[SPR_BOOKE_ESR] = ESR_PIL;
> +/* Some invalids will have the PC in the right place already */
> +if (env->error_code & POWERPC_EXCP_INVAL_LSWX) {
> +goto store_next;
> +}
>  break;
>  case POWERPC_EXCP_PRIV:
>  msr |= 0x0004;
> @@ -306,6 +310,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>  srr1 = SPR_HSRR1;
>  new_msr |= (target_ulong)MSR_HVB;
>  new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
> +/* Some invalids will have the PC in the right place already */
> +if (env->error_code == (POWERPC_EXCP_INVAL|POWERPC_EXCP_INVAL_LSWX)) 
> {
> +goto store_next;
> +}
>  goto store_current;
>  case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception 
> */
>  goto store_current;
> diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
> index e4ed377..de96c91 100644
> --- a/target-ppc/mem_helper.c
> +++ b/target-ppc/mem_helper.c
> @@ -77,23 +77,30 @@ void helper_stmw(CPUPPCState *env, target_ulong addr, 
> uint32_t reg)
>  }
>  }
>  
> -void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t 
> reg)
> +static void do_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb,
> +   uint32_t reg, uintptr_t raddr)
>  {
>  int sh;
>  
>  for (; nb > 3; nb -= 4) {
> -env->gpr[reg] = cpu_ldl_data(env, addr);
> +env->gpr[reg] = cpu_ldl_data_ra(env, addr, raddr);
>  reg = (reg + 1) % 32;
>  addr = addr_add(env, addr, 4);
>  }
>  if (unlikely(nb > 0)) {
>  env->gpr[reg] = 0;
>  for (sh = 24; nb > 0; nb--, sh -= 8) {
> -env->gpr[reg] |= cpu_ldub_data(env, addr) << sh;
> +env->gpr[reg] |= cpu_ldub_data_ra(env, addr, raddr) << sh;
>  addr = addr_add(env, addr, 1);
>  }
>  }
>  }
> +
> +void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t 
> reg)
> +{
> +do_lsw(env, addr, nb, reg, GETPC());
> +}
> +
>  /* PPC32 specification says we must generate an exception if
>   * rA is in the range of registers to be loaded.
>   * In an other hand, IBM says this is valid, but rA won't be loaded.
> @@ -106,12 +113,11 @@ void helper_lswx(CPUPPCState *env, target_ulong addr, 
> uint32_t reg,
>  int num_used_regs = (xer_bc + 3) / 4;
>  if (unlikely((ra != 0 && lsw_reg_in_range(reg, num_used_regs, ra)) ||
>   lsw_reg_in_range(reg, num_used_regs, rb))) {
> -env->nip += 4; /* Compensate the "nip - 4" from gen_lswx() */
> -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -   POWERPC_EXCP_INVAL |
> -   POWERPC_EXCP_INVAL_LSWX);
> +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +   POWERPC_EXCP_INVAL |
> +   POWERPC_EXCP_INVAL_LSWX, GETPC());
>  } else {
> -helper_lsw(env, addr, xer_bc, reg);
> +do_lsw(env, addr, xer_bc, reg, GETPC());
>  }
>  }
>  }
> @@ -122,13 +128,13 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, 
> uint32_t nb,
>  int sh;
>  
>  for (; nb > 3; nb -= 4) {
> -cpu_stl_data(env, addr, env->gpr[reg]);
> +cpu_stl_data_ra(env, addr, env->gpr[reg], GETPC());
>  reg = (reg + 1) % 32;
>  addr = addr_add(env, addr, 4);
>  }
>  if (unlikely(nb > 0)) {
>  for (sh = 24; nb > 0; nb--, sh -= 8) {
> -cpu_stb_data(env, addr, (env->gpr[reg] >> sh) & 0xFF);
> +

Re: [Qemu-devel] [PATCH 25/32] ppc: Handle unconditional (always/never) traps at translation time

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:19AM +1000, Benjamin Herrenschmidt wrote:
> We don't need to call a helper for trap always and trap never
> which are used by Linux under some circumstances.
> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/translate.c | 48 ++--
>  1 file changed, 42 insertions(+), 6 deletions(-)
> 
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 9af3f5f..57a891b 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -3360,10 +3360,29 @@ static void gen_sc(DisasContext *ctx)
>  
>  /***Trap   
> ***/
>  
> +/* Check for unconditional traps (always or never) */
> +static bool check_unconditional_trap(DisasContext *ctx)
> +{
> +/* Trap never */
> +if (TO(ctx->opcode) == 0) {
> +return true;
> +}
> +/* Trap always */
> +if (TO(ctx->opcode) == 31) {
> +gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);

Should you be returning true here?

Without it, IIUC, the functions below will generate the unconditional
trap, then generate more code to actually test the condition and trap
again.

> +}
> +return false;
> +}
> +
>  /* tw */
>  static void gen_tw(DisasContext *ctx)
>  {
> -TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
> +TCGv_i32 t0;
> +
> +if (check_unconditional_trap(ctx)) {
> +return;
> +}
> +t0 = tcg_const_i32(TO(ctx->opcode));
>  gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], 
> cpu_gpr[rB(ctx->opcode)],
>t0);
>  tcg_temp_free_i32(t0);
> @@ -3372,8 +3391,14 @@ static void gen_tw(DisasContext *ctx)
>  /* twi */
>  static void gen_twi(DisasContext *ctx)
>  {
> -TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
> -TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
> +TCGv t0;
> +TCGv_i32 t1;
> +
> +if (check_unconditional_trap(ctx)) {
> +return;
> +}
> +t0 = tcg_const_tl(SIMM(ctx->opcode));
> +t1 = tcg_const_i32(TO(ctx->opcode));
>  gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
>  tcg_temp_free(t0);
>  tcg_temp_free_i32(t1);
> @@ -3383,7 +3408,12 @@ static void gen_twi(DisasContext *ctx)
>  /* td */
>  static void gen_td(DisasContext *ctx)
>  {
> -TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
> +TCGv_i32 t0;
> +
> +if (check_unconditional_trap(ctx)) {
> +return;
> +}
> +t0 = tcg_const_i32(TO(ctx->opcode));
>  gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], 
> cpu_gpr[rB(ctx->opcode)],
>t0);
>  tcg_temp_free_i32(t0);
> @@ -3392,8 +3422,14 @@ static void gen_td(DisasContext *ctx)
>  /* tdi */
>  static void gen_tdi(DisasContext *ctx)
>  {
> -TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
> -TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
> +TCGv t0;
> +TCGv_i32 t1;
> +
> +if (check_unconditional_trap(ctx)) {
> +return;
> +}
> +t0 = tcg_const_tl(SIMM(ctx->opcode));
> +t1 = tcg_const_i32(TO(ctx->opcode));
>  gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
>  tcg_temp_free(t0);
>  tcg_temp_free_i32(t1);

-- 
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 10/32] ppc: Make float_check_status() pass the return address

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:04AM +1000, Benjamin Herrenschmidt wrote:
> Instead of relying on NIP having been updated already.
> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/fpu_helper.c | 63 
> +
>  1 file changed, 38 insertions(+), 25 deletions(-)
> 
> diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
> index 8d881fc..7bab3ff 100644
> --- a/target-ppc/fpu_helper.c
> +++ b/target-ppc/fpu_helper.c
> @@ -209,7 +209,7 @@ static inline uint64_t float_invalid_op_excp(CPUPPCState 
> *env, int op,
>  return ret;
>  }
>  
> -static inline void float_zero_divide_excp(CPUPPCState *env)
> +static inline void float_zero_divide_excp(CPUPPCState *env, uintptr_t raddr)
>  {
>  env->fpscr |= 1 << FPSCR_ZX;
>  env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
> @@ -219,8 +219,9 @@ static inline void float_zero_divide_excp(CPUPPCState 
> *env)
>  /* Update the floating-point enabled exception summary */
>  env->fpscr |= 1 << FPSCR_FEX;
>  if (msr_fe0 != 0 || msr_fe1 != 0) {
> -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -   POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
> +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +   POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX,
> +   raddr);
>  }
>  }
>  }
> @@ -493,13 +494,14 @@ void store_fpscr(CPUPPCState *env, uint64_t arg, 
> uint32_t mask)
>  helper_store_fpscr(env, arg, mask);
>  }
>  
> -void helper_float_check_status(CPUPPCState *env)
> +static __attribute__((noinline)) void do_float_check_status(CPUPPCState *env,
> +uintptr_t raddr)

Why do you need to force this to be non-inline?

>  {
>  CPUState *cs = CPU(ppc_env_get_cpu(env));
>  int status = get_float_exception_flags(>fp_status);
>  
>  if (status & float_flag_divbyzero) {
> -float_zero_divide_excp(env);
> +float_zero_divide_excp(env, raddr);
>  } else if (status & float_flag_overflow) {
>  float_overflow_excp(env);
>  } else if (status & float_flag_underflow) {
> @@ -512,12 +514,23 @@ void helper_float_check_status(CPUPPCState *env)
>  (env->error_code & POWERPC_EXCP_FP)) {
>  /* Differred floating-point exception after target FPR update */
>  if (msr_fe0 != 0 || msr_fe1 != 0) {
> -helper_raise_exception_err(env, cs->exception_index,
> -   env->error_code);
> +raise_exception_err_ra(env, cs->exception_index,
> +   env->error_code, raddr);
>  }
>  }
>  }
>  
> +static inline void float_check_status(CPUPPCState *env)
> +{
> +/* GETPC() works here because this is inline */
> +do_float_check_status(env, GETPC());
> +}
> +
> +void helper_float_check_status(CPUPPCState *env)
> +{
> +do_float_check_status(env, GETPC());
> +}
> +
>  void helper_reset_fpstatus(CPUPPCState *env)
>  {
>  set_float_exception_flags(0, >fp_status);
> @@ -642,7 +655,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)  
>  \
> float_flag_invalid) {   \
>  float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);  \
>  }  \
> -helper_float_check_status(env);\
> +float_check_status(env);   \
>  }  \
>  return farg.ll;\
>   }
> @@ -667,7 +680,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)  
>  \
>  } else {   \
>  farg.d = cvtr(arg, >fp_status);   \
>  }  \
> -helper_float_check_status(env);\
> +float_check_status(env);   \
>  return farg.ll;\
>  }
>  
> @@ -700,7 +713,7 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t 
> arg,
>  env->fp_status.float_exception_flags &= ~float_flag_inexact;
>  }
>  }
> -helper_float_check_status(env);
> +float_check_status(env);
>  return farg.ll;
>  }
>  
> @@ -1856,7 +1869,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)   
>  \
>  }
> \
>  }
> \
>  putVSR(xT(opcode), , env);
> \
> -helper_float_check_status(env); 

Re: [Qemu-devel] [PATCH 16/32] ppc: Rework NIP updates vs. exception generation

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:10AM +1000, Benjamin Herrenschmidt wrote:
> We make env->nip almost always point to the faulting instruction,
> thus avoiding a mess of "store_current" vs "store_next" in the
> exception handling. The syscall exception knows to move the PC by
> 4 and that's really about it.
> 
> This actually fixes a number of cases where the translator was
> setting env->nip to ctx->nip - 4 (ie. the *current* instruction)
> but the program check exception handler would branch to
> "store_current" which applies another -4 offset.
> 
> Signed-off-by: Benjamin Herrenschmidt 

I'm having a fair bit of trouble wrapping my head around this.  Still
comments on a couple of small matters.

> ---
>  linux-user/main.c|  12 ++--
>  target-ppc/excp_helper.c | 148 
> ++-
>  target-ppc/translate.c   |  59 +++
>  3 files changed, 96 insertions(+), 123 deletions(-)
> 
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 462e820..1d149dc 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -1814,7 +1814,7 @@ void cpu_loop(CPUPPCState *env)
>env->error_code);
>  break;
>  }
> -info._sifields._sigfault._addr = env->nip - 4;
> +info._sifields._sigfault._addr = env->nip;
>  queue_signal(env, info.si_signo, );
>  break;
>  case POWERPC_EXCP_FPU:  /* Floating-point unavailable exception  
> */
> @@ -1822,7 +1822,7 @@ void cpu_loop(CPUPPCState *env)
>  info.si_signo = TARGET_SIGILL;
>  info.si_errno = 0;
>  info.si_code = TARGET_ILL_COPROC;
> -info._sifields._sigfault._addr = env->nip - 4;
> +info._sifields._sigfault._addr = env->nip;
>  queue_signal(env, info.si_signo, );
>  break;
>  case POWERPC_EXCP_SYSCALL:  /* System call exception 
> */
> @@ -1834,7 +1834,7 @@ void cpu_loop(CPUPPCState *env)
>  info.si_signo = TARGET_SIGILL;
>  info.si_errno = 0;
>  info.si_code = TARGET_ILL_COPROC;
> -info._sifields._sigfault._addr = env->nip - 4;
> +info._sifields._sigfault._addr = env->nip;
>  queue_signal(env, info.si_signo, );
>  break;
>  case POWERPC_EXCP_DECR: /* Decrementer exception 
> */
> @@ -1862,7 +1862,7 @@ void cpu_loop(CPUPPCState *env)
>  info.si_signo = TARGET_SIGILL;
>  info.si_errno = 0;
>  info.si_code = TARGET_ILL_COPROC;
> -info._sifields._sigfault._addr = env->nip - 4;
> +info._sifields._sigfault._addr = env->nip;
>  queue_signal(env, info.si_signo, );
>  break;
>  case POWERPC_EXCP_EFPDI:/* Embedded floating-point data IRQ  
> */
> @@ -1926,7 +1926,7 @@ void cpu_loop(CPUPPCState *env)
>  info.si_signo = TARGET_SIGILL;
>  info.si_errno = 0;
>  info.si_code = TARGET_ILL_COPROC;
> -info._sifields._sigfault._addr = env->nip - 4;
> +info._sifields._sigfault._addr = env->nip;
>  queue_signal(env, info.si_signo, );
>  break;
>  case POWERPC_EXCP_PIT:  /* Programmable interval timer IRQ   
> */
> @@ -2001,9 +2001,9 @@ void cpu_loop(CPUPPCState *env)
>   env->gpr[5], env->gpr[6], env->gpr[7],
>   env->gpr[8], 0, 0);
>  if (ret == -TARGET_ERESTARTSYS) {
> -env->nip -= 4;
>  break;
>  }
> +env->nip += 4;
>  if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
>  /* Returning from a successful sigreturn syscall.
> Avoid corrupting register state.  */
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index 563c7bc..570d188 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -198,7 +198,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>  default:
>  goto excp_invalid;
>  }
> -goto store_next;
> +break;
>  case POWERPC_EXCP_MCHECK:/* Machine check exception  
> */
>  if (msr_me == 0) {
>  /* Machine check exception is not enabled.
> @@ -209,7 +209,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>  if (qemu_log_separate()) {
>  qemu_log("Machine check while not allowed. "
>  "Entering checkstop state\n");
> -}
> + }

Looks like an accidental whitespace change.

>  cs->halted = 1;
>  cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
>  }
> @@ -235,16 +235,16 @@ static inline void powerpc_excp(PowerPCCPU *cpu, 

Re: [Qemu-devel] [PATCH 32/32] ppc: Speed up load/store multiple

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:26AM +1000, Benjamin Herrenschmidt wrote:
> Use a single translate when not crossing a page boundary and avoid
> going through layers of helpers. MacOS uses those instructions
> a lot, so does OpenBIOS.
> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/mem_helper.c | 69 
> +
>  1 file changed, 69 insertions(+)
> 
> diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
> index da3f973..511079b 100644
> --- a/target-ppc/mem_helper.c
> +++ b/target-ppc/mem_helper.c
> @@ -53,8 +53,48 @@ static inline target_ulong addr_add(CPUPPCState *env, 
> target_ulong addr,
>  }
>  }
>  
> +/* 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)
> +{
> +#ifndef CONFIG_USER_ONLY
> +if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) {
> +return -addr & ~TARGET_PAGE_MASK;
> +}
> +#endif
> +return len;
> +}
> +
>  void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
>  {
> +uint32_t *src;
> +uint64_t len, adjlen;
> +
> +if ((addr & 3)) {
> +goto fallback;
> +}
> +len = (32 - reg) << 2;
> +while (len) {
> +src = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, env->dmmu_idx);
> +if (!src) {
> +goto fallback;
> +}
> +adjlen = adj_len_to_page(len, addr);
> +len -= adjlen;
> +#if defined(HOST_WORDS_BIGENDIAN)
> +memcpy(>gpr[reg], src, adjlen);
> +reg += (adjlen >> 2);
> +addr = addr_add(env, addr, adjlen);
> +#else
> +while(adjlen) {
> +env->gpr[reg++] = bswap32(*(src++));
> +adjlen -= 4;
> +addr = addr_add(env, addr, 4);
> +}
> +#endif

Would it improve this any further to do the memcpy() unconditionally,
then byteswap the GPRs in-place for the LE host case?

> +}
> +return;
> +
> + fallback:
>  for (; reg < 32; reg++) {
>  if (needs_byteswap(env)) {
>  env->gpr[reg] = bswap32(cpu_ldl_data_ra(env, addr, GETPC()));
> @@ -67,6 +107,35 @@ void helper_lmw(CPUPPCState *env, target_ulong addr, 
> uint32_t reg)
>  
>  void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
>  {
> +uint32_t *dst;
> +uint64_t len, adjlen;
> +
> +if ((addr & 3)) {
> +goto fallback;
> +}
> +len = (32 - reg) << 2;
> +while (len) {
> +dst = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, env->dmmu_idx);
> +if (!dst) {
> +goto fallback;
> +}
> +adjlen = adj_len_to_page(len, addr);
> +len -= adjlen;
> +#if defined(HOST_WORDS_BIGENDIAN)
> +memcpy(dst, >gpr[reg], adjlen);
> +reg += (adjlen >> 2);
> +addr = addr_add(env, addr, adjlen);
> +#else
> +while(adjlen) {
> +*(dst++) = bswap32(env->gpr[reg++]);
> +adjlen -= 4;
> +addr = addr_add(env, addr, 4);
> +}
> +#endif
> +}
> +return;
> +
> + fallback:
>  for (; reg < 32; reg++) {
>  if (needs_byteswap(env)) {
>  cpu_stl_data_ra(env, addr, bswap32((uint32_t)env->gpr[reg]),

-- 
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 02/32] ppc: Provide basic raise_exception_* functions

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:20:56AM +1000, Benjamin Herrenschmidt wrote:
> Instead of using the same helpers called from translate.c, let's have
> a bunch of functions that take the various argument combinations,
> especially the retaddr which will be needed in subsequent patches,
> and leave the helpers to be just that, helpers for translate.c
> 
> We don't yet convert all users, we'll go through them in subsequent
> patches.
> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/cpu.h |  8 
>  target-ppc/excp_helper.c | 51 
> 
>  2 files changed, 42 insertions(+), 17 deletions(-)
> 
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index 5fce1ff..2ee7a5e 100644
> --- a/target-ppc/cpu.h
> +++ b/target-ppc/cpu.h
> @@ -2295,6 +2295,14 @@ static inline void cpu_get_tb_cpu_state(CPUPPCState 
> *env, target_ulong *pc,
>  *flags = env->hflags;
>  }
>  
> +void QEMU_NORETURN raise_exception(CPUPPCState *env, uint32_t exception);
> +void QEMU_NORETURN raise_exception_ra(CPUPPCState *env, uint32_t exception,
> +  uintptr_t raddr);
> +void QEMU_NORETURN raise_exception_err(CPUPPCState *env, uint32_t exception,
> +   uint32_t error_code);
> +void QEMU_NORETURN raise_exception_err_ra(CPUPPCState *env, uint32_t 
> exception,
> +  uint32_t error_code, uintptr_t 
> raddr);
> +
>  #if !defined(CONFIG_USER_ONLY)
>  static inline int booke206_tlbm_id(CPUPPCState *env, ppcmas_tlb_t *tlbm)
>  {
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index d6e1678..f4b115e 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -898,34 +898,53 @@ static void cpu_dump_rfi(target_ulong RA, target_ulong 
> msr)
>  
> /*/
>  /* Exceptions processing helpers */
>  
> -void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
> -uint32_t error_code)
> +void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
> +uint32_t error_code, uintptr_t raddr)
>  {
>  CPUState *cs = CPU(ppc_env_get_cpu(env));
>  
> -#if 0
> -printf("Raise exception %3x code : %d\n", exception, error_code);
> -#endif
>  cs->exception_index = exception;
>  env->error_code = error_code;
> -cpu_loop_exit(cs);
> +cpu_loop_exit_restore(cs, raddr);
> +}
> +
> +void raise_exception_err(CPUPPCState *env, uint32_t exception,
> + uint32_t error_code)
> +{
> +raise_exception_err_ra(env, exception, error_code, 0);
> +}
> +
> +void raise_exception(CPUPPCState *env, uint32_t exception)
> +{
> +raise_exception_err_ra(env, exception, 0, 0);
> +}
> +
> +void raise_exception_ra(CPUPPCState *env, uint32_t exception,
> +uintptr_t raddr)
> +{
> +raise_exception_err_ra(env, exception, 0, 0);

This should pass raddr as the last argument, shouldn't it?

> +}
> +
> +void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
> +uint32_t error_code)
> +{
> +raise_exception_err_ra(env, exception, error_code, 0);
>  }
>  
>  void helper_raise_exception(CPUPPCState *env, uint32_t exception)
>  {
> -helper_raise_exception_err(env, exception, 0);
> +raise_exception_err_ra(env, exception, 0, 0);
>  }
>  
>  #if !defined(CONFIG_USER_ONLY)
>  void helper_store_msr(CPUPPCState *env, target_ulong val)
>  {
> -CPUState *cs;
> +uint32_t excp = hreg_store_msr(env, val, 0);
>  
> -val = hreg_store_msr(env, val, 0);
> -if (val != 0) {
> -cs = CPU(ppc_env_get_cpu(env));
> +if (excp != 0) {
> +CPUState *cs = CPU(ppc_env_get_cpu(env));
>  cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
> -helper_raise_exception(env, val);
> +raise_exception(env, excp);
>  }
>  }
>  
> @@ -951,7 +970,7 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t 
> insn)
>   * but this doesn't seem to be a problem.
>   */
>  env->msr |= (1ull << MSR_EE);
> -helper_raise_exception(env, EXCP_HLT);
> +raise_exception(env, EXCP_HLT);
>  }
>  #endif /* defined(TARGET_PPC64) */
>  
> @@ -1041,8 +1060,7 @@ void helper_tw(CPUPPCState *env, target_ulong arg1, 
> target_ulong arg2,
>((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
>((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
>((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01) {
> -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -   POWERPC_EXCP_TRAP);
> +raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
>  }
>  }
>  
> @@ -1055,8 +1073,7 @@ void helper_td(CPUPPCState *env, target_ulong arg1, 
> target_ulong 

Re: [Qemu-devel] [PATCH 24/32] ppc: Make alignment exceptions suck less

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:18AM +1000, Benjamin Herrenschmidt wrote:
> The current alignment exception generation tries to load the opcode
> to put in DSISR from a context where a cpu_ldl_code() is really not
> a good idea. It might fault and longjmp out and that's not something
> we want happening here.
> 
> Instead, pass the releavant opcode bits via the error_code.
> 
> There are a couple of cases of alignment interrupts that won't set
> anything, the ones coming from access to direct store segments, but
> that doesn't happen in practice, nobody used direct store segments
> and they are gone from newer chips.

Do I understand correctly that this isn't actually new?  This was
already wrong for direct store segments, you've just noted it?

> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/excp_helper.c | 9 +
>  target-ppc/translate.c   | 2 +-
>  2 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index c31bbad..9a26578 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -260,11 +260,12 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>  }
>  break;
>  case POWERPC_EXCP_ALIGN: /* Alignment exception  
> */
> -/* XXX: this is false */
>  /* Get rS/rD and rA from faulting opcode */
> -/* Broken for LE mode */
> -env->spr[SPR_DSISR] |= (cpu_ldl_code(env, env->nip)
> -& 0x03FF) >> 16;
> +/* Note: the opcode fields will not be set properly for a direct
> + * store load/store, but nobody cares as nobody actually uses
> + * direct store segments.
> + */
> +env->spr[SPR_DSISR] |= (env->error_code & 0x03FF) >> 16;
>  break;
>  case POWERPC_EXCP_PROGRAM:   /* Program exception
> */
>  switch (env->error_code & ~0xF) {
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index ddfec33..9af3f5f 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -2202,7 +2202,7 @@ static inline void gen_check_align(DisasContext *ctx, 
> TCGv EA, int mask)
>  tcg_gen_andi_tl(t0, EA, mask);
>  tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
>  t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
> -t2 = tcg_const_i32(0);
> +t2 = tcg_const_i32(ctx->opcode & 0x03FF);
>  gen_update_nip(ctx, ctx->nip - 4);
>  gen_helper_raise_exception_err(cpu_env, t1, t2);
>  tcg_temp_free_i32(t1);

-- 
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 21/32] ppc: Don't update NIP on conditional trap instructions

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:15AM +1000, Benjamin Herrenschmidt wrote:
> This is no longer necessary as the helpers will properly retrieve
> the return address when needed.

Is this right?  Don't the tw etc. instructions continue on rather than
retrying if an exception occurs?

> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/excp_helper.c | 6 --
>  target-ppc/translate.c   | 8 
>  2 files changed, 4 insertions(+), 10 deletions(-)
> 
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index 570d188..c31bbad 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -1031,7 +1031,8 @@ void helper_tw(CPUPPCState *env, target_ulong arg1, 
> target_ulong arg2,
>((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
>((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
>((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01) {
> -raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
> +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +   POWERPC_EXCP_TRAP, GETPC());
>  }
>  }
>  
> @@ -1044,7 +1045,8 @@ void helper_td(CPUPPCState *env, target_ulong arg1, 
> target_ulong arg2,
>((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
>((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
>((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01) {
> -raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
> +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +   POWERPC_EXCP_TRAP, GETPC());
>  }
>  }
>  #endif
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 8f5afba..7163b19 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -3365,8 +3365,6 @@ static void gen_sc(DisasContext *ctx)
>  static void gen_tw(DisasContext *ctx)
>  {
>  TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
> -/* Update the nip since this might generate a trap exception */
> -gen_update_nip(ctx, ctx->nip - 4);
>  gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], 
> cpu_gpr[rB(ctx->opcode)],
>t0);
>  tcg_temp_free_i32(t0);
> @@ -3377,8 +3375,6 @@ static void gen_twi(DisasContext *ctx)
>  {
>  TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
>  TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
> -/* Update the nip since this might generate a trap exception */
> -gen_update_nip(ctx, ctx->nip - 4);
>  gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
>  tcg_temp_free(t0);
>  tcg_temp_free_i32(t1);
> @@ -3389,8 +3385,6 @@ static void gen_twi(DisasContext *ctx)
>  static void gen_td(DisasContext *ctx)
>  {
>  TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
> -/* Update the nip since this might generate a trap exception */
> -gen_update_nip(ctx, ctx->nip - 4);
>  gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], 
> cpu_gpr[rB(ctx->opcode)],
>t0);
>  tcg_temp_free_i32(t0);
> @@ -3401,8 +3395,6 @@ static void gen_tdi(DisasContext *ctx)
>  {
>  TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
>  TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
> -/* Update the nip since this might generate a trap exception */
> -gen_update_nip(ctx, ctx->nip - 4);
>  gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
>  tcg_temp_free(t0);
>  tcg_temp_free_i32(t1);

-- 
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 12/32] ppc: FP exceptions are always precise

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:06AM +1000, Benjamin Herrenschmidt wrote:
> We don't implement imprecise FP exceptions and using store_current
> which sets SRR1 to the *previous* instruction never makes sense
> for these. So let's be truthful and make them precise, which is
> allowed by the architecture.

I don't see any store_correct in the altered code, so the description
doesn't quite make sense to me.

> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/excp_helper.c | 11 ++-
>  target-ppc/translate.c   |  1 -
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index f4b115e..91fdf4b 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -274,12 +274,13 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>  env->error_code = 0;
>  return;
>  }
> +
> +/* FP exceptions always have NIP pointing to the faulting
> + * instruction, so always use store_next and claim we are
> + * precise in the MSR.
> + */
>  msr |= 0x0010;
> -if (msr_fe0 == msr_fe1) {
> -goto store_next;
> -}
> -msr |= 0x0001;
> -break;
> +goto store_next;
>  case POWERPC_EXCP_INVAL:
>  LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
>  msr |= 0x0008;
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index cb4e313..a05fed7 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -2846,7 +2846,6 @@ static void gen_conditional_store(DisasContext *ctx, 
> TCGv EA,
>int reg, int size)
>  {
>  TCGv t0 = tcg_temp_new();
> -uint32_t save_exception = ctx->exception;

Also, this appears to be an unrelated change.

>  tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
>  tcg_gen_movi_tl(t0, (size << 5) | reg);

-- 
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 01/32] ppc: Fix fault PC reporting for lve*/stve* VMX instructions

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:20:55AM +1000, Benjamin Herrenschmidt wrote:
> We forgot to do gen_update_nip() for these like we do with other
> helpers. Fix this, but in a more efficient way by passing the RA
> to the accessors instead so the overhead is only taken on faults.
> 
> Signed-off-by: Benjamin Herrenschmidt 

As a bugfix, I've applied this to ppc-for-2.7.

> ---
>  target-ppc/mem_helper.c | 21 +++--
>  1 file changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
> index e4de86b..e4ed377 100644
> --- a/target-ppc/mem_helper.c
> +++ b/target-ppc/mem_helper.c
> @@ -232,16 +232,16 @@ target_ulong helper_lscbx(CPUPPCState *env, 
> target_ulong addr, uint32_t reg,
>  \
>  if (needs_byteswap(env)) {  \
>  r->element[LO_IDX ? index : (adjust - index)] = \
> -swap(access(env, addr));\
> +swap(access(env, addr, GETPC()));   \
>  } else {\
>  r->element[LO_IDX ? index : (adjust - index)] = \
> -access(env, addr);  \
> +access(env, addr, GETPC()); \
>  }   \
>  }
>  #define I(x) (x)
> -LVE(lvebx, cpu_ldub_data, I, u8)
> -LVE(lvehx, cpu_lduw_data, bswap16, u16)
> -LVE(lvewx, cpu_ldl_data, bswap32, u32)
> +LVE(lvebx, cpu_ldub_data_ra, I, u8)
> +LVE(lvehx, cpu_lduw_data_ra, bswap16, u16)
> +LVE(lvewx, cpu_ldl_data_ra, bswap32, u32)
>  #undef I
>  #undef LVE
>  
> @@ -259,16 +259,17 @@ LVE(lvewx, cpu_ldl_data, bswap32, u32)
>  \
>  if (needs_byteswap(env)) {  \
>  access(env, addr, swap(r->element[LO_IDX ? index :  \
> -  (adjust - index)]));  \
> +  (adjust - index)]),   \
> +GETPC());   \
>  } else {\
>  access(env, addr, r->element[LO_IDX ? index :   \
> - (adjust - index)]);\
> + (adjust - index)], GETPC());   \
>  }   \
>  }
>  #define I(x) (x)
> -STVE(stvebx, cpu_stb_data, I, u8)
> -STVE(stvehx, cpu_stw_data, bswap16, u16)
> -STVE(stvewx, cpu_stl_data, bswap32, u32)
> +STVE(stvebx, cpu_stb_data_ra, I, u8)
> +STVE(stvehx, cpu_stw_data_ra, bswap16, u16)
> +STVE(stvewx, cpu_stl_data_ra, bswap32, u32)
>  #undef I
>  #undef LVE
>  

-- 
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 18/32] ppc: Don't update NIP in DCR access routines

2016-07-26 Thread David Gibson
On Wed, Jul 27, 2016 at 08:21:12AM +1000, Benjamin Herrenschmidt wrote:
> This is no longer necessary as the helpers will properly retrieve
> the return address when needed

Well, the helpers are only fixed in this patch IIUC.

> 
> Signed-off-by: Benjamin Herrenschmidt 
> ---
>  target-ppc/timebase_helper.c | 23 +--
>  target-ppc/translate.c   | 12 
>  2 files changed, 13 insertions(+), 22 deletions(-)
> 
> diff --git a/target-ppc/timebase_helper.c b/target-ppc/timebase_helper.c
> index a07faa4..73363e0 100644
> --- a/target-ppc/timebase_helper.c
> +++ b/target-ppc/timebase_helper.c
> @@ -19,6 +19,7 @@
>  #include "qemu/osdep.h"
>  #include "cpu.h"
>  #include "exec/helper-proto.h"
> +#include "exec/exec-all.h"
>  #include "qemu/log.h"
>  
>  
> /*/
> @@ -143,15 +144,16 @@ target_ulong helper_load_dcr(CPUPPCState *env, 
> target_ulong dcrn)
>  
>  if (unlikely(env->dcr_env == NULL)) {
>  qemu_log_mask(LOG_GUEST_ERROR, "No DCR environment\n");
> -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -   POWERPC_EXCP_INVAL |
> -   POWERPC_EXCP_INVAL_INVAL);
> +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +   POWERPC_EXCP_INVAL |
> +   POWERPC_EXCP_INVAL_INVAL, GETPC());
>  } else if (unlikely(ppc_dcr_read(env->dcr_env,
>   (uint32_t)dcrn, ) != 0)) {
>  qemu_log_mask(LOG_GUEST_ERROR, "DCR read error %d %03x\n",
>(uint32_t)dcrn, (uint32_t)dcrn);
> -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -   POWERPC_EXCP_INVAL | 
> POWERPC_EXCP_PRIV_REG);
> +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +   POWERPC_EXCP_INVAL |
> +   POWERPC_EXCP_PRIV_REG, GETPC());
>  }
>  return val;
>  }
> @@ -160,14 +162,15 @@ void helper_store_dcr(CPUPPCState *env, target_ulong 
> dcrn, target_ulong val)
>  {
>  if (unlikely(env->dcr_env == NULL)) {
>  qemu_log_mask(LOG_GUEST_ERROR, "No DCR environment\n");
> -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -   POWERPC_EXCP_INVAL |
> -   POWERPC_EXCP_INVAL_INVAL);
> +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +   POWERPC_EXCP_INVAL |
> +   POWERPC_EXCP_INVAL_INVAL, GETPC());
>  } else if (unlikely(ppc_dcr_write(env->dcr_env, (uint32_t)dcrn,
>(uint32_t)val) != 0)) {
>  qemu_log_mask(LOG_GUEST_ERROR, "DCR write error %d %03x\n",
>(uint32_t)dcrn, (uint32_t)dcrn);
> -helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
> -   POWERPC_EXCP_INVAL | 
> POWERPC_EXCP_PRIV_REG);
> +raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
> +   POWERPC_EXCP_INVAL |
> +   POWERPC_EXCP_PRIV_REG, GETPC());
>  }
>  }
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 84bcb09..f0e0ec6 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -5262,8 +5262,6 @@ static void gen_mfdcr(DisasContext *ctx)
>  TCGv dcrn;
>  
>  CHK_SV;
> -/* NIP cannot be restored if the memory exception comes from an helper */
> -gen_update_nip(ctx, ctx->nip - 4);
>  dcrn = tcg_const_tl(SPR(ctx->opcode));
>  gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
>  tcg_temp_free(dcrn);
> @@ -5279,8 +5277,6 @@ static void gen_mtdcr(DisasContext *ctx)
>  TCGv dcrn;
>  
>  CHK_SV;
> -/* NIP cannot be restored if the memory exception comes from an helper */
> -gen_update_nip(ctx, ctx->nip - 4);
>  dcrn = tcg_const_tl(SPR(ctx->opcode));
>  gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
>  tcg_temp_free(dcrn);
> @@ -5295,8 +5291,6 @@ static void gen_mfdcrx(DisasContext *ctx)
>  GEN_PRIV;
>  #else
>  CHK_SV;
> -/* NIP cannot be restored if the memory exception comes from an helper */
> -gen_update_nip(ctx, ctx->nip - 4);
>  gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
>  cpu_gpr[rA(ctx->opcode)]);
>  /* Note: Rc update flag set leads to undefined state of Rc0 */
> @@ -5311,8 +5305,6 @@ static void gen_mtdcrx(DisasContext *ctx)
>  GEN_PRIV;
>  #else
>  CHK_SV;
> -/* NIP cannot be restored if the memory exception comes from an helper */
> -gen_update_nip(ctx, ctx->nip - 4);
>  gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
>   cpu_gpr[rS(ctx->opcode)]);
>  /* Note: Rc update flag 

Re: [Qemu-devel] [RFC PATCH V3 0/3] filter-rewriter: introduce filter-rewriter

2016-07-26 Thread Zhang Chen

Hi~ all~~

Anyone have some comments for this series?

We need more comments to improve COLO codes.


Thanks

Zhang Chen


On 07/05/2016 06:29 PM, Zhang Chen wrote:

Filter-rewriter is a part of COLO project.
So this patch set depend on colo-compare.
It will rewrite some of secondary packet to make
secondary guest's connection established successfully.
In this module we will rewrite tcp packet's ack to the secondary
from primary,and rewrite tcp packet's seq to the primary from
secondary.

v3:
   - fix typo
   - add conn->syn_flag
   - add some comments
   - remove conn_list_lock
   - fix offset set bug

v2:
   - add more comments about packet flows
   - add some trace-event
   - add seq offset ( = secondary_seq - primary_seq)

v1:
   - initial patch

Zhang Chen (3):
   filter-rewriter: introduce filter-rewriter initialization
   filter-rewriter: track connection and parse packet
   filter-rewriter: rewrite tcp packet to keep secondary connection

  net/Makefile.objs |   1 +
  net/colo-base.c   |   2 +
  net/colo-base.h   |   7 ++
  net/filter-rewriter.c | 262 ++
  qemu-options.hx   |  13 +++
  trace-events  |   5 +
  vl.c  |   3 +-
  7 files changed, 292 insertions(+), 1 deletion(-)
  create mode 100644 net/filter-rewriter.c



--
Thanks
zhangchen






Re: [Qemu-devel] [RFC PATCH 3/3] hw/arm/virt: add nvdimm emulation support

2016-07-26 Thread kwangwoo....@sk.com
Hi Peter,

Thanks for your guidance!

> -Original Message-
> From: Peter Maydell [mailto:peter.mayd...@linaro.org]
> Sent: Tuesday, July 26, 2016 5:23 PM
> To: 이광우(LEE KWANGWOO) MS SW
> Cc: Xiao Guangrong; Michael S. Tsirkin; Igor Mammedov; Paolo Bonzini; Richard 
> Henderson; Eduardo
> Habkost; Shannon Zhao; Shannon Zhao; QEMU Developers; qemu-arm; 정우석(CHUNG WOO 
> SUK) MS SW; 김현철(KIM
> HYUNCHUL) MS SW
> Subject: Re: [RFC PATCH 3/3] hw/arm/virt: add nvdimm emulation support
> 
> On 26 July 2016 at 08:03, kwangwoo@sk.com  wrote:
> > Hi Peter,
> >
> > Please, check the comments below. Thanks a lot!
> >
> >> -Original Message-
> >> From: Peter Maydell [mailto:peter.mayd...@linaro.org]
> >> This seems to be missing code to write the device tree
> >> information about whatever this device is?
> >
> > Is it OK to just add a memory region which cannot be used without ACPI?
> > This is unclear to me. If you suggest that it is better way, I'll revise
> > this patch to add a device tree node. Please, help me to understand.
> 
> They don't necessarily both have to be added in the exact same patch
> if it's less confusing to split it, but the series as a whole
> should support both DT and ACPI (and your kernel patches also
> ought to have both DT and ACPI bindings I think).

Although NVDIMM is dependent on ACPI NFIT table currently, I'll keep
this comment in mind and revise it step by step.

> thanks
> -- PMM

Best Regards,
Kwangwoo Lee


Re: [Qemu-devel] [PATCH v23 12/12] MAINTAINERS: add maintainer for replication

2016-07-26 Thread Changlong Xie

On 07/27/2016 12:25 AM, Max Reitz wrote:

+replication

While some acronyms are written fully in lower case in this file, this
is not an acronym, so I'd capitalize it as "Replication", or maybe call
it "Block replication" instead.



I just know the rule and "Repliation" is good for me.


>+M: Wen Congyang
>+M: Changlong Xie
>+S: Supported
>+F: replication*
>+F: block/replication.c
>+F: test/test-replication.c

docs/block-replication.txt should probably be mentioned as well.



Surely


Max


>+
>  Build and test automation
>  -
>  M: Alex Bennée
>








Re: [Qemu-devel] [PATCH v23 11/12] support replication driver in blockdev-add

2016-07-26 Thread Changlong Xie

On 07/27/2016 12:22 AM, Max Reitz wrote:

On 26.07.2016 10:15, Changlong Xie wrote:

From: Wen Congyang 

Signed-off-by: Wen Congyang 
Signed-off-by: Changlong Xie 
Signed-off-by: Wang WeiWei 
Signed-off-by: zhanghailiang 
Signed-off-by: Gonglei 
Reviewed-by: Eric Blake 
---
  qapi/block-core.json | 22 --
  1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 7258a87..48aa112 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -248,6 +248,7 @@
  #   2.3: 'host_floppy' deprecated
  #   2.5: 'host_floppy' dropped
  #   2.6: 'luks' added
+#   2.8: 'replication' added
  #
  # @backing_file: #optional the name of the backing file (for copy-on-write)
  #
@@ -1696,8 +1697,8 @@
'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
  'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
  'host_device', 'http', 'https', 'luks', 'null-aio', 'null-co',
-'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp',
-'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
+'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 
'replication',
+'tftp', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }

  ##
  # @BlockdevOptionsFile
@@ -2160,6 +2161,22 @@
  { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }

  ##
+# @BlockdevOptionsReplication
+#
+# Driver specific block device options for replication
+#
+# @mode: the replication mode
+#
+# @top-id: the id to protect replication model chain


It's hard for me to understand this sentence without reading the code
and thus knowing what this ID is used for. I'd use the following instead:

@top-id: In secondary mode, node name or device ID of the root node who
owns the replication node chain. Ignored in primary mode.


Pretty description



Also, since this parameter is only necessary in secondary mode and
completely ignored in primary mode, I would probably make it an optional
parameter.


Surely.



Max


+#
+# Since: 2.8
+##
+{ 'struct': 'BlockdevOptionsReplication',
+  'base': 'BlockdevOptionsGenericFormat',
+  'data': { 'mode': 'ReplicationMode',
+'top-id': 'str' } }
+
+##
  # @BlockdevOptions
  #
  # Options for creating a block device.  Many options are available for all
@@ -2224,6 +2241,7 @@
'quorum': 'BlockdevOptionsQuorum',
'raw':'BlockdevOptionsGenericFormat',
  # TODO rbd: Wait for structured options
+  'replication':'BlockdevOptionsReplication',
  # TODO sheepdog: Wait for structured options
  # TODO ssh: Should take InetSocketAddress for 'host'?
'tftp':   'BlockdevOptionsFile',










Re: [Qemu-devel] [PATCH v23 09/12] Implement new driver for block replication

2016-07-26 Thread Changlong Xie

On 07/27/2016 12:17 AM, Max Reitz wrote:

On 26.07.2016 10:15, Changlong Xie wrote:

From: Wen Congyang 

Signed-off-by: Wen Congyang 
Signed-off-by: Changlong Xie 
Signed-off-by: Wang WeiWei 
Signed-off-by: zhanghailiang 
Signed-off-by: Gonglei 
---
  block/Makefile.objs |   1 +
  block/replication.c | 658 
  2 files changed, 659 insertions(+)
  create mode 100644 block/replication.c


[...]


diff --git a/block/replication.c b/block/replication.c
new file mode 100644
index 000..ec35348
--- /dev/null
+++ b/block/replication.c
@@ -0,0 +1,658 @@


[...]


+static void replication_start(ReplicationState *rs, ReplicationMode mode,
+  Error **errp)
+{


[...]


+/* start backup job now */
+error_setg(>blocker,
+   "Block device is in use by internal backup job");
+
+top_bs = bdrv_lookup_bs(s->top_id, s->top_id, errp);


I think you should pass NULL instead of errp...


+if (!top_bs || !check_top_bs(top_bs, bs)) {
+error_setg(errp, "No top_bs or it is invalid");


...or if you don't, then you should not call this function if top_bs is
NULL. Otherwise you'll probably get a failed assertion in error_setv()
because *errp is not NULL.


Thanks for pointing it out. if top_is is NULL, *errp will be set in 
bdrv_lookup_bs(). Then we'll get failed assertion in error_setv(). Will

fix it.




+reopen_backing_file(s, false, NULL);
+aio_context_release(aio_context);
+return;
+}
+bdrv_op_block_all(top_bs, s->blocker);
+bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker);


Shouldn't you make sure that top_bs is a root node? The first patch in


Indeed, it should be a root node


Kevin's "block: Accept node-name in all node level QMP commands" series
introduces the bdrv_is_root_node() function for that purpose.

Maybe that check should be put into check_top_bs().



I think we just need check top_bs is a root node or not one time before 
stepping in check_top_bs().


if (!top_bs || !bdrv_is_root_node(top_bs) ||
!check_top_bs(top_bs, bs)) {


Max


+
+backup_start("replication-backup", s->secondary_disk->bs,
+ s->hidden_disk->bs, 0, MIRROR_SYNC_MODE_NONE, NULL,
+ BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
+ backup_job_completed, s, NULL, _err);
+if (local_err) {
+error_propagate(errp, local_err);
+backup_job_cleanup(s);
+aio_context_release(aio_context);
+return;
+}
+break;








[Qemu-devel] [PATCH v2 repost 6/7] mm: add the related functions to get free page info

2016-07-26 Thread Liang Li
Save the free page info into a page bitmap, will be used in virtio
balloon device driver.

Signed-off-by: Liang Li 
Cc: Andrew Morton 
Cc: Vlastimil Babka 
Cc: Mel Gorman 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Cornelia Huck 
Cc: Amit Shah 
---
 mm/page_alloc.c | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 7da61ad..3ad8b10 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4523,6 +4523,52 @@ unsigned long get_max_pfn(void)
 }
 EXPORT_SYMBOL(get_max_pfn);
 
+static void mark_free_pages_bitmap(struct zone *zone, unsigned long start_pfn,
+   unsigned long end_pfn, unsigned long *bitmap, unsigned long len)
+{
+   unsigned long pfn, flags, page_num;
+   unsigned int order, t;
+   struct list_head *curr;
+
+   if (zone_is_empty(zone))
+   return;
+   end_pfn = min(start_pfn + len, end_pfn);
+   spin_lock_irqsave(>lock, flags);
+
+   for_each_migratetype_order(order, t) {
+   list_for_each(curr, >free_area[order].free_list[t]) {
+   pfn = page_to_pfn(list_entry(curr, struct page, lru));
+   if (pfn >= start_pfn && pfn <= end_pfn) {
+   page_num = 1UL << order;
+   if (pfn + page_num > end_pfn)
+   page_num = end_pfn - pfn;
+   bitmap_set(bitmap, pfn - start_pfn, page_num);
+   }
+   }
+   }
+
+   spin_unlock_irqrestore(>lock, flags);
+}
+
+int get_free_pages(unsigned long start_pfn, unsigned long end_pfn,
+   unsigned long *bitmap, unsigned long len)
+{
+   struct zone *zone;
+   int ret = 0;
+
+   if (bitmap == NULL || start_pfn > end_pfn || start_pfn >= max_pfn)
+   return 0;
+   if (end_pfn < max_pfn)
+   ret = 1;
+   if (end_pfn >= max_pfn)
+   ret = 0;
+
+   for_each_populated_zone(zone)
+   mark_free_pages_bitmap(zone, start_pfn, end_pfn, bitmap, len);
+   return ret;
+}
+EXPORT_SYMBOL(get_free_pages);
+
 static void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref)
 {
zoneref->zone = zone;
-- 
1.9.1




Re: [Qemu-devel] [virtio-dev] Re: [PATCH v2 kernel 0/7] Extend virtio-balloon for fast (de)inflating & fast live migration

2016-07-26 Thread Li, Liang Z
> So I'm fine with this patchset, but I noticed it was not yet reviewed by MM
> people. And that is not surprising since you did not copy memory
> management mailing list on it.
> 
> I added linux...@kvack.org Cc on this mail but this might not be enough.
> 
> Please repost (e.g. [PATCH v2 repost]) copying the relevant mailing list so we
> can get some reviews.
> 

I will repost. Thanks!

Liang



[Qemu-devel] [PATCH v2 repost 5/7] virtio-balloon: define feature bit and head for misc virt queue

2016-07-26 Thread Liang Li
Define a new feature bit which supports a new virtual queue. This
new virtual qeuque is for information exchange between hypervisor
and guest. The VMM hypervisor can make use of this virtual queue
to request the guest do some operations, e.g. drop page cache,
synchronize file system, etc. And the VMM hypervisor can get some
of guest's runtime information through this virtual queue, e.g. the
guest's free page information, which can be used for live migration
optimization.

Signed-off-by: Liang Li 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Cornelia Huck 
Cc: Amit Shah 
---
 include/uapi/linux/virtio_balloon.h | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/include/uapi/linux/virtio_balloon.h 
b/include/uapi/linux/virtio_balloon.h
index d3b182a..be4880f 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -35,6 +35,7 @@
 #define VIRTIO_BALLOON_F_STATS_VQ  1 /* Memory Stats virtqueue */
 #define VIRTIO_BALLOON_F_DEFLATE_ON_OOM2 /* Deflate balloon on OOM */
 #define VIRTIO_BALLOON_F_PAGE_BITMAP   3 /* Send page info with bitmap */
+#define VIRTIO_BALLOON_F_MISC_VQ   4 /* Misc info virtqueue */
 
 /* Size of a PFN in the balloon interface. */
 #define VIRTIO_BALLOON_PFN_SHIFT 12
@@ -101,4 +102,25 @@ struct balloon_bmap_hdr {
__virtio64 bmap_len;
 };
 
+enum balloon_req_id {
+   /* Get free pages information */
+   BALLOON_GET_FREE_PAGES,
+};
+
+enum balloon_flag {
+   /* Have more data for a request */
+   BALLOON_FLAG_CONT,
+   /* No more data for a request */
+   BALLOON_FLAG_DONE,
+};
+
+struct balloon_req_hdr {
+   /* Used to distinguish different request */
+   __virtio16 cmd;
+   /* Reserved */
+   __virtio16 reserved[3];
+   /* Request parameter */
+   __virtio64 param;
+};
+
 #endif /* _LINUX_VIRTIO_BALLOON_H */
-- 
1.9.1




[Qemu-devel] [PATCH v2 repost 1/7] virtio-balloon: rework deflate to add page to a list

2016-07-26 Thread Liang Li
will allow faster notifications using a bitmap down the road.
balloon_pfn_to_page() can be removed because it's useless.

Signed-off-by: Liang Li 
Signed-off-by: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Cornelia Huck 
Cc: Amit Shah 
---
 drivers/virtio/virtio_balloon.c | 22 --
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 476c0e3..8d649a2 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -98,12 +98,6 @@ static u32 page_to_balloon_pfn(struct page *page)
return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE;
 }
 
-static struct page *balloon_pfn_to_page(u32 pfn)
-{
-   BUG_ON(pfn % VIRTIO_BALLOON_PAGES_PER_PAGE);
-   return pfn_to_page(pfn / VIRTIO_BALLOON_PAGES_PER_PAGE);
-}
-
 static void balloon_ack(struct virtqueue *vq)
 {
struct virtio_balloon *vb = vq->vdev->priv;
@@ -176,18 +170,16 @@ static unsigned fill_balloon(struct virtio_balloon *vb, 
size_t num)
return num_allocated_pages;
 }
 
-static void release_pages_balloon(struct virtio_balloon *vb)
+static void release_pages_balloon(struct virtio_balloon *vb,
+struct list_head *pages)
 {
-   unsigned int i;
-   struct page *page;
+   struct page *page, *next;
 
-   /* Find pfns pointing at start of each page, get pages and free them. */
-   for (i = 0; i < vb->num_pfns; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
-   page = balloon_pfn_to_page(virtio32_to_cpu(vb->vdev,
-  vb->pfns[i]));
+   list_for_each_entry_safe(page, next, pages, lru) {
if (!virtio_has_feature(vb->vdev,
VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
adjust_managed_page_count(page, 1);
+   list_del(>lru);
put_page(page); /* balloon reference */
}
 }
@@ -197,6 +189,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, 
size_t num)
unsigned num_freed_pages;
struct page *page;
struct balloon_dev_info *vb_dev_info = >vb_dev_info;
+   LIST_HEAD(pages);
 
/* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns));
@@ -208,6 +201,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, 
size_t num)
if (!page)
break;
set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
+   list_add(>lru, );
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
}
 
@@ -219,7 +213,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, 
size_t num)
 */
if (vb->num_pfns != 0)
tell_host(vb, vb->deflate_vq);
-   release_pages_balloon(vb);
+   release_pages_balloon(vb, );
mutex_unlock(>balloon_lock);
return num_freed_pages;
 }
-- 
1.9.1




[Qemu-devel] [PATCH v2 repost 7/7] virtio-balloon: tell host vm's free page info

2016-07-26 Thread Liang Li
Support the request for vm's free page information, response with
a page bitmap. QEMU can make use of this free page bitmap to speed
up live migration process by skipping process the free pages.

Signed-off-by: Liang Li 
Cc: Michael S. Tsirkin 
Cc: Andrew Morton 
Cc: Vlastimil Babka 
Cc: Mel Gorman 
Cc: Paolo Bonzini 
Cc: Cornelia Huck 
Cc: Amit Shah 
---
 drivers/virtio/virtio_balloon.c | 104 +---
 1 file changed, 98 insertions(+), 6 deletions(-)

diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 2d18ff6..5ca4ad3 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -62,10 +62,13 @@ module_param(oom_pages, int, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(oom_pages, "pages to free on OOM");
 
 extern unsigned long get_max_pfn(void);
+extern int get_free_pages(unsigned long start_pfn, unsigned long end_pfn,
+   unsigned long *bitmap, unsigned long len);
+
 
 struct virtio_balloon {
struct virtio_device *vdev;
-   struct virtqueue *inflate_vq, *deflate_vq, *stats_vq;
+   struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *misc_vq;
 
/* The balloon servicing is delegated to a freezable workqueue. */
struct work_struct update_balloon_stats_work;
@@ -89,6 +92,8 @@ struct virtio_balloon {
unsigned long pfn_limit;
/* Used to record the processed pfn range */
unsigned long min_pfn, max_pfn, start_pfn, end_pfn;
+   /* Request header */
+   struct balloon_req_hdr req_hdr;
/*
 * The pages we've told the Host we're not using are enqueued
 * at vb_dev_info->pages list.
@@ -373,6 +378,49 @@ static void update_balloon_stats(struct virtio_balloon *vb)
pages_to_bytes(available));
 }
 
+static void update_free_pages_stats(struct virtio_balloon *vb,
+   unsigned long req_id)
+{
+   struct scatterlist sg_in, sg_out;
+   unsigned long pfn = 0, bmap_len, max_pfn;
+   struct virtqueue *vq = vb->misc_vq;
+   struct balloon_bmap_hdr *hdr = vb->bmap_hdr;
+   int ret = 1;
+
+   max_pfn = get_max_pfn();
+   mutex_lock(>balloon_lock);
+   while (pfn < max_pfn) {
+   memset(vb->page_bitmap, 0, vb->bmap_len);
+   ret = get_free_pages(pfn, pfn + vb->pfn_limit,
+   vb->page_bitmap, vb->bmap_len * BITS_PER_BYTE);
+   hdr->cmd = cpu_to_virtio16(vb->vdev, BALLOON_GET_FREE_PAGES);
+   hdr->page_shift = cpu_to_virtio16(vb->vdev, PAGE_SHIFT);
+   hdr->req_id = cpu_to_virtio64(vb->vdev, req_id);
+   hdr->start_pfn = cpu_to_virtio64(vb->vdev, pfn);
+   bmap_len = vb->pfn_limit / BITS_PER_BYTE;
+   if (!ret) {
+   hdr->flag = cpu_to_virtio16(vb->vdev,
+   BALLOON_FLAG_DONE);
+   if (pfn + vb->pfn_limit > max_pfn)
+   bmap_len = (max_pfn - pfn) / BITS_PER_BYTE;
+   } else
+   hdr->flag = cpu_to_virtio16(vb->vdev,
+   BALLOON_FLAG_CONT);
+   hdr->bmap_len = cpu_to_virtio64(vb->vdev, bmap_len);
+   sg_init_one(_out, hdr,
+sizeof(struct balloon_bmap_hdr) + bmap_len);
+
+   virtqueue_add_outbuf(vq, _out, 1, vb, GFP_KERNEL);
+   virtqueue_kick(vq);
+   pfn += vb->pfn_limit;
+   }
+
+   sg_init_one(_in, >req_hdr, sizeof(vb->req_hdr));
+   virtqueue_add_inbuf(vq, _in, 1, >req_hdr, GFP_KERNEL);
+   virtqueue_kick(vq);
+   mutex_unlock(>balloon_lock);
+}
+
 /*
  * While most virtqueues communicate guest-initiated requests to the 
hypervisor,
  * the stats queue operates in reverse.  The driver initializes the virtqueue
@@ -511,18 +559,49 @@ static void update_balloon_size_func(struct work_struct 
*work)
queue_work(system_freezable_wq, work);
 }
 
+static void misc_handle_rq(struct virtio_balloon *vb)
+{
+   struct balloon_req_hdr *ptr_hdr;
+   unsigned int len;
+
+   ptr_hdr = virtqueue_get_buf(vb->misc_vq, );
+   if (!ptr_hdr || len != sizeof(vb->req_hdr))
+   return;
+
+   switch (ptr_hdr->cmd) {
+   case BALLOON_GET_FREE_PAGES:
+   update_free_pages_stats(vb, ptr_hdr->param);
+   break;
+   default:
+   break;
+   }
+}
+
+static void misc_request(struct virtqueue *vq)
+{
+   struct virtio_balloon *vb = vq->vdev->priv;
+
+   misc_handle_rq(vb);
+}
+
 static int init_vqs(struct virtio_balloon *vb)
 {
-   struct virtqueue *vqs[3];
-   vq_callback_t *callbacks[] = { 

[Qemu-devel] [PATCH v2 repost 3/7] mm: add a function to get the max pfn

2016-07-26 Thread Liang Li
Expose the function to get the max pfn, so it can be used in the
virtio-balloon device driver.

Signed-off-by: Liang Li 
Cc: Andrew Morton 
Cc: Vlastimil Babka 
Cc: Mel Gorman 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Cornelia Huck 
Cc: Amit Shah 
---
 mm/page_alloc.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 8b3e134..7da61ad 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4517,6 +4517,12 @@ void show_free_areas(unsigned int filter)
show_swap_cache_info();
 }
 
+unsigned long get_max_pfn(void)
+{
+   return max_pfn;
+}
+EXPORT_SYMBOL(get_max_pfn);
+
 static void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref)
 {
zoneref->zone = zone;
-- 
1.9.1




[Qemu-devel] [PATCH v2 repost 0/7] Extend virtio-balloon for fast (de)inflating & fast live migration

2016-07-26 Thread Liang Li
This patchset is for kernel and contains two parts of change to the
virtio-balloon. 

One is the change for speeding up the inflating & deflating process,
the main idea of this optimization is to use bitmap to send the page
information to host instead of the PFNs, to reduce the overhead of
virtio data transmission, address translation and madvise(). This can
help to improve the performance by about 85%.

Another change is for speeding up live migration. By skipping process
guest's free pages in the first round of data copy, to reduce needless
data processing, this can help to save quite a lot of CPU cycles and
network bandwidth. We put guest's free page information in bitmap and
send it to host with the virt queue of virtio-balloon. For an idle 8GB
guest, this can help to shorten the total live migration time from 2Sec
to about 500ms in the 10Gbps network environment.  


Changes from v1 to v2:
* Abandon the patch for dropping page cache.
* Put some structures to uapi head file.
* Use a new way to determine the page bitmap size.
* Use a unified way to send the free page information with the bitmap 
* Address the issues referred in MST's comments

Liang Li (7):
  virtio-balloon: rework deflate to add page to a list
  virtio-balloon: define new feature bit and page bitmap head
  mm: add a function to get the max pfn
  virtio-balloon: speed up inflate/deflate process
  virtio-balloon: define feature bit and head for misc virt queue
  mm: add the related functions to get free page info
  virtio-balloon: tell host vm's free page info

 drivers/virtio/virtio_balloon.c | 306 +++-
 include/uapi/linux/virtio_balloon.h |  41 +
 mm/page_alloc.c |  52 ++
 3 files changed, 359 insertions(+), 40 deletions(-)

-- 
1.9.1




[Qemu-devel] [PATCH v2 repost 4/7] virtio-balloon: speed up inflate/deflate process

2016-07-26 Thread Liang Li
The implementation of the current virtio-balloon is not very
efficient, the time spends on different stages of inflating
the balloon to 7GB of a 8GB idle guest:

a. allocating pages (6.5%)
b. sending PFNs to host (68.3%)
c. address translation (6.1%)
d. madvise (19%)

It takes about 4126ms for the inflating process to complete.
Debugging shows that the bottle neck are the stage b and stage d.

If using a bitmap to send the page info instead of the PFNs, we
can reduce the overhead in stage b quite a lot. Furthermore, we
can do the address translation and call madvise() with a bulk of
RAM pages, instead of the current page per page way, the overhead
of stage c and stage d can also be reduced a lot.

This patch is the kernel side implementation which is intended to
speed up the inflating & deflating process by adding a new feature
to the virtio-balloon device. With this new feature, inflating the
balloon to 7GB of a 8GB idle guest only takes 590ms, the
performance improvement is about 85%.

TODO: optimize stage a by allocating/freeing a chunk of pages
instead of a single page at a time.

Signed-off-by: Liang Li 
Suggested-by: Michael S. Tsirkin 
Cc: Michael S. Tsirkin 
Cc: Andrew Morton 
Cc: Vlastimil Babka 
Cc: Mel Gorman 
Cc: Paolo Bonzini 
Cc: Cornelia Huck 
Cc: Amit Shah 
---
 drivers/virtio/virtio_balloon.c | 184 +++-
 1 file changed, 162 insertions(+), 22 deletions(-)

diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 8d649a2..2d18ff6 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -41,10 +41,28 @@
 #define OOM_VBALLOON_DEFAULT_PAGES 256
 #define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80
 
+/*
+ * VIRTIO_BALLOON_PFNS_LIMIT is used to limit the size of page bitmap
+ * to prevent a very large page bitmap, there are two reasons for this:
+ * 1) to save memory.
+ * 2) allocate a large bitmap may fail.
+ *
+ * The actual limit of pfn is determined by:
+ * pfn_limit = min(max_pfn, VIRTIO_BALLOON_PFNS_LIMIT);
+ *
+ * If system has more pages than VIRTIO_BALLOON_PFNS_LIMIT, we will scan
+ * the page list and send the PFNs with several times. To reduce the
+ * overhead of scanning the page list. VIRTIO_BALLOON_PFNS_LIMIT should
+ * be set with a value which can cover most cases.
+ */
+#define VIRTIO_BALLOON_PFNS_LIMIT ((32 * (1ULL << 30)) >> PAGE_SHIFT) /* 32GB 
*/
+
 static int oom_pages = OOM_VBALLOON_DEFAULT_PAGES;
 module_param(oom_pages, int, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(oom_pages, "pages to free on OOM");
 
+extern unsigned long get_max_pfn(void);
+
 struct virtio_balloon {
struct virtio_device *vdev;
struct virtqueue *inflate_vq, *deflate_vq, *stats_vq;
@@ -62,6 +80,15 @@ struct virtio_balloon {
 
/* Number of balloon pages we've told the Host we're not using. */
unsigned int num_pages;
+   /* Pointer of the bitmap header. */
+   void *bmap_hdr;
+   /* Bitmap and length used to tell the host the pages */
+   unsigned long *page_bitmap;
+   unsigned long bmap_len;
+   /* Pfn limit */
+   unsigned long pfn_limit;
+   /* Used to record the processed pfn range */
+   unsigned long min_pfn, max_pfn, start_pfn, end_pfn;
/*
 * The pages we've told the Host we're not using are enqueued
 * at vb_dev_info->pages list.
@@ -105,12 +132,45 @@ static void balloon_ack(struct virtqueue *vq)
wake_up(>acked);
 }
 
+static inline void init_pfn_range(struct virtio_balloon *vb)
+{
+   vb->min_pfn = ULONG_MAX;
+   vb->max_pfn = 0;
+}
+
+static inline void update_pfn_range(struct virtio_balloon *vb,
+struct page *page)
+{
+   unsigned long balloon_pfn = page_to_balloon_pfn(page);
+
+   if (balloon_pfn < vb->min_pfn)
+   vb->min_pfn = balloon_pfn;
+   if (balloon_pfn > vb->max_pfn)
+   vb->max_pfn = balloon_pfn;
+}
+
 static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
 {
struct scatterlist sg;
unsigned int len;
 
-   sg_init_one(, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
+   if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_PAGE_BITMAP)) {
+   struct balloon_bmap_hdr *hdr = vb->bmap_hdr;
+   unsigned long bmap_len;
+
+   /* cmd and req_id are not used here, set them to 0 */
+   hdr->cmd = cpu_to_virtio16(vb->vdev, 0);
+   hdr->page_shift = cpu_to_virtio16(vb->vdev, PAGE_SHIFT);
+   hdr->reserved = cpu_to_virtio16(vb->vdev, 0);
+   hdr->req_id = cpu_to_virtio64(vb->vdev, 0);
+   hdr->start_pfn = cpu_to_virtio64(vb->vdev, vb->start_pfn);
+   bmap_len = min(vb->bmap_len,
+   

[Qemu-devel] [PATCH v2 repost 2/7] virtio-balloon: define new feature bit and page bitmap head

2016-07-26 Thread Liang Li
Add a new feature which supports sending the page information with
a bitmap. The current implementation uses PFNs array, which is not
very efficient. Using bitmap can improve the performance of
inflating/deflating significantly

The page bitmap header will used to tell the host some information
about the page bitmap. e.g. the page size, page bitmap length and
start pfn.

Signed-off-by: Liang Li 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Cornelia Huck 
Cc: Amit Shah 
---
 include/uapi/linux/virtio_balloon.h | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/include/uapi/linux/virtio_balloon.h 
b/include/uapi/linux/virtio_balloon.h
index 343d7dd..d3b182a 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -34,6 +34,7 @@
 #define VIRTIO_BALLOON_F_MUST_TELL_HOST0 /* Tell before reclaiming 
pages */
 #define VIRTIO_BALLOON_F_STATS_VQ  1 /* Memory Stats virtqueue */
 #define VIRTIO_BALLOON_F_DEFLATE_ON_OOM2 /* Deflate balloon on OOM */
+#define VIRTIO_BALLOON_F_PAGE_BITMAP   3 /* Send page info with bitmap */
 
 /* Size of a PFN in the balloon interface. */
 #define VIRTIO_BALLOON_PFN_SHIFT 12
@@ -82,4 +83,22 @@ struct virtio_balloon_stat {
__virtio64 val;
 } __attribute__((packed));
 
+/* Page bitmap header structure */
+struct balloon_bmap_hdr {
+   /* Used to distinguish different request */
+   __virtio16 cmd;
+   /* Shift width of page in the bitmap */
+   __virtio16 page_shift;
+   /* flag used to identify different status */
+   __virtio16 flag;
+   /* Reserved */
+   __virtio16 reserved;
+   /* ID of the request */
+   __virtio64 req_id;
+   /* The pfn of 0 bit in the bitmap */
+   __virtio64 start_pfn;
+   /* The length of the bitmap, in bytes */
+   __virtio64 bmap_len;
+};
+
 #endif /* _LINUX_VIRTIO_BALLOON_H */
-- 
1.9.1




Re: [Qemu-devel] [PATCH v2] test: port postcopy test to ppc64

2016-07-26 Thread David Gibson
On Thu, Jul 21, 2016 at 06:47:56PM +0200, Laurent Vivier wrote:
> As userfaultfd syscall is available on powerpc, migration
> postcopy can be used.
> 
> This patch adds the support needed to test this on powerpc,
> instead of using a bootsector to run code to modify memory,
> we use a FORTH script in "boot-command" property.
> 
> As spapr machine doesn't support "-prom-env" argument
> (the nvram is initialized by SLOF and not by QEMU),
> "boot-command" is provided to SLOF via a file mapped nvram
> (with "-drive file=...,if=pflash")
> 
> Signed-off-by: Laurent Vivier 

So, the warning message is a bit unfortunate, but the following
discussion seems to show that removing it isn't trivial.  If we can do
so in a follow up patch, that would be nice, but for the time being,
I've merged this patch to ppc-for-2.7 anyway.

> ---
> v2: move FORTH script directly in sprintf()
> use openbios_firmware_abi.h
> remove useless "default" case
> 
>  tests/Makefile.include |   1 +
>  tests/postcopy-test.c  | 116 
> +
>  2 files changed, 98 insertions(+), 19 deletions(-)
> 
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index e7e50d6..e2d1885 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -268,6 +268,7 @@ check-qtest-sparc-y += tests/prom-env-test$(EXESUF)
>  #check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
>  check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
>  check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
> +check-qtest-ppc64-y += tests/postcopy-test$(EXESUF)
>  
>  check-qtest-generic-y += tests/qom-test$(EXESUF)
>  
> diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c
> index 16465ab..229e9e9 100644
> --- a/tests/postcopy-test.c
> +++ b/tests/postcopy-test.c
> @@ -18,6 +18,9 @@
>  #include "qemu/sockets.h"
>  #include "sysemu/char.h"
>  #include "sysemu/sysemu.h"
> +#include "hw/nvram/openbios_firmware_abi.h"
> +
> +#define MIN_NVRAM_SIZE 8192 /* from spapr_nvram.c */
>  
>  const unsigned start_address = 1024 * 1024;
>  const unsigned end_address = 100 * 1024 * 1024;
> @@ -122,6 +125,44 @@ unsigned char bootsect[] = {
>0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
>  };
>  
> +static void init_bootfile_x86(const char *bootpath)
> +{
> +FILE *bootfile = fopen(bootpath, "wb");
> +
> +g_assert_cmpint(fwrite(bootsect, 512, 1, bootfile), ==, 1);
> +fclose(bootfile);
> +}
> +
> +static void init_bootfile_ppc(const char *bootpath)
> +{
> +FILE *bootfile;
> +char buf[MIN_NVRAM_SIZE];
> +struct OpenBIOS_nvpart_v1 *header = (struct OpenBIOS_nvpart_v1 *)buf;
> +
> +memset(buf, 0, MIN_NVRAM_SIZE);
> +
> +/* Create a "common" partition in nvram to store boot-command property */
> +
> +header->signature = OPENBIOS_PART_SYSTEM;
> +memcpy(header->name, "common", 6);
> +OpenBIOS_finish_partition(header, MIN_NVRAM_SIZE);
> +
> +/* FW_MAX_SIZE is 4MB, but slof.bin is only 900KB,
> + * so let's modify memory between 1MB and 100MB
> + * to do like PC bootsector
> + */
> +
> +sprintf(buf + 16,
> +"boot-command=hex .\" _\" begin %x %x do i c@ 1 + i c! 1000 
> +loop "
> +".\" B\" 0 until", end_address, start_address);
> +
> +/* Write partition to the NVRAM file */
> +
> +bootfile = fopen(bootpath, "wb");
> +g_assert_cmpint(fwrite(buf, MIN_NVRAM_SIZE, 1, bootfile), ==, 1);
> +fclose(bootfile);
> +}
> +
>  /*
>   * Wait for some output in the serial output file,
>   * we get an 'A' followed by an endless string of 'B's
> @@ -131,10 +172,29 @@ static void wait_for_serial(const char *side)
>  {
>  char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
>  FILE *serialfile = fopen(serialpath, "r");
> +const char *arch = qtest_get_arch();
> +int started = (strcmp(side, "src_serial") == 0 &&
> +   strcmp(arch, "ppc64") == 0) ? 0 : 1;
>  
>  do {
>  int readvalue = fgetc(serialfile);
>  
> +if (!started) {
> +/* SLOF prints its banner before starting test,
> + * to ignore it, mark the start of the test with '_',
> + * ignore all characters until this marker
> + */
> +switch (readvalue) {
> +case '_':
> +started = 1;
> +break;
> +case EOF:
> +fseek(serialfile, 0, SEEK_SET);
> +usleep(1000);
> +break;
> +}
> +continue;
> +}
>  switch (readvalue) {
>  case 'A':
>  /* Fine */
> @@ -147,6 +207,8 @@ static void wait_for_serial(const char *side)
>  return;
>  
>  case EOF:
> +started = (strcmp(side, "src_serial") == 0 &&
> +   strcmp(arch, "ppc64") == 0) ? 0 : 1;
>  fseek(serialfile, 0, SEEK_SET);
>  usleep(1000);
>  break;
> @@ -295,32 +357,48 @@ 

[Qemu-devel] Improving QEMU's About dialog

2016-07-26 Thread Programmingkid
Under Mac OS X, QEMU's about dialog is not very helpful. It only displays an 
icon and the name of the binary. I think this should be improved. Let me know 
what you think of this idea:




   Version: 
Git commit version: 
Build date: 

Example:

 


qemu-system-ppc   Version: 2.6.90
Git commit version: 2d2e632ad00d11867c6c5625605b1fbc022dd62f
Build date: 7-26-2016


Want anything added?


[Qemu-devel] forking a virtual machine

2016-07-26 Thread Tim Newsham
Hi,  We've got an unusual use case for our qemu virtual machines.
We're using a qemu-based system to run a bunch of instrumented
test cases. QEMU provides the instrumented execution environment.
Before we start testing we setup the test environment, which includes
booting an operating system as a guest.  Once everything is ready, we
fork the qemu process once for each test case, with the parent controlling
the test operation while the child performs a test.  (For more details,
see our blog post:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2016/june/project-triforce-run-afl-on-everything/,
full code
can be found at https://github.com/nccgroup/TriforceAFL)

Right now our fork process is very hacky and gross, because linux
fork() intentionally does not handle forking a multithreaded program.
 We have a special
cpu instruction which triggers the forking to go into test mode.  It sets a
flag, which causes the one and only cpu thread to exit.  Right before it
exits, it sends a signal to the iothread by writing over a pipe.  The
iothread
gets woken up and starts controlling test cases by forking children.
After each fork, it starts up a new cpu to replace the one that exited
before the fork.

This is less than ideal for several reasons.  Most importantly for us, we
would like to be able to communicate informatoin about new JITs that
occur from the child back to the parent so that the parent can reproduce
the JIT and save future children from having to keep JITting the same
thing.  This doesnt currently work (I think because the cpu has exited,
and there is no cpu left in the parent process).

We would also like to have more elegant forking code.

And so my question here -- Is there a better solution that we could use
to support forking a qemu VM?  Are there any single-threaded variants of
qemu that would work well here?  Are there any interesting tricks to pause
and resume a cpu across forks in a clean fashion?  Has anyone else
already worked on this problem?

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


[Qemu-devel] [PATCH 25/32] ppc: Handle unconditional (always/never) traps at translation time

2016-07-26 Thread Benjamin Herrenschmidt
We don't need to call a helper for trap always and trap never
which are used by Linux under some circumstances.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c | 48 ++--
 1 file changed, 42 insertions(+), 6 deletions(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 9af3f5f..57a891b 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3360,10 +3360,29 @@ static void gen_sc(DisasContext *ctx)
 
 /***Trap   ***/
 
+/* Check for unconditional traps (always or never) */
+static bool check_unconditional_trap(DisasContext *ctx)
+{
+/* Trap never */
+if (TO(ctx->opcode) == 0) {
+return true;
+}
+/* Trap always */
+if (TO(ctx->opcode) == 31) {
+gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
+}
+return false;
+}
+
 /* tw */
 static void gen_tw(DisasContext *ctx)
 {
-TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
+TCGv_i32 t0;
+
+if (check_unconditional_trap(ctx)) {
+return;
+}
+t0 = tcg_const_i32(TO(ctx->opcode));
 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
   t0);
 tcg_temp_free_i32(t0);
@@ -3372,8 +3391,14 @@ static void gen_tw(DisasContext *ctx)
 /* twi */
 static void gen_twi(DisasContext *ctx)
 {
-TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
-TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
+TCGv t0;
+TCGv_i32 t1;
+
+if (check_unconditional_trap(ctx)) {
+return;
+}
+t0 = tcg_const_tl(SIMM(ctx->opcode));
+t1 = tcg_const_i32(TO(ctx->opcode));
 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
 tcg_temp_free(t0);
 tcg_temp_free_i32(t1);
@@ -3383,7 +3408,12 @@ static void gen_twi(DisasContext *ctx)
 /* td */
 static void gen_td(DisasContext *ctx)
 {
-TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
+TCGv_i32 t0;
+
+if (check_unconditional_trap(ctx)) {
+return;
+}
+t0 = tcg_const_i32(TO(ctx->opcode));
 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
   t0);
 tcg_temp_free_i32(t0);
@@ -3392,8 +3422,14 @@ static void gen_td(DisasContext *ctx)
 /* tdi */
 static void gen_tdi(DisasContext *ctx)
 {
-TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
-TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
+TCGv t0;
+TCGv_i32 t1;
+
+if (check_unconditional_trap(ctx)) {
+return;
+}
+t0 = tcg_const_tl(SIMM(ctx->opcode));
+t1 = tcg_const_i32(TO(ctx->opcode));
 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
 tcg_temp_free(t0);
 tcg_temp_free_i32(t1);
-- 
2.7.4




[Qemu-devel] [PATCH 32/32] ppc: Speed up load/store multiple

2016-07-26 Thread Benjamin Herrenschmidt
Use a single translate when not crossing a page boundary and avoid
going through layers of helpers. MacOS uses those instructions
a lot, so does OpenBIOS.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/mem_helper.c | 69 +
 1 file changed, 69 insertions(+)

diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index da3f973..511079b 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -53,8 +53,48 @@ static inline target_ulong addr_add(CPUPPCState *env, 
target_ulong addr,
 }
 }
 
+/* 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)
+{
+#ifndef CONFIG_USER_ONLY
+if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) {
+return -addr & ~TARGET_PAGE_MASK;
+}
+#endif
+return len;
+}
+
 void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
 {
+uint32_t *src;
+uint64_t len, adjlen;
+
+if ((addr & 3)) {
+goto fallback;
+}
+len = (32 - reg) << 2;
+while (len) {
+src = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, env->dmmu_idx);
+if (!src) {
+goto fallback;
+}
+adjlen = adj_len_to_page(len, addr);
+len -= adjlen;
+#if defined(HOST_WORDS_BIGENDIAN)
+memcpy(>gpr[reg], src, adjlen);
+reg += (adjlen >> 2);
+addr = addr_add(env, addr, adjlen);
+#else
+while(adjlen) {
+env->gpr[reg++] = bswap32(*(src++));
+adjlen -= 4;
+addr = addr_add(env, addr, 4);
+}
+#endif
+}
+return;
+
+ fallback:
 for (; reg < 32; reg++) {
 if (needs_byteswap(env)) {
 env->gpr[reg] = bswap32(cpu_ldl_data_ra(env, addr, GETPC()));
@@ -67,6 +107,35 @@ void helper_lmw(CPUPPCState *env, target_ulong addr, 
uint32_t reg)
 
 void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
 {
+uint32_t *dst;
+uint64_t len, adjlen;
+
+if ((addr & 3)) {
+goto fallback;
+}
+len = (32 - reg) << 2;
+while (len) {
+dst = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, env->dmmu_idx);
+if (!dst) {
+goto fallback;
+}
+adjlen = adj_len_to_page(len, addr);
+len -= adjlen;
+#if defined(HOST_WORDS_BIGENDIAN)
+memcpy(dst, >gpr[reg], adjlen);
+reg += (adjlen >> 2);
+addr = addr_add(env, addr, adjlen);
+#else
+while(adjlen) {
+*(dst++) = bswap32(env->gpr[reg++]);
+adjlen -= 4;
+addr = addr_add(env, addr, 4);
+}
+#endif
+}
+return;
+
+ fallback:
 for (; reg < 32; reg++) {
 if (needs_byteswap(env)) {
 cpu_stl_data_ra(env, addr, bswap32((uint32_t)env->gpr[reg]),
-- 
2.7.4




[Qemu-devel] [PATCH 23/32] ppc: Don't update NIP in dcbz and lscbx

2016-07-26 Thread Benjamin Herrenschmidt
Instead, pass GETPC() result to the corresponding helpers.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/mem_helper.c | 9 +
 target-ppc/translate.c  | 4 
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index e20a53e..92a594c 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -141,13 +141,14 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, 
uint32_t nb,
 }
 }
 
-static void do_dcbz(CPUPPCState *env, target_ulong addr, int dcache_line_size)
+static void do_dcbz(CPUPPCState *env, target_ulong addr, int dcache_line_size,
+uintptr_t raddr)
 {
 int i;
 
 addr &= ~(dcache_line_size - 1);
 for (i = 0; i < dcache_line_size; i += 4) {
-cpu_stl_data(env, addr + i, 0);
+cpu_stl_data_ra(env, addr + i, 0, raddr);
 }
 if (env->reserve_addr == addr) {
 env->reserve_addr = (target_ulong)-1ULL;
@@ -168,7 +169,7 @@ void helper_dcbz(CPUPPCState *env, target_ulong addr, 
uint32_t is_dcbzl)
 
 /* XXX add e500mc support */
 
-do_dcbz(env, addr, dcbz_size);
+do_dcbz(env, addr, dcbz_size, GETPC());
 }
 
 void helper_icbi(CPUPPCState *env, target_ulong addr)
@@ -190,7 +191,7 @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong 
addr, uint32_t reg,
 
 d = 24;
 for (i = 0; i < xer_bc; i++) {
-c = cpu_ldub_data(env, addr);
+c = cpu_ldub_data_ra(env, addr, GETPC());
 addr = addr_add(env, addr, 1);
 /* ra (if not 0) and rb are never modified */
 if (likely(reg != rb && (ra == 0 || reg != ra))) {
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 8670932..ddfec33 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3819,8 +3819,6 @@ static void gen_dcbz(DisasContext *ctx)
 int is_dcbzl = ctx->opcode & 0x0020 ? 1 : 0;
 
 gen_set_access_type(ctx, ACCESS_CACHE);
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 tcgv_addr = tcg_temp_new();
 tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);
 
@@ -4348,8 +4346,6 @@ static void gen_lscbx(DisasContext *ctx)
 TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
 
 gen_addr_reg_index(ctx, t0);
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
 tcg_temp_free_i32(t1);
 tcg_temp_free_i32(t2);
-- 
2.7.4




[Qemu-devel] [PATCH 26/32] ppc: Speed up dcbz

2016-07-26 Thread Benjamin Herrenschmidt
Use tlb_vaddr_to_host to do a fast path single translate for
the whole cache line. Also make the reservation check match
the entire range.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/mem_helper.c | 46 +-
 target-ppc/translate.c  | 11 ---
 2 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index 92a594c..6548715 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -141,35 +141,39 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, 
uint32_t nb,
 }
 }
 
-static void do_dcbz(CPUPPCState *env, target_ulong addr, int dcache_line_size,
-uintptr_t raddr)
+void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode)
 {
-int i;
-
-addr &= ~(dcache_line_size - 1);
-for (i = 0; i < dcache_line_size; i += 4) {
-cpu_stl_data_ra(env, addr + i, 0, raddr);
-}
-if (env->reserve_addr == addr) {
-env->reserve_addr = (target_ulong)-1ULL;
-}
-}
-
-void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t is_dcbzl)
-{
-int dcbz_size = env->dcache_line_size;
+target_ulong mask, dcbz_size = env->dcache_line_size;
+uint32_t i;
+void *haddr;
 
 #if defined(TARGET_PPC64)
-if (!is_dcbzl &&
-(env->excp_model == POWERPC_EXCP_970) &&
-((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) {
+/* Check for dcbz vs dcbzl on 970 */
+if (env->excp_model == POWERPC_EXCP_970 &&
+!(opcode & 0x0020) && ((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) {
 dcbz_size = 32;
 }
 #endif
 
-/* XXX add e500mc support */
+/* Align address */
+mask = ~(dcbz_size - 1);
+addr &= mask;
+
+/* Check reservation */
+if ((env->reserve_addr & mask) == (addr & mask))  {
+env->reserve_addr = (target_ulong)-1ULL;
+}
 
-do_dcbz(env, addr, dcbz_size, GETPC());
+/* Try fast path translate */
+haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, env->dmmu_idx);
+if (haddr) {
+memset(haddr, 0, dcbz_size);
+} else {
+/* Slow path */
+for (i = 0; i < dcbz_size; i += 8) {
+cpu_stq_data_ra(env, addr + i, 0, GETPC());
+}
+}
 }
 
 void helper_icbi(CPUPPCState *env, target_ulong addr)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 57a891b..5288e02 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3851,18 +3851,15 @@ static void gen_dcbtls(DisasContext *ctx)
 static void gen_dcbz(DisasContext *ctx)
 {
 TCGv tcgv_addr;
-TCGv_i32 tcgv_is_dcbzl;
-int is_dcbzl = ctx->opcode & 0x0020 ? 1 : 0;
+TCGv_i32 tcgv_op;
 
 gen_set_access_type(ctx, ACCESS_CACHE);
 tcgv_addr = tcg_temp_new();
-tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);
-
+tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000);
 gen_addr_reg_index(ctx, tcgv_addr);
-gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_is_dcbzl);
-
+gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_op);
 tcg_temp_free(tcgv_addr);
-tcg_temp_free_i32(tcgv_is_dcbzl);
+tcg_temp_free_i32(tcgv_op);
 }
 
 /* dst / dstt */
-- 
2.7.4




[Qemu-devel] [PATCH 22/32] ppc: Don't update NIP if not taking alignment exceptions

2016-07-26 Thread Benjamin Herrenschmidt
Move the NIP update to after the conditional branch so that we
don't do it if we aren't going to take the alignment exception

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 7163b19..8670932 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2199,12 +2199,11 @@ static inline void gen_check_align(DisasContext *ctx, 
TCGv EA, int mask)
 TCGLabel *l1 = gen_new_label();
 TCGv t0 = tcg_temp_new();
 TCGv_i32 t1, t2;
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 tcg_gen_andi_tl(t0, EA, mask);
 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
 t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
 t2 = tcg_const_i32(0);
+gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_raise_exception_err(cpu_env, t1, t2);
 tcg_temp_free_i32(t1);
 tcg_temp_free_i32(t2);
-- 
2.7.4




[Qemu-devel] [PATCH 30/32] ppc: Use a helper to generate "LE unsupported" alignment interrupts

2016-07-26 Thread Benjamin Herrenschmidt
Some operations aren't allowed in LE mode, use a helper rather than
open coding the exception generation.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index fcff24a..df9a5bd 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2212,6 +2212,12 @@ static inline void gen_check_align(DisasContext *ctx, 
TCGv EA, int mask)
 tcg_temp_free(t0);
 }
 
+static inline void gen_align_no_le(DisasContext *ctx)
+{
+gen_exception_err(ctx, POWERPC_EXCP_ALIGN,
+  (ctx->opcode & 0x03FF) | POWERPC_EXCP_ALIGN_LE);
+}
+
 /*** Integer load  ***/
 static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
 {
@@ -2432,10 +2438,9 @@ static void gen_lq(DisasContext *ctx)
 }
 
 if (!le_is_supported && ctx->le_mode) {
-gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
+gen_align_no_le(ctx);
 return;
 }
-
 ra = rA(ctx->opcode);
 rd = rD(ctx->opcode);
 if (unlikely((rd & 1) || rd == ra)) {
@@ -2566,7 +2571,7 @@ static void gen_std(DisasContext *ctx)
 }
 
 if (!le_is_supported && ctx->le_mode) {
-gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
+gen_align_no_le(ctx);
 return;
 }
 
-- 
2.7.4




[Qemu-devel] [PATCH 31/32] ppc: load/store multiple and string insns don't do LE

2016-07-26 Thread Benjamin Herrenschmidt
Just generate an alignment interrupt

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index df9a5bd..3a6de20 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2674,6 +2674,11 @@ static void gen_lmw(DisasContext *ctx)
 {
 TCGv t0;
 TCGv_i32 t1;
+
+if (ctx->le_mode) {
+gen_align_no_le(ctx);
+return;
+}
 gen_set_access_type(ctx, ACCESS_INT);
 t0 = tcg_temp_new();
 t1 = tcg_const_i32(rD(ctx->opcode));
@@ -2688,6 +2693,11 @@ static void gen_stmw(DisasContext *ctx)
 {
 TCGv t0;
 TCGv_i32 t1;
+
+if (ctx->le_mode) {
+gen_align_no_le(ctx);
+return;
+}
 gen_set_access_type(ctx, ACCESS_INT);
 t0 = tcg_temp_new();
 t1 = tcg_const_i32(rS(ctx->opcode));
@@ -2714,6 +2724,10 @@ static void gen_lswi(DisasContext *ctx)
 int ra = rA(ctx->opcode);
 int nr;
 
+if (ctx->le_mode) {
+gen_align_no_le(ctx);
+return;
+}
 if (nb == 0)
 nb = 32;
 nr = (nb + 3) / 4;
@@ -2737,6 +2751,11 @@ static void gen_lswx(DisasContext *ctx)
 {
 TCGv t0;
 TCGv_i32 t1, t2, t3;
+
+if (ctx->le_mode) {
+gen_align_no_le(ctx);
+return;
+}
 gen_set_access_type(ctx, ACCESS_INT);
 t0 = tcg_temp_new();
 gen_addr_reg_index(ctx, t0);
@@ -2756,6 +2775,11 @@ static void gen_stswi(DisasContext *ctx)
 TCGv t0;
 TCGv_i32 t1, t2;
 int nb = NB(ctx->opcode);
+
+if (ctx->le_mode) {
+gen_align_no_le(ctx);
+return;
+}
 gen_set_access_type(ctx, ACCESS_INT);
 t0 = tcg_temp_new();
 gen_addr_register(ctx, t0);
@@ -2774,6 +2798,11 @@ static void gen_stswx(DisasContext *ctx)
 {
 TCGv t0;
 TCGv_i32 t1, t2;
+
+if (ctx->le_mode) {
+gen_align_no_le(ctx);
+return;
+}
 gen_set_access_type(ctx, ACCESS_INT);
 t0 = tcg_temp_new();
 gen_addr_reg_index(ctx, t0);
-- 
2.7.4




[Qemu-devel] [PATCH 28/32] ppc: Avoid double translation for lvx/lvxl/stvx/stvxl

2016-07-26 Thread Benjamin Herrenschmidt
Those are always naturally aligned, so cannot cross a page boundary,
thus instead of generating two 8-byte loads with translation on each
(and double swap for LE on LE), we use a helper that will do a single
translation and memcpy the result over (or do appropriate swapping
if needed).

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/helper.h |  2 ++
 target-ppc/mem_helper.c | 60 +
 target-ppc/translate/vmx-impl.c | 38 --
 target-ppc/translate/vmx-ops.c  |  4 +--
 4 files changed, 75 insertions(+), 29 deletions(-)

diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 1f5cfd0..64f7d2c 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -269,9 +269,11 @@ DEF_HELPER_5(vmsumshm, void, env, avr, avr, avr, avr)
 DEF_HELPER_5(vmsumshs, void, env, avr, avr, avr, avr)
 DEF_HELPER_4(vmladduhm, void, avr, avr, avr, avr)
 DEF_HELPER_2(mtvscr, void, env, avr)
+DEF_HELPER_3(lvx, void, env, i32, tl)
 DEF_HELPER_3(lvebx, void, env, avr, tl)
 DEF_HELPER_3(lvehx, void, env, avr, tl)
 DEF_HELPER_3(lvewx, void, env, avr, tl)
+DEF_HELPER_3(stvx, void, env, i32, tl)
 DEF_HELPER_3(stvebx, void, env, avr, tl)
 DEF_HELPER_3(stvehx, void, env, avr, tl)
 DEF_HELPER_3(stvewx, void, env, avr, tl)
diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index 6548715..da3f973 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -225,6 +225,66 @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong 
addr, uint32_t reg,
 #define LO_IDX 0
 #endif
 
+void helper_lvx(CPUPPCState *env, uint32_t vr, target_ulong addr)
+{
+uintptr_t raddr = GETPC();
+ppc_avr_t *haddr;
+
+/* Align address */
+addr &= ~(target_ulong)0xf;
+
+/* Try fast path translate */
+haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, env->dmmu_idx);
+if (haddr) {
+if (msr_le && HI_IDX) {
+memcpy(>avr[vr], haddr, 16);
+} else {
+env->avr[vr].u64[LO_IDX] = bswap64(haddr->u64[HI_IDX]);
+env->avr[vr].u64[HI_IDX] = bswap64(haddr->u64[LO_IDX]);
+}
+} else {
+if (needs_byteswap(env)) {
+env->avr[vr].u64[LO_IDX] =
+bswap64(cpu_ldq_data_ra(env, addr, raddr));
+env->avr[vr].u64[HI_IDX] =
+bswap64(cpu_ldq_data_ra(env, addr + 8, raddr));
+} else {
+env->avr[vr].u64[HI_IDX] = cpu_ldq_data_ra(env, addr, raddr);
+env->avr[vr].u64[LO_IDX] = cpu_ldq_data_ra(env, addr + 8, raddr);
+}
+}
+}
+
+void helper_stvx(CPUPPCState *env, uint32_t vr, target_ulong addr)
+{
+uintptr_t raddr = GETPC();
+ppc_avr_t *haddr;
+
+/* Align address */
+addr &= ~(target_ulong)0xf;
+
+/* Try fast path translate */
+haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, env->dmmu_idx);
+if (haddr) {
+if (msr_le && HI_IDX) {
+memcpy(haddr, >avr[vr], 16);
+} else {
+haddr->u64[LO_IDX] = bswap64(env->avr[vr].u64[HI_IDX]);
+haddr->u64[HI_IDX] = bswap64(env->avr[vr].u64[LO_IDX]);
+}
+} else {
+if (needs_byteswap(env)) {
+cpu_stq_data_ra(env, addr,
+bswap64(env->avr[vr].u64[LO_IDX]), raddr);
+cpu_stq_data_ra(env, addr + 8,
+bswap64(env->avr[vr].u64[HI_IDX]), raddr);
+} else {
+cpu_stq_data_ra(env, addr, env->avr[vr].u64[HI_IDX], raddr);
+cpu_stq_data_ra(env, addr + 8, env->avr[vr].u64[LO_IDX], raddr);
+}
+}
+}
+
 /* We use msr_le to determine index ordering in a vector.  However,
byteswapping is not simply controlled by msr_le.  We also need to take
into account endianness of the target.  This is done for the little-endian
diff --git a/target-ppc/translate/vmx-impl.c b/target-ppc/translate/vmx-impl.c
index 110e19c..a58aa0c 100644
--- a/target-ppc/translate/vmx-impl.c
+++ b/target-ppc/translate/vmx-impl.c
@@ -15,55 +15,39 @@ static inline TCGv_ptr gen_avr_ptr(int reg)
 }
 
 #define GEN_VR_LDX(name, opc2, opc3)  \
-static void glue(gen_, name)(DisasContext *ctx)
   \
+static void glue(gen_, name)(DisasContext *ctx)   \
 { \
 TCGv EA;  \
+TCGv_i32 t0;  \
 if (unlikely(!ctx->altivec_enabled)) {\
 gen_exception(ctx, POWERPC_EXCP_VPU); \
 return;   \
 } \
 gen_set_access_type(ctx, ACCESS_INT); 

[Qemu-devel] [PATCH 27/32] ppc: Fix CFAR updates

2016-07-26 Thread Benjamin Herrenschmidt
We were one instruction off

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 5288e02..57e9a12 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3131,7 +3131,7 @@ static void gen_b(DisasContext *ctx)
 if (LK(ctx->opcode)) {
 gen_setlr(ctx, ctx->nip);
 }
-gen_update_cfar(ctx, ctx->nip);
+gen_update_cfar(ctx, ctx->nip - 4);
 gen_goto_tb(ctx, 0, target);
 }
 
@@ -3196,7 +3196,7 @@ static inline void gen_bcond(DisasContext *ctx, int type)
 }
 tcg_temp_free_i32(temp);
 }
-gen_update_cfar(ctx, ctx->nip);
+gen_update_cfar(ctx, ctx->nip - 4);
 if (type == BCOND_IM) {
 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
 if (likely(AA(ctx->opcode) == 0)) {
@@ -3311,7 +3311,7 @@ static void gen_rfi(DisasContext *ctx)
  */
 /* Restore CPU state */
 CHK_SV;
-gen_update_cfar(ctx, ctx->nip);
+gen_update_cfar(ctx, ctx->nip - 4);
 gen_helper_rfi(cpu_env);
 gen_sync_exception(ctx);
 #endif
@@ -3325,7 +3325,7 @@ static void gen_rfid(DisasContext *ctx)
 #else
 /* Restore CPU state */
 CHK_SV;
-gen_update_cfar(ctx, ctx->nip);
+gen_update_cfar(ctx, ctx->nip - 4);
 gen_helper_rfid(cpu_env);
 gen_sync_exception(ctx);
 #endif
-- 
2.7.4




[Qemu-devel] [PATCH 24/32] ppc: Make alignment exceptions suck less

2016-07-26 Thread Benjamin Herrenschmidt
The current alignment exception generation tries to load the opcode
to put in DSISR from a context where a cpu_ldl_code() is really not
a good idea. It might fault and longjmp out and that's not something
we want happening here.

Instead, pass the releavant opcode bits via the error_code.

There are a couple of cases of alignment interrupts that won't set
anything, the ones coming from access to direct store segments, but
that doesn't happen in practice, nobody used direct store segments
and they are gone from newer chips.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/excp_helper.c | 9 +
 target-ppc/translate.c   | 2 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index c31bbad..9a26578 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -260,11 +260,12 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 }
 break;
 case POWERPC_EXCP_ALIGN: /* Alignment exception  */
-/* XXX: this is false */
 /* Get rS/rD and rA from faulting opcode */
-/* Broken for LE mode */
-env->spr[SPR_DSISR] |= (cpu_ldl_code(env, env->nip)
-& 0x03FF) >> 16;
+/* Note: the opcode fields will not be set properly for a direct
+ * store load/store, but nobody cares as nobody actually uses
+ * direct store segments.
+ */
+env->spr[SPR_DSISR] |= (env->error_code & 0x03FF) >> 16;
 break;
 case POWERPC_EXCP_PROGRAM:   /* Program exception*/
 switch (env->error_code & ~0xF) {
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index ddfec33..9af3f5f 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2202,7 +2202,7 @@ static inline void gen_check_align(DisasContext *ctx, 
TCGv EA, int mask)
 tcg_gen_andi_tl(t0, EA, mask);
 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
 t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
-t2 = tcg_const_i32(0);
+t2 = tcg_const_i32(ctx->opcode & 0x03FF);
 gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_raise_exception_err(cpu_env, t1, t2);
 tcg_temp_free_i32(t1);
-- 
2.7.4




[Qemu-devel] [PATCH 17/32] ppc: Fix source NIP on SLB related interrupts

2016-07-26 Thread Benjamin Herrenschmidt
We need to pass it to the raise helper since we don't update it
before the calls.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/mmu-hash64.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 5de1358..8118143 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -241,8 +241,8 @@ void helper_store_slb(CPUPPCState *env, target_ulong rb, 
target_ulong rs)
 PowerPCCPU *cpu = ppc_env_get_cpu(env);
 
 if (ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs) < 0) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL, GETPC());
 }
 }
 
@@ -252,8 +252,8 @@ target_ulong helper_load_slb_esid(CPUPPCState *env, 
target_ulong rb)
 target_ulong rt = 0;
 
 if (ppc_load_slb_esid(cpu, rb, ) < 0) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL, GETPC());
 }
 return rt;
 }
@@ -264,8 +264,8 @@ target_ulong helper_find_slb_vsid(CPUPPCState *env, 
target_ulong rb)
 target_ulong rt = 0;
 
 if (ppc_find_slb_vsid(cpu, rb, ) < 0) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL, GETPC());
 }
 return rt;
 }
@@ -276,8 +276,8 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, 
target_ulong rb)
 target_ulong rt = 0;
 
 if (ppc_load_slb_vsid(cpu, rb, ) < 0) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL, GETPC());
 }
 return rt;
 }
-- 
2.7.4




[Qemu-devel] [PATCH 21/32] ppc: Don't update NIP on conditional trap instructions

2016-07-26 Thread Benjamin Herrenschmidt
This is no longer necessary as the helpers will properly retrieve
the return address when needed.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/excp_helper.c | 6 --
 target-ppc/translate.c   | 8 
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 570d188..c31bbad 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -1031,7 +1031,8 @@ void helper_tw(CPUPPCState *env, target_ulong arg1, 
target_ulong arg2,
   ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
   ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
   ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01) {
-raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_TRAP, GETPC());
 }
 }
 
@@ -1044,7 +1045,8 @@ void helper_td(CPUPPCState *env, target_ulong arg1, 
target_ulong arg2,
   ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
   ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
   ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01) {
-raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_TRAP, GETPC());
 }
 }
 #endif
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 8f5afba..7163b19 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3365,8 +3365,6 @@ static void gen_sc(DisasContext *ctx)
 static void gen_tw(DisasContext *ctx)
 {
 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
-/* Update the nip since this might generate a trap exception */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
   t0);
 tcg_temp_free_i32(t0);
@@ -3377,8 +3375,6 @@ static void gen_twi(DisasContext *ctx)
 {
 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
-/* Update the nip since this might generate a trap exception */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
 tcg_temp_free(t0);
 tcg_temp_free_i32(t1);
@@ -3389,8 +3385,6 @@ static void gen_twi(DisasContext *ctx)
 static void gen_td(DisasContext *ctx)
 {
 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
-/* Update the nip since this might generate a trap exception */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
   t0);
 tcg_temp_free_i32(t0);
@@ -3401,8 +3395,6 @@ static void gen_tdi(DisasContext *ctx)
 {
 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
-/* Update the nip since this might generate a trap exception */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
 tcg_temp_free(t0);
 tcg_temp_free_i32(t1);
-- 
2.7.4




[Qemu-devel] [PATCH 14/32] ppc: Don't update NIP in lmw/stmw/icbi

2016-07-26 Thread Benjamin Herrenschmidt
Instead, pass GETPC() result to the corresponding helpers.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/mem_helper.c | 11 ++-
 target-ppc/translate.c  |  6 --
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index de96c91..e20a53e 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -57,9 +57,9 @@ void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t 
reg)
 {
 for (; reg < 32; reg++) {
 if (needs_byteswap(env)) {
-env->gpr[reg] = bswap32(cpu_ldl_data(env, addr));
+env->gpr[reg] = bswap32(cpu_ldl_data_ra(env, addr, GETPC()));
 } else {
-env->gpr[reg] = cpu_ldl_data(env, addr);
+env->gpr[reg] = cpu_ldl_data_ra(env, addr, GETPC());
 }
 addr = addr_add(env, addr, 4);
 }
@@ -69,9 +69,10 @@ void helper_stmw(CPUPPCState *env, target_ulong addr, 
uint32_t reg)
 {
 for (; reg < 32; reg++) {
 if (needs_byteswap(env)) {
-cpu_stl_data(env, addr, bswap32((uint32_t)env->gpr[reg]));
+cpu_stl_data_ra(env, addr, bswap32((uint32_t)env->gpr[reg]),
+   GETPC());
 } else {
-cpu_stl_data(env, addr, (uint32_t)env->gpr[reg]);
+cpu_stl_data_ra(env, addr, (uint32_t)env->gpr[reg], GETPC());
 }
 addr = addr_add(env, addr, 4);
 }
@@ -178,7 +179,7 @@ void helper_icbi(CPUPPCState *env, target_ulong addr)
  * (not a fetch) by the MMU. To be sure it will be so,
  * do the load "by hand".
  */
-cpu_ldl_data(env, addr);
+cpu_ldl_data_ra(env, addr, GETPC());
 }
 
 /* XXX: to be tested */
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 9d2e923..c4f8916 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2654,8 +2654,6 @@ static void gen_lmw(DisasContext *ctx)
 TCGv t0;
 TCGv_i32 t1;
 gen_set_access_type(ctx, ACCESS_INT);
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 t0 = tcg_temp_new();
 t1 = tcg_const_i32(rD(ctx->opcode));
 gen_addr_imm_index(ctx, t0, 0);
@@ -2670,8 +2668,6 @@ static void gen_stmw(DisasContext *ctx)
 TCGv t0;
 TCGv_i32 t1;
 gen_set_access_type(ctx, ACCESS_INT);
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 t0 = tcg_temp_new();
 t1 = tcg_const_i32(rS(ctx->opcode));
 gen_addr_imm_index(ctx, t0, 0);
@@ -3872,8 +3868,6 @@ static void gen_icbi(DisasContext *ctx)
 {
 TCGv t0;
 gen_set_access_type(ctx, ACCESS_CACHE);
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 t0 = tcg_temp_new();
 gen_addr_reg_index(ctx, t0);
 gen_helper_icbi(cpu_env, t0);
-- 
2.7.4




[Qemu-devel] [PATCH 16/32] ppc: Rework NIP updates vs. exception generation

2016-07-26 Thread Benjamin Herrenschmidt
We make env->nip almost always point to the faulting instruction,
thus avoiding a mess of "store_current" vs "store_next" in the
exception handling. The syscall exception knows to move the PC by
4 and that's really about it.

This actually fixes a number of cases where the translator was
setting env->nip to ctx->nip - 4 (ie. the *current* instruction)
but the program check exception handler would branch to
"store_current" which applies another -4 offset.

Signed-off-by: Benjamin Herrenschmidt 
---
 linux-user/main.c|  12 ++--
 target-ppc/excp_helper.c | 148 ++-
 target-ppc/translate.c   |  59 +++
 3 files changed, 96 insertions(+), 123 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 462e820..1d149dc 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1814,7 +1814,7 @@ void cpu_loop(CPUPPCState *env)
   env->error_code);
 break;
 }
-info._sifields._sigfault._addr = env->nip - 4;
+info._sifields._sigfault._addr = env->nip;
 queue_signal(env, info.si_signo, );
 break;
 case POWERPC_EXCP_FPU:  /* Floating-point unavailable exception  */
@@ -1822,7 +1822,7 @@ void cpu_loop(CPUPPCState *env)
 info.si_signo = TARGET_SIGILL;
 info.si_errno = 0;
 info.si_code = TARGET_ILL_COPROC;
-info._sifields._sigfault._addr = env->nip - 4;
+info._sifields._sigfault._addr = env->nip;
 queue_signal(env, info.si_signo, );
 break;
 case POWERPC_EXCP_SYSCALL:  /* System call exception */
@@ -1834,7 +1834,7 @@ void cpu_loop(CPUPPCState *env)
 info.si_signo = TARGET_SIGILL;
 info.si_errno = 0;
 info.si_code = TARGET_ILL_COPROC;
-info._sifields._sigfault._addr = env->nip - 4;
+info._sifields._sigfault._addr = env->nip;
 queue_signal(env, info.si_signo, );
 break;
 case POWERPC_EXCP_DECR: /* Decrementer exception */
@@ -1862,7 +1862,7 @@ void cpu_loop(CPUPPCState *env)
 info.si_signo = TARGET_SIGILL;
 info.si_errno = 0;
 info.si_code = TARGET_ILL_COPROC;
-info._sifields._sigfault._addr = env->nip - 4;
+info._sifields._sigfault._addr = env->nip;
 queue_signal(env, info.si_signo, );
 break;
 case POWERPC_EXCP_EFPDI:/* Embedded floating-point data IRQ  */
@@ -1926,7 +1926,7 @@ void cpu_loop(CPUPPCState *env)
 info.si_signo = TARGET_SIGILL;
 info.si_errno = 0;
 info.si_code = TARGET_ILL_COPROC;
-info._sifields._sigfault._addr = env->nip - 4;
+info._sifields._sigfault._addr = env->nip;
 queue_signal(env, info.si_signo, );
 break;
 case POWERPC_EXCP_PIT:  /* Programmable interval timer IRQ   */
@@ -2001,9 +2001,9 @@ void cpu_loop(CPUPPCState *env)
  env->gpr[5], env->gpr[6], env->gpr[7],
  env->gpr[8], 0, 0);
 if (ret == -TARGET_ERESTARTSYS) {
-env->nip -= 4;
 break;
 }
+env->nip += 4;
 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
 /* Returning from a successful sigreturn syscall.
Avoid corrupting register state.  */
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 563c7bc..570d188 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -198,7 +198,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 default:
 goto excp_invalid;
 }
-goto store_next;
+break;
 case POWERPC_EXCP_MCHECK:/* Machine check exception  */
 if (msr_me == 0) {
 /* Machine check exception is not enabled.
@@ -209,7 +209,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 if (qemu_log_separate()) {
 qemu_log("Machine check while not allowed. "
 "Entering checkstop state\n");
-}
+ }
 cs->halted = 1;
 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
@@ -235,16 +235,16 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 default:
 break;
 }
-goto store_next;
+break;
 case POWERPC_EXCP_DSI:   /* Data storage exception   */
 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
  "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
-goto store_next;
+break;
 case POWERPC_EXCP_ISI:   /* Instruction storage exception  

[Qemu-devel] [PATCH 19/32] ppc: Don't update NIP in facility unavailable interrupts

2016-07-26 Thread Benjamin Herrenschmidt
This is no longer necessary as the helpers will properly retrieve
the return address when needed. Also remove gen_update_current_nip()
which didn't seem to make much sense to me.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/cpu.h| 1 -
 target-ppc/misc_helper.c| 9 +
 target-ppc/translate.c  | 7 ---
 target-ppc/translate_init.c | 2 --
 4 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 2ee7a5e..0786738 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1201,7 +1201,6 @@ extern const struct VMStateDescription vmstate_ppc_cpu;
 /*/
 PowerPCCPU *cpu_ppc_init(const char *cpu_model);
 void ppc_translate_init(void);
-void gen_update_current_nip(void *opaque);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU.  */
diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
index cb5ebf5..1e6e705 100644
--- a/target-ppc/misc_helper.c
+++ b/target-ppc/misc_helper.c
@@ -39,7 +39,8 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
 
 #ifdef TARGET_PPC64
 static void raise_fu_exception(CPUPPCState *env, uint32_t bit,
-   uint32_t sprn, uint32_t cause)
+   uint32_t sprn, uint32_t cause,
+   uintptr_t raddr)
 {
 qemu_log("Facility SPR %d is unavailable (SPR FSCR:%d)\n", sprn, bit);
 
@@ -47,7 +48,7 @@ static void raise_fu_exception(CPUPPCState *env, uint32_t bit,
 cause &= FSCR_IC_MASK;
 env->spr[SPR_FSCR] |= (target_ulong)cause << FSCR_IC_POS;
 
-helper_raise_exception_err(env, POWERPC_EXCP_FU, 0);
+raise_exception_err_ra(env, POWERPC_EXCP_FU, 0, raddr);
 }
 #endif
 
@@ -59,7 +60,7 @@ void helper_fscr_facility_check(CPUPPCState *env, uint32_t 
bit,
 /* Facility is enabled, continue */
 return;
 }
-raise_fu_exception(env, bit, sprn, cause);
+raise_fu_exception(env, bit, sprn, cause, GETPC());
 #endif
 }
 
@@ -71,7 +72,7 @@ void helper_msr_facility_check(CPUPPCState *env, uint32_t bit,
 /* Facility is enabled, continue */
 return;
 }
-raise_fu_exception(env, bit, sprn, cause);
+raise_fu_exception(env, bit, sprn, cause, GETPC());
 #endif
 }
 
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index f0e0ec6..4577788 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -266,13 +266,6 @@ static inline void gen_update_nip(DisasContext *ctx, 
target_ulong nip)
 tcg_gen_movi_tl(cpu_nip, nip);
 }
 
-void gen_update_current_nip(void *opaque)
-{
-DisasContext *ctx = opaque;
-
-tcg_gen_movi_tl(cpu_nip, ctx->nip);
-}
-
 static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
 {
 TCGv_i32 t0, t1;
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 5ecafc7..74b1b33 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7469,7 +7469,6 @@ static void gen_fscr_facility_check(DisasContext *ctx, 
int facility_sprn,
 TCGv_i32 t2 = tcg_const_i32(sprn);
 TCGv_i32 t3 = tcg_const_i32(cause);
 
-gen_update_current_nip(ctx);
 gen_helper_fscr_facility_check(cpu_env, t1, t2, t3);
 
 tcg_temp_free_i32(t3);
@@ -7484,7 +7483,6 @@ static void gen_msr_facility_check(DisasContext *ctx, int 
facility_sprn,
 TCGv_i32 t2 = tcg_const_i32(sprn);
 TCGv_i32 t3 = tcg_const_i32(cause);
 
-gen_update_current_nip(ctx);
 gen_helper_msr_facility_check(cpu_env, t1, t2, t3);
 
 tcg_temp_free_i32(t3);
-- 
2.7.4




[Qemu-devel] [PATCH 29/32] ppc: Don't set access_type on all load/stores on hash64

2016-07-26 Thread Benjamin Herrenschmidt
We don't use it so let's not generate the updates.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 57e9a12..fcff24a 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -195,6 +195,7 @@ struct DisasContext {
 /* Routine used to access memory */
 bool pr, hv, dr, le_mode;
 bool lazy_tlb_flush;
+bool need_access_type;
 int mem_idx;
 int access_type;
 /* Translation flags */
@@ -252,7 +253,7 @@ struct opc_handler_t {
 
 static inline void gen_set_access_type(DisasContext *ctx, int access_type)
 {
-if (ctx->access_type != access_type) {
+if (ctx->need_access_type && ctx->access_type != access_type) {
 tcg_gen_movi_i32(cpu_access_type, access_type);
 ctx->access_type = access_type;
 }
@@ -6638,6 +6639,7 @@ void gen_intermediate_code(CPUPPCState *env, struct 
TranslationBlock *tb)
 ctx.insns_flags = env->insns_flags;
 ctx.insns_flags2 = env->insns_flags2;
 ctx.access_type = -1;
+ctx.need_access_type = !(env->mmu_model & POWERPC_MMU_64B);
 ctx.le_mode = !!(env->hflags & (1 << MSR_LE));
 ctx.default_tcg_memop_mask = ctx.le_mode ? MO_LE : MO_BE;
 #if defined(TARGET_PPC64)
-- 
2.7.4




[Qemu-devel] [PATCH 18/32] ppc: Don't update NIP in DCR access routines

2016-07-26 Thread Benjamin Herrenschmidt
This is no longer necessary as the helpers will properly retrieve
the return address when needed

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/timebase_helper.c | 23 +--
 target-ppc/translate.c   | 12 
 2 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/target-ppc/timebase_helper.c b/target-ppc/timebase_helper.c
index a07faa4..73363e0 100644
--- a/target-ppc/timebase_helper.c
+++ b/target-ppc/timebase_helper.c
@@ -19,6 +19,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/exec-all.h"
 #include "qemu/log.h"
 
 /*/
@@ -143,15 +144,16 @@ target_ulong helper_load_dcr(CPUPPCState *env, 
target_ulong dcrn)
 
 if (unlikely(env->dcr_env == NULL)) {
 qemu_log_mask(LOG_GUEST_ERROR, "No DCR environment\n");
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL |
-   POWERPC_EXCP_INVAL_INVAL);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL |
+   POWERPC_EXCP_INVAL_INVAL, GETPC());
 } else if (unlikely(ppc_dcr_read(env->dcr_env,
  (uint32_t)dcrn, ) != 0)) {
 qemu_log_mask(LOG_GUEST_ERROR, "DCR read error %d %03x\n",
   (uint32_t)dcrn, (uint32_t)dcrn);
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL |
+   POWERPC_EXCP_PRIV_REG, GETPC());
 }
 return val;
 }
@@ -160,14 +162,15 @@ void helper_store_dcr(CPUPPCState *env, target_ulong 
dcrn, target_ulong val)
 {
 if (unlikely(env->dcr_env == NULL)) {
 qemu_log_mask(LOG_GUEST_ERROR, "No DCR environment\n");
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL |
-   POWERPC_EXCP_INVAL_INVAL);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL |
+   POWERPC_EXCP_INVAL_INVAL, GETPC());
 } else if (unlikely(ppc_dcr_write(env->dcr_env, (uint32_t)dcrn,
   (uint32_t)val) != 0)) {
 qemu_log_mask(LOG_GUEST_ERROR, "DCR write error %d %03x\n",
   (uint32_t)dcrn, (uint32_t)dcrn);
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL |
+   POWERPC_EXCP_PRIV_REG, GETPC());
 }
 }
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 84bcb09..f0e0ec6 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -5262,8 +5262,6 @@ static void gen_mfdcr(DisasContext *ctx)
 TCGv dcrn;
 
 CHK_SV;
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 dcrn = tcg_const_tl(SPR(ctx->opcode));
 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
 tcg_temp_free(dcrn);
@@ -5279,8 +5277,6 @@ static void gen_mtdcr(DisasContext *ctx)
 TCGv dcrn;
 
 CHK_SV;
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 dcrn = tcg_const_tl(SPR(ctx->opcode));
 gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
 tcg_temp_free(dcrn);
@@ -5295,8 +5291,6 @@ static void gen_mfdcrx(DisasContext *ctx)
 GEN_PRIV;
 #else
 CHK_SV;
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
 cpu_gpr[rA(ctx->opcode)]);
 /* Note: Rc update flag set leads to undefined state of Rc0 */
@@ -5311,8 +5305,6 @@ static void gen_mtdcrx(DisasContext *ctx)
 GEN_PRIV;
 #else
 CHK_SV;
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
  cpu_gpr[rS(ctx->opcode)]);
 /* Note: Rc update flag set leads to undefined state of Rc0 */
@@ -5322,8 +5314,6 @@ static void gen_mtdcrx(DisasContext *ctx)
 /* mfdcrux (PPC 460) : user-mode access to DCR */
 static void gen_mfdcrux(DisasContext *ctx)
 {
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 

[Qemu-devel] [PATCH 12/32] ppc: FP exceptions are always precise

2016-07-26 Thread Benjamin Herrenschmidt
We don't implement imprecise FP exceptions and using store_current
which sets SRR1 to the *previous* instruction never makes sense
for these. So let's be truthful and make them precise, which is
allowed by the architecture.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/excp_helper.c | 11 ++-
 target-ppc/translate.c   |  1 -
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index f4b115e..91fdf4b 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -274,12 +274,13 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 env->error_code = 0;
 return;
 }
+
+/* FP exceptions always have NIP pointing to the faulting
+ * instruction, so always use store_next and claim we are
+ * precise in the MSR.
+ */
 msr |= 0x0010;
-if (msr_fe0 == msr_fe1) {
-goto store_next;
-}
-msr |= 0x0001;
-break;
+goto store_next;
 case POWERPC_EXCP_INVAL:
 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
 msr |= 0x0008;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index cb4e313..a05fed7 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2846,7 +2846,6 @@ static void gen_conditional_store(DisasContext *ctx, TCGv 
EA,
   int reg, int size)
 {
 TCGv t0 = tcg_temp_new();
-uint32_t save_exception = ctx->exception;
 
 tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
 tcg_gen_movi_tl(t0, (size << 5) | reg);
-- 
2.7.4




[Qemu-devel] [PATCH 20/32] ppc: Don't update NIP BookE 2.06 tlbwe

2016-07-26 Thread Benjamin Herrenschmidt
This is no longer necessary as the helpers will properly retrieve
the return address when needed.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/mmu_helper.c | 12 ++--
 target-ppc/translate.c  |  1 -
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 80cc262..40aaffa 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -2598,9 +2598,9 @@ void helper_booke206_tlbwe(CPUPPCState *env)
 tlb = booke206_cur_tlb(env);
 
 if (!tlb) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL |
-   POWERPC_EXCP_INVAL_INVAL);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL |
+   POWERPC_EXCP_INVAL_INVAL, GETPC());
 }
 
 /* check that we support the targeted size */
@@ -2608,9 +2608,9 @@ void helper_booke206_tlbwe(CPUPPCState *env)
 size_ps = booke206_tlbnps(env, tlbn);
 if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
 !(size_ps & (1 << size_tlb))) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL |
-   POWERPC_EXCP_INVAL_INVAL);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL |
+   POWERPC_EXCP_INVAL_INVAL, GETPC());
 }
 
 if (msr_gs) {
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 4577788..8f5afba 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -5613,7 +5613,6 @@ static void gen_tlbwe_booke206(DisasContext *ctx)
 GEN_PRIV;
 #else
 CHK_SV;
-gen_update_nip(ctx, ctx->nip - 4);
 gen_helper_booke206_tlbwe(cpu_env);
 #endif /* defined(CONFIG_USER_ONLY) */
 }
-- 
2.7.4




[Qemu-devel] [PATCH 08/32] ppc: Rename fload_invalid_op_excp to float_invalid_op_excp

2016-07-26 Thread Benjamin Herrenschmidt
No other change

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/fpu_helper.c | 122 
 1 file changed, 61 insertions(+), 61 deletions(-)

diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index d9795d0..e1f600a 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -116,7 +116,7 @@ void helper_compute_fprf(CPUPPCState *env, uint64_t arg)
 }
 
 /* Floating-point invalid operations exception */
-static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op,
+static inline uint64_t float_invalid_op_excp(CPUPPCState *env, int op,
  int set_fpcc)
 {
 CPUState *cs = CPU(ppc_env_get_cpu(env));
@@ -532,12 +532,12 @@ uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, 
uint64_t arg2)
 if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) 
&&
  float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
 /* Magnitude subtraction of infinities */
-farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
 } else {
 if (unlikely(float64_is_signaling_nan(farg1.d, >fp_status) ||
  float64_is_signaling_nan(farg2.d, >fp_status))) {
 /* sNaN addition */
-fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
 }
 farg1.d = float64_add(farg1.d, farg2.d, >fp_status);
 }
@@ -556,12 +556,12 @@ uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, 
uint64_t arg2)
 if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) 
&&
  float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
 /* Magnitude subtraction of infinities */
-farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
 } else {
 if (unlikely(float64_is_signaling_nan(farg1.d, >fp_status) ||
  float64_is_signaling_nan(farg2.d, >fp_status))) {
 /* sNaN subtraction */
-fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
 }
 farg1.d = float64_sub(farg1.d, farg2.d, >fp_status);
 }
@@ -580,12 +580,12 @@ uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, 
uint64_t arg2)
 if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
  (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d {
 /* Multiplication of zero by infinity */
-farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
+farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
 } else {
 if (unlikely(float64_is_signaling_nan(farg1.d, >fp_status) ||
  float64_is_signaling_nan(farg2.d, >fp_status))) {
 /* sNaN multiplication */
-fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
 }
 farg1.d = float64_mul(farg1.d, farg2.d, >fp_status);
 }
@@ -604,15 +604,15 @@ uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, 
uint64_t arg2)
 if (unlikely(float64_is_infinity(farg1.d) &&
  float64_is_infinity(farg2.d))) {
 /* Division of infinity by infinity */
-farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
+farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
 } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) 
{
 /* Division of zero by zero */
-farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
+farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
 } else {
 if (unlikely(float64_is_signaling_nan(farg1.d, >fp_status) ||
  float64_is_signaling_nan(farg2.d, >fp_status))) {
 /* sNaN division */
-fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
 }
 farg1.d = float64_div(farg1.d, farg2.d, >fp_status);
 }
@@ -631,14 +631,14 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)  
 \
\
 if (unlikely(env->fp_status.float_exception_flags)) {  \
 if (float64_is_any_nan(arg)) { \
-fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);  \
+float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);  \
 if (float64_is_signaling_nan(arg, >fp_status)) {  \
-fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 

[Qemu-devel] [PATCH 06/32] ppc: Move VMX ops out of translate.c

2016-07-26 Thread Benjamin Herrenschmidt
Makes things a bit more manageable

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c  | 1069 +--
 target-ppc/translate/vmx-impl.c |  829 ++
 target-ppc/translate/vmx-ops.c  |  246 +
 3 files changed, 1078 insertions(+), 1066 deletions(-)
 create mode 100644 target-ppc/translate/vmx-impl.c
 create mode 100644 target-ppc/translate/vmx-ops.c

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index ee45673..421fd98 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -5005,6 +5005,8 @@ static void gen_rfsvc(DisasContext *ctx)
 
 #include "translate/fp-impl.c"
 
+#include "translate/vmx-impl.c"
+
 /* svc is not implemented for now */
 
 /* BookE specific instructions */
@@ -5769,812 +5771,6 @@ static void gen_msgsnd(DisasContext *ctx)
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
-/***  Altivec vector extension ***/
-/* Altivec registers moves */
-
-static inline TCGv_ptr gen_avr_ptr(int reg)
-{
-TCGv_ptr r = tcg_temp_new_ptr();
-tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
-return r;
-}
-
-#define GEN_VR_LDX(name, opc2, opc3)  \
-static void glue(gen_, name)(DisasContext *ctx)
   \
-{ \
-TCGv EA;  \
-if (unlikely(!ctx->altivec_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_VPU); \
-return;   \
-} \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-gen_addr_reg_index(ctx, EA);  \
-tcg_gen_andi_tl(EA, EA, ~0xf);\
-/* We only need to swap high and low halves. gen_qemu_ld64 does necessary \
-   64-bit byteswap already. */\
-if (ctx->le_mode) {   \
-gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);\
-tcg_gen_addi_tl(EA, EA, 8);   \
-gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);\
-} else {  \
-gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);\
-tcg_gen_addi_tl(EA, EA, 8);   \
-gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);\
-} \
-tcg_temp_free(EA);\
-}
-
-#define GEN_VR_STX(name, opc2, opc3)  \
-static void gen_st##name(DisasContext *ctx)   \
-{ \
-TCGv EA;  \
-if (unlikely(!ctx->altivec_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_VPU); \
-return;   \
-} \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-gen_addr_reg_index(ctx, EA);  \
-tcg_gen_andi_tl(EA, EA, ~0xf);\
-/* We only need to swap high and low halves. gen_qemu_st64 does necessary \
-   64-bit byteswap already. */\
-if (ctx->le_mode) {   \
-gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);\
-tcg_gen_addi_tl(EA, EA, 8);   \
-gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);\
-} else {  \
-gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);\
-tcg_gen_addi_tl(EA, EA, 8);   \
-gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);\
-}  

[Qemu-devel] [PATCH 07/32] ppc: Move VSX ops out of translate.c

2016-07-26 Thread Benjamin Herrenschmidt
Makes things a bit more manageable

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c  | 994 +---
 target-ppc/translate/vsx-impl.c | 721 +
 target-ppc/translate/vsx-ops.c  | 271 +++
 3 files changed, 995 insertions(+), 991 deletions(-)
 create mode 100644 target-ppc/translate/vsx-impl.c
 create mode 100644 target-ppc/translate/vsx-ops.c

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 421fd98..cb4e313 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -5007,6 +5007,8 @@ static void gen_rfsvc(DisasContext *ctx)
 
 #include "translate/vmx-impl.c"
 
+#include "translate/vsx-impl.c"
+
 /* svc is not implemented for now */
 
 /* BookE specific instructions */
@@ -5771,721 +5773,6 @@ static void gen_msgsnd(DisasContext *ctx)
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
-/***   VSX extension   ***/
-
-static inline TCGv_i64 cpu_vsrh(int n)
-{
-if (n < 32) {
-return cpu_fpr[n];
-} else {
-return cpu_avrh[n-32];
-}
-}
-
-static inline TCGv_i64 cpu_vsrl(int n)
-{
-if (n < 32) {
-return cpu_vsr[n];
-} else {
-return cpu_avrl[n-32];
-}
-}
-
-#define VSX_LOAD_SCALAR(name, operation)  \
-static void gen_##name(DisasContext *ctx) \
-{ \
-TCGv EA;  \
-if (unlikely(!ctx->vsx_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_VSXU);\
-return;   \
-} \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-gen_addr_reg_index(ctx, EA);  \
-gen_qemu_##operation(ctx, cpu_vsrh(xT(ctx->opcode)), EA); \
-/* NOTE: cpu_vsrl is undefined */ \
-tcg_temp_free(EA);\
-}
-
-VSX_LOAD_SCALAR(lxsdx, ld64)
-VSX_LOAD_SCALAR(lxsiwax, ld32s_i64)
-VSX_LOAD_SCALAR(lxsiwzx, ld32u_i64)
-VSX_LOAD_SCALAR(lxsspx, ld32fs)
-
-static void gen_lxvd2x(DisasContext *ctx)
-{
-TCGv EA;
-if (unlikely(!ctx->vsx_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_VSXU);
-return;
-}
-gen_set_access_type(ctx, ACCESS_INT);
-EA = tcg_temp_new();
-gen_addr_reg_index(ctx, EA);
-gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
-tcg_gen_addi_tl(EA, EA, 8);
-gen_qemu_ld64(ctx, cpu_vsrl(xT(ctx->opcode)), EA);
-tcg_temp_free(EA);
-}
-
-static void gen_lxvdsx(DisasContext *ctx)
-{
-TCGv EA;
-if (unlikely(!ctx->vsx_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_VSXU);
-return;
-}
-gen_set_access_type(ctx, ACCESS_INT);
-EA = tcg_temp_new();
-gen_addr_reg_index(ctx, EA);
-gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
-tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
-tcg_temp_free(EA);
-}
-
-static void gen_lxvw4x(DisasContext *ctx)
-{
-TCGv EA;
-TCGv_i64 tmp;
-TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
-TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
-if (unlikely(!ctx->vsx_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_VSXU);
-return;
-}
-gen_set_access_type(ctx, ACCESS_INT);
-EA = tcg_temp_new();
-tmp = tcg_temp_new_i64();
-
-gen_addr_reg_index(ctx, EA);
-gen_qemu_ld32u_i64(ctx, tmp, EA);
-tcg_gen_addi_tl(EA, EA, 4);
-gen_qemu_ld32u_i64(ctx, xth, EA);
-tcg_gen_deposit_i64(xth, xth, tmp, 32, 32);
-
-tcg_gen_addi_tl(EA, EA, 4);
-gen_qemu_ld32u_i64(ctx, tmp, EA);
-tcg_gen_addi_tl(EA, EA, 4);
-gen_qemu_ld32u_i64(ctx, xtl, EA);
-tcg_gen_deposit_i64(xtl, xtl, tmp, 32, 32);
-
-tcg_temp_free(EA);
-tcg_temp_free_i64(tmp);
-}
-
-#define VSX_STORE_SCALAR(name, operation) \
-static void gen_##name(DisasContext *ctx) \
-{ \
-TCGv EA;  \
-if (unlikely(!ctx->vsx_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_VSXU);\
-return;   \
-} \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-gen_addr_reg_index(ctx, EA);  \
-gen_qemu_##operation(ctx, cpu_vsrh(xS(ctx->opcode)), EA); \
-tcg_temp_free(EA);\
-}
-
-VSX_STORE_SCALAR(stxsdx, st64)
-VSX_STORE_SCALAR(stxsiwx, 

[Qemu-devel] [PATCH 03/32] ppc: Move classic fp ops out of translate.c

2016-07-26 Thread Benjamin Herrenschmidt
Makes things a bit more manageable

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c | 1205 +---
 target-ppc/translate/fp-impl.c | 1098 
 target-ppc/translate/fp-ops.c  |  111 
 3 files changed, 1213 insertions(+), 1201 deletions(-)
 create mode 100644 target-ppc/translate/fp-impl.c
 create mode 100644 target-ppc/translate/fp-ops.c

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 92030b6..e42f576 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -250,17 +250,6 @@ struct opc_handler_t {
 #endif
 };
 
-static inline void gen_reset_fpstatus(void)
-{
-gen_helper_reset_fpstatus(cpu_env);
-}
-
-static inline void gen_compute_fprf(TCGv_i64 arg)
-{
-gen_helper_compute_fprf(cpu_env, arg);
-gen_helper_float_check_status(cpu_env);
-}
-
 static inline void gen_set_access_type(DisasContext *ctx, int access_type)
 {
 if (ctx->access_type != access_type) {
@@ -2126,602 +2115,6 @@ static void gen_srd(DisasContext *ctx)
 }
 #endif
 
-#if defined(TARGET_PPC64)
-static void gen_set_cr1_from_fpscr(DisasContext *ctx)
-{
-TCGv_i32 tmp = tcg_temp_new_i32();
-tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
-tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
-tcg_temp_free_i32(tmp);
-}
-#else
-static void gen_set_cr1_from_fpscr(DisasContext *ctx)
-{
-tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
-}
-#endif
-
-/***   Floating-Point arithmetic   ***/
-#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)   \
-static void gen_f##name(DisasContext *ctx)\
-{ \
-if (unlikely(!ctx->fpu_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_FPU); \
-return;   \
-} \
-/* NIP cannot be restored if the memory exception comes from an helper */ \
-gen_update_nip(ctx, ctx->nip - 4);\
-gen_reset_fpstatus(); \
-gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,   \
- cpu_fpr[rA(ctx->opcode)],\
- cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
-if (isfloat) {\
-gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,\
-cpu_fpr[rD(ctx->opcode)]);\
-} \
-if (set_fprf) {   \
-gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);   \
-} \
-if (unlikely(Rc(ctx->opcode) != 0)) { \
-gen_set_cr1_from_fpscr(ctx);  \
-} \
-}
-
-#define GEN_FLOAT_ACB(name, op2, set_fprf, type)  \
-_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
-_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
-
-#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
-static void gen_f##name(DisasContext *ctx)\
-{ \
-if (unlikely(!ctx->fpu_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_FPU); \
-return;   \
-} \
-/* NIP cannot be restored if the memory exception comes from an helper */ \
-gen_update_nip(ctx, ctx->nip - 4);\
-gen_reset_fpstatus(); \
-gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,   \
- cpu_fpr[rA(ctx->opcode)],\
- cpu_fpr[rB(ctx->opcode)]);   \
-if (isfloat) {\
-gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,\
-cpu_fpr[rD(ctx->opcode)]);\
-}

[Qemu-devel] [PATCH 11/32] ppc: Don't update the NIP in floating point generated code

2016-07-26 Thread Benjamin Herrenschmidt
This is no longer necessary as the helpers will properly retrieve
the return address.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate/fp-impl.c  | 28 
 target-ppc/translate/vsx-impl.c |  6 --
 2 files changed, 34 deletions(-)

diff --git a/target-ppc/translate/fp-impl.c b/target-ppc/translate/fp-impl.c
index 2abc386..9ba9289 100644
--- a/target-ppc/translate/fp-impl.c
+++ b/target-ppc/translate/fp-impl.c
@@ -38,8 +38,6 @@ static void gen_f##name(DisasContext *ctx)
\
 gen_exception(ctx, POWERPC_EXCP_FPU); \
 return;   \
 } \
-/* NIP cannot be restored if the memory exception comes from an helper */ \
-gen_update_nip(ctx, ctx->nip - 4);\
 gen_reset_fpstatus(); \
 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,   \
  cpu_fpr[rA(ctx->opcode)],\
@@ -67,8 +65,6 @@ static void gen_f##name(DisasContext *ctx)
\
 gen_exception(ctx, POWERPC_EXCP_FPU); \
 return;   \
 } \
-/* NIP cannot be restored if the memory exception comes from an helper */ \
-gen_update_nip(ctx, ctx->nip - 4);\
 gen_reset_fpstatus(); \
 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,   \
  cpu_fpr[rA(ctx->opcode)],\
@@ -95,8 +91,6 @@ static void gen_f##name(DisasContext *ctx)
\
 gen_exception(ctx, POWERPC_EXCP_FPU); \
 return;   \
 } \
-/* NIP cannot be restored if the memory exception comes from an helper */ \
-gen_update_nip(ctx, ctx->nip - 4);\
 gen_reset_fpstatus(); \
 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,   \
  cpu_fpr[rA(ctx->opcode)],\
@@ -123,8 +117,6 @@ static void gen_f##name(DisasContext *ctx)  
  \
 gen_exception(ctx, POWERPC_EXCP_FPU); \
 return;   \
 } \
-/* NIP cannot be restored if the memory exception comes from an helper */ \
-gen_update_nip(ctx, ctx->nip - 4);\
 gen_reset_fpstatus(); \
 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
cpu_fpr[rB(ctx->opcode)]); \
@@ -143,8 +135,6 @@ static void gen_f##name(DisasContext *ctx)  
  \
 gen_exception(ctx, POWERPC_EXCP_FPU); \
 return;   \
 } \
-/* NIP cannot be restored if the memory exception comes from an helper */ \
-gen_update_nip(ctx, ctx->nip - 4);\
 gen_reset_fpstatus(); \
 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
cpu_fpr[rB(ctx->opcode)]); \
@@ -179,8 +169,6 @@ static void gen_frsqrtes(DisasContext *ctx)
 gen_exception(ctx, POWERPC_EXCP_FPU);
 return;
 }
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_reset_fpstatus();
 gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
cpu_fpr[rB(ctx->opcode)]);
@@ -205,8 +193,6 @@ static void gen_fsqrt(DisasContext *ctx)
 gen_exception(ctx, POWERPC_EXCP_FPU);
 return;
 }
-/* NIP cannot be restored if the memory exception comes from an helper */
-gen_update_nip(ctx, ctx->nip - 4);
 gen_reset_fpstatus();
 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
  cpu_fpr[rB(ctx->opcode)]);

[Qemu-devel] [PATCH 13/32] ppc: Don't update NIP in lswi/lswx/stswi/stswx

2016-07-26 Thread Benjamin Herrenschmidt
Instead, pass GETPC() result to the corresponding helpers. This
requires a bit of fiddling to get the PC (hopefully) right in
the case where we generate a program check, though the hacks there
are temporary, a subsequent patch will clean this all up by always
having the nip already set to the right instruction when taking
the fault.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/excp_helper.c |  8 
 target-ppc/mem_helper.c  | 26 --
 target-ppc/translate.c   | 18 --
 3 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 91fdf4b..563c7bc 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -285,6 +285,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
 msr |= 0x0008;
 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
+/* Some invalids will have the PC in the right place already */
+if (env->error_code & POWERPC_EXCP_INVAL_LSWX) {
+goto store_next;
+}
 break;
 case POWERPC_EXCP_PRIV:
 msr |= 0x0004;
@@ -306,6 +310,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 srr1 = SPR_HSRR1;
 new_msr |= (target_ulong)MSR_HVB;
 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
+/* Some invalids will have the PC in the right place already */
+if (env->error_code == (POWERPC_EXCP_INVAL|POWERPC_EXCP_INVAL_LSWX)) {
+goto store_next;
+}
 goto store_current;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 goto store_current;
diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index e4ed377..de96c91 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -77,23 +77,30 @@ void helper_stmw(CPUPPCState *env, target_ulong addr, 
uint32_t reg)
 }
 }
 
-void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t reg)
+static void do_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb,
+   uint32_t reg, uintptr_t raddr)
 {
 int sh;
 
 for (; nb > 3; nb -= 4) {
-env->gpr[reg] = cpu_ldl_data(env, addr);
+env->gpr[reg] = cpu_ldl_data_ra(env, addr, raddr);
 reg = (reg + 1) % 32;
 addr = addr_add(env, addr, 4);
 }
 if (unlikely(nb > 0)) {
 env->gpr[reg] = 0;
 for (sh = 24; nb > 0; nb--, sh -= 8) {
-env->gpr[reg] |= cpu_ldub_data(env, addr) << sh;
+env->gpr[reg] |= cpu_ldub_data_ra(env, addr, raddr) << sh;
 addr = addr_add(env, addr, 1);
 }
 }
 }
+
+void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t reg)
+{
+do_lsw(env, addr, nb, reg, GETPC());
+}
+
 /* PPC32 specification says we must generate an exception if
  * rA is in the range of registers to be loaded.
  * In an other hand, IBM says this is valid, but rA won't be loaded.
@@ -106,12 +113,11 @@ void helper_lswx(CPUPPCState *env, target_ulong addr, 
uint32_t reg,
 int num_used_regs = (xer_bc + 3) / 4;
 if (unlikely((ra != 0 && lsw_reg_in_range(reg, num_used_regs, ra)) ||
  lsw_reg_in_range(reg, num_used_regs, rb))) {
-env->nip += 4; /* Compensate the "nip - 4" from gen_lswx() */
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_INVAL |
-   POWERPC_EXCP_INVAL_LSWX);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_INVAL |
+   POWERPC_EXCP_INVAL_LSWX, GETPC());
 } else {
-helper_lsw(env, addr, xer_bc, reg);
+do_lsw(env, addr, xer_bc, reg, GETPC());
 }
 }
 }
@@ -122,13 +128,13 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, 
uint32_t nb,
 int sh;
 
 for (; nb > 3; nb -= 4) {
-cpu_stl_data(env, addr, env->gpr[reg]);
+cpu_stl_data_ra(env, addr, env->gpr[reg], GETPC());
 reg = (reg + 1) % 32;
 addr = addr_add(env, addr, 4);
 }
 if (unlikely(nb > 0)) {
 for (sh = 24; nb > 0; nb--, sh -= 8) {
-cpu_stb_data(env, addr, (env->gpr[reg] >> sh) & 0xFF);
+cpu_stb_data_ra(env, addr, (env->gpr[reg] >> sh) & 0xFF, GETPC());
 addr = addr_add(env, addr, 1);
 }
 }
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index a05fed7..9d2e923 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2701,12 +2701,16 @@ static void gen_lswi(DisasContext *ctx)
 nb = 32;
 nr = (nb + 3) / 4;
 if (unlikely(lsw_reg_in_range(start, nr, ra))) {
+/* The 

[Qemu-devel] [PATCH 10/32] ppc: Make float_check_status() pass the return address

2016-07-26 Thread Benjamin Herrenschmidt
Instead of relying on NIP having been updated already.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/fpu_helper.c | 63 +
 1 file changed, 38 insertions(+), 25 deletions(-)

diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 8d881fc..7bab3ff 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -209,7 +209,7 @@ static inline uint64_t float_invalid_op_excp(CPUPPCState 
*env, int op,
 return ret;
 }
 
-static inline void float_zero_divide_excp(CPUPPCState *env)
+static inline void float_zero_divide_excp(CPUPPCState *env, uintptr_t raddr)
 {
 env->fpscr |= 1 << FPSCR_ZX;
 env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
@@ -219,8 +219,9 @@ static inline void float_zero_divide_excp(CPUPPCState *env)
 /* Update the floating-point enabled exception summary */
 env->fpscr |= 1 << FPSCR_FEX;
 if (msr_fe0 != 0 || msr_fe1 != 0) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX,
+   raddr);
 }
 }
 }
@@ -493,13 +494,14 @@ void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t 
mask)
 helper_store_fpscr(env, arg, mask);
 }
 
-void helper_float_check_status(CPUPPCState *env)
+static __attribute__((noinline)) void do_float_check_status(CPUPPCState *env,
+uintptr_t raddr)
 {
 CPUState *cs = CPU(ppc_env_get_cpu(env));
 int status = get_float_exception_flags(>fp_status);
 
 if (status & float_flag_divbyzero) {
-float_zero_divide_excp(env);
+float_zero_divide_excp(env, raddr);
 } else if (status & float_flag_overflow) {
 float_overflow_excp(env);
 } else if (status & float_flag_underflow) {
@@ -512,12 +514,23 @@ void helper_float_check_status(CPUPPCState *env)
 (env->error_code & POWERPC_EXCP_FP)) {
 /* Differred floating-point exception after target FPR update */
 if (msr_fe0 != 0 || msr_fe1 != 0) {
-helper_raise_exception_err(env, cs->exception_index,
-   env->error_code);
+raise_exception_err_ra(env, cs->exception_index,
+   env->error_code, raddr);
 }
 }
 }
 
+static inline void float_check_status(CPUPPCState *env)
+{
+/* GETPC() works here because this is inline */
+do_float_check_status(env, GETPC());
+}
+
+void helper_float_check_status(CPUPPCState *env)
+{
+do_float_check_status(env, GETPC());
+}
+
 void helper_reset_fpstatus(CPUPPCState *env)
 {
 set_float_exception_flags(0, >fp_status);
@@ -642,7 +655,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)
   \
float_flag_invalid) {   \
 float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);  \
 }  \
-helper_float_check_status(env);\
+float_check_status(env);   \
 }  \
 return farg.ll;\
  }
@@ -667,7 +680,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)   \
 } else {   \
 farg.d = cvtr(arg, >fp_status);   \
 }  \
-helper_float_check_status(env);\
+float_check_status(env);   \
 return farg.ll;\
 }
 
@@ -700,7 +713,7 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t 
arg,
 env->fp_status.float_exception_flags &= ~float_flag_inexact;
 }
 }
-helper_float_check_status(env);
+float_check_status(env);
 return farg.ll;
 }
 
@@ -1856,7 +1869,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) 
   \
 }\
 }\
 putVSR(xT(opcode), , env);\
-helper_float_check_status(env);  \
+float_check_status(env); \
 }
 
 VSX_ADD_SUB(xsadddp, add, 1, float64, VsrD(0), 1, 0)
@@ -1912,7 +1925,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)   
   \
 }\

[Qemu-devel] [PATCH 04/32] ppc: Move embedded spe ops out of translate.c

2016-07-26 Thread Benjamin Herrenschmidt
Makes things a bit more manageable

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c  | 1328 +--
 target-ppc/translate/spe-impl.c | 1229 
 target-ppc/translate/spe-ops.c  |  106 
 3 files changed, 1337 insertions(+), 1326 deletions(-)
 create mode 100644 target-ppc/translate/spe-impl.c
 create mode 100644 target-ppc/translate/spe-ops.c

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index e42f576..3b96bed 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -7495,1226 +7495,7 @@ GEN_DFP_T_FPR_I32_Rc(dscliq, rA, DCM)
 GEN_DFP_T_FPR_I32_Rc(dscri, rA, DCM)
 GEN_DFP_T_FPR_I32_Rc(dscriq, rA, DCM)
 
-/***   SPE extension   ***/
-/* Register moves */
-
-static inline void gen_evmra(DisasContext *ctx)
-{
-
-if (unlikely(!ctx->spe_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_SPEU);
-return;
-}
-
-TCGv_i64 tmp = tcg_temp_new_i64();
-
-/* tmp := rA_lo + rA_hi << 32 */
-tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)], 
cpu_gprh[rA(ctx->opcode)]);
-
-/* spe_acc := tmp */
-tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
-tcg_temp_free_i64(tmp);
-
-/* rD := rA */
-tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
-tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
-}
-
-static inline void gen_load_gpr64(TCGv_i64 t, int reg)
-{
-tcg_gen_concat_tl_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
-}
-
-static inline void gen_store_gpr64(int reg, TCGv_i64 t)
-{
-tcg_gen_extr_i64_tl(cpu_gpr[reg], cpu_gprh[reg], t);
-}
-
-#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
-static void glue(gen_, name0##_##name1)(DisasContext *ctx)\
-{ \
-if (Rc(ctx->opcode))  \
-gen_##name1(ctx); \
-else  \
-gen_##name0(ctx); \
-}
-
-/* Handler for undefined SPE opcodes */
-static inline void gen_speundef(DisasContext *ctx)
-{
-gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
-}
-
-/* SPE logic */
-#define GEN_SPEOP_LOGIC2(name, tcg_op)\
-static inline void gen_##name(DisasContext *ctx)  \
-{ \
-if (unlikely(!ctx->spe_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_SPEU);\
-return;   \
-} \
-tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],\
-   cpu_gpr[rB(ctx->opcode)]); \
-tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],  \
-   cpu_gprh[rB(ctx->opcode)]);\
-}
-
-GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
-GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
-GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
-GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
-GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
-GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
-GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
-GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
-
-/* SPE logic immediate */
-#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)   \
-static inline void gen_##name(DisasContext *ctx)  \
-{ \
-TCGv_i32 t0;  \
-if (unlikely(!ctx->spe_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_SPEU);\
-return;   \
-} \
-t0 = tcg_temp_new_i32();  \
-  \
-tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);   \
-tcg_opi(t0, t0, rB(ctx->opcode)); \
-tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);\
-  \
-tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]);  \
-tcg_opi(t0, t0, 

[Qemu-devel] [PATCH 15/32] ppc: Make tlb_fill() use new exception helper

2016-07-26 Thread Benjamin Herrenschmidt
Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/mmu_helper.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 3eb3cd7..80cc262 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -2892,10 +2892,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, 
MMUAccessType access_type,
 ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
 }
 if (unlikely(ret != 0)) {
-if (likely(retaddr)) {
-/* now we have a real cpu fault */
-cpu_restore_state(cs, retaddr);
-}
-helper_raise_exception_err(env, cs->exception_index, env->error_code);
+raise_exception_err_ra(env, cs->exception_index, env->error_code,
+   retaddr);
 }
 }
-- 
2.7.4




[Qemu-devel] [PATCH 09/32] ppc: Make float_invalid_op_excp() pass the return address

2016-07-26 Thread Benjamin Herrenschmidt
Instead of relying on NIP having been updated already

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/fpu_helper.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index e1f600a..8d881fc 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -19,6 +19,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/exec-all.h"
 
 #define float64_snan_to_qnan(x) ((x) | 0x0008ULL)
 #define float32_snan_to_qnan(x) ((x) | 0x0040)
@@ -200,8 +201,9 @@ static inline uint64_t float_invalid_op_excp(CPUPPCState 
*env, int op,
 /* Update the floating-point enabled exception summary */
 env->fpscr |= 1 << FPSCR_FEX;
 if (msr_fe0 != 0 || msr_fe1 != 0) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_FP | op);
+/* GETPC() works here because this is inline */
+raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+   POWERPC_EXCP_FP | op, GETPC());
 }
 }
 return ret;
-- 
2.7.4




[Qemu-devel] [PATCH 02/32] ppc: Provide basic raise_exception_* functions

2016-07-26 Thread Benjamin Herrenschmidt
Instead of using the same helpers called from translate.c, let's have
a bunch of functions that take the various argument combinations,
especially the retaddr which will be needed in subsequent patches,
and leave the helpers to be just that, helpers for translate.c

We don't yet convert all users, we'll go through them in subsequent
patches.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/cpu.h |  8 
 target-ppc/excp_helper.c | 51 
 2 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 5fce1ff..2ee7a5e 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2295,6 +2295,14 @@ static inline void cpu_get_tb_cpu_state(CPUPPCState 
*env, target_ulong *pc,
 *flags = env->hflags;
 }
 
+void QEMU_NORETURN raise_exception(CPUPPCState *env, uint32_t exception);
+void QEMU_NORETURN raise_exception_ra(CPUPPCState *env, uint32_t exception,
+  uintptr_t raddr);
+void QEMU_NORETURN raise_exception_err(CPUPPCState *env, uint32_t exception,
+   uint32_t error_code);
+void QEMU_NORETURN raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
+  uint32_t error_code, uintptr_t 
raddr);
+
 #if !defined(CONFIG_USER_ONLY)
 static inline int booke206_tlbm_id(CPUPPCState *env, ppcmas_tlb_t *tlbm)
 {
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index d6e1678..f4b115e 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -898,34 +898,53 @@ static void cpu_dump_rfi(target_ulong RA, target_ulong 
msr)
 /*/
 /* Exceptions processing helpers */
 
-void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
-uint32_t error_code)
+void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
+uint32_t error_code, uintptr_t raddr)
 {
 CPUState *cs = CPU(ppc_env_get_cpu(env));
 
-#if 0
-printf("Raise exception %3x code : %d\n", exception, error_code);
-#endif
 cs->exception_index = exception;
 env->error_code = error_code;
-cpu_loop_exit(cs);
+cpu_loop_exit_restore(cs, raddr);
+}
+
+void raise_exception_err(CPUPPCState *env, uint32_t exception,
+ uint32_t error_code)
+{
+raise_exception_err_ra(env, exception, error_code, 0);
+}
+
+void raise_exception(CPUPPCState *env, uint32_t exception)
+{
+raise_exception_err_ra(env, exception, 0, 0);
+}
+
+void raise_exception_ra(CPUPPCState *env, uint32_t exception,
+uintptr_t raddr)
+{
+raise_exception_err_ra(env, exception, 0, 0);
+}
+
+void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
+uint32_t error_code)
+{
+raise_exception_err_ra(env, exception, error_code, 0);
 }
 
 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
 {
-helper_raise_exception_err(env, exception, 0);
+raise_exception_err_ra(env, exception, 0, 0);
 }
 
 #if !defined(CONFIG_USER_ONLY)
 void helper_store_msr(CPUPPCState *env, target_ulong val)
 {
-CPUState *cs;
+uint32_t excp = hreg_store_msr(env, val, 0);
 
-val = hreg_store_msr(env, val, 0);
-if (val != 0) {
-cs = CPU(ppc_env_get_cpu(env));
+if (excp != 0) {
+CPUState *cs = CPU(ppc_env_get_cpu(env));
 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
-helper_raise_exception(env, val);
+raise_exception(env, excp);
 }
 }
 
@@ -951,7 +970,7 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
  * but this doesn't seem to be a problem.
  */
 env->msr |= (1ull << MSR_EE);
-helper_raise_exception(env, EXCP_HLT);
+raise_exception(env, EXCP_HLT);
 }
 #endif /* defined(TARGET_PPC64) */
 
@@ -1041,8 +1060,7 @@ void helper_tw(CPUPPCState *env, target_ulong arg1, 
target_ulong arg2,
   ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
   ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
   ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_TRAP);
+raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
 }
 }
 
@@ -1055,8 +1073,7 @@ void helper_td(CPUPPCState *env, target_ulong arg1, 
target_ulong arg2,
   ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
   ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
   ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01) {
-helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-   POWERPC_EXCP_TRAP);
+raise_exception_err(env, POWERPC_EXCP_PROGRAM, 

[Qemu-devel] [PATCH 01/32] ppc: Fix fault PC reporting for lve*/stve* VMX instructions

2016-07-26 Thread Benjamin Herrenschmidt
We forgot to do gen_update_nip() for these like we do with other
helpers. Fix this, but in a more efficient way by passing the RA
to the accessors instead so the overhead is only taken on faults.

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/mem_helper.c | 21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index e4de86b..e4ed377 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -232,16 +232,16 @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong 
addr, uint32_t reg,
 \
 if (needs_byteswap(env)) {  \
 r->element[LO_IDX ? index : (adjust - index)] = \
-swap(access(env, addr));\
+swap(access(env, addr, GETPC()));   \
 } else {\
 r->element[LO_IDX ? index : (adjust - index)] = \
-access(env, addr);  \
+access(env, addr, GETPC()); \
 }   \
 }
 #define I(x) (x)
-LVE(lvebx, cpu_ldub_data, I, u8)
-LVE(lvehx, cpu_lduw_data, bswap16, u16)
-LVE(lvewx, cpu_ldl_data, bswap32, u32)
+LVE(lvebx, cpu_ldub_data_ra, I, u8)
+LVE(lvehx, cpu_lduw_data_ra, bswap16, u16)
+LVE(lvewx, cpu_ldl_data_ra, bswap32, u32)
 #undef I
 #undef LVE
 
@@ -259,16 +259,17 @@ LVE(lvewx, cpu_ldl_data, bswap32, u32)
 \
 if (needs_byteswap(env)) {  \
 access(env, addr, swap(r->element[LO_IDX ? index :  \
-  (adjust - index)]));  \
+  (adjust - index)]),   \
+GETPC());   \
 } else {\
 access(env, addr, r->element[LO_IDX ? index :   \
- (adjust - index)]);\
+ (adjust - index)], GETPC());   \
 }   \
 }
 #define I(x) (x)
-STVE(stvebx, cpu_stb_data, I, u8)
-STVE(stvehx, cpu_stw_data, bswap16, u16)
-STVE(stvewx, cpu_stl_data, bswap32, u32)
+STVE(stvebx, cpu_stb_data_ra, I, u8)
+STVE(stvehx, cpu_stw_data_ra, bswap16, u16)
+STVE(stvewx, cpu_stl_data_ra, bswap32, u32)
 #undef I
 #undef LVE
 
-- 
2.7.4




[Qemu-devel] [PATCH 05/32] ppc: Move DFP ops out of translate.c

2016-07-26 Thread Benjamin Herrenschmidt
Makes things a bit more manageable

Signed-off-by: Benjamin Herrenschmidt 
---
 target-ppc/translate.c  | 365 +---
 target-ppc/translate/dfp-impl.c | 212 +++
 target-ppc/translate/dfp-ops.c  | 151 +
 3 files changed, 365 insertions(+), 363 deletions(-)
 create mode 100644 target-ppc/translate/dfp-impl.c
 create mode 100644 target-ppc/translate/dfp-ops.c

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3b96bed..ee45673 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -7290,210 +7290,7 @@ static void gen_xxsldwi(DisasContext *ctx)
 tcg_temp_free_i64(xtl);
 }
 
-/*** Decimal Floating Point ***/
-
-static inline TCGv_ptr gen_fprp_ptr(int reg)
-{
-TCGv_ptr r = tcg_temp_new_ptr();
-tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, fpr[reg]));
-return r;
-}
-
-#define GEN_DFP_T_A_B_Rc(name)   \
-static void gen_##name(DisasContext *ctx)\
-{\
-TCGv_ptr rd, ra, rb; \
-if (unlikely(!ctx->fpu_enabled)) {   \
-gen_exception(ctx, POWERPC_EXCP_FPU);\
-return;  \
-}\
-gen_update_nip(ctx, ctx->nip - 4);   \
-rd = gen_fprp_ptr(rD(ctx->opcode));  \
-ra = gen_fprp_ptr(rA(ctx->opcode));  \
-rb = gen_fprp_ptr(rB(ctx->opcode));  \
-gen_helper_##name(cpu_env, rd, ra, rb);  \
-if (unlikely(Rc(ctx->opcode) != 0)) {\
-gen_set_cr1_from_fpscr(ctx); \
-}\
-tcg_temp_free_ptr(rd);   \
-tcg_temp_free_ptr(ra);   \
-tcg_temp_free_ptr(rb);   \
-}
-
-#define GEN_DFP_BF_A_B(name)  \
-static void gen_##name(DisasContext *ctx) \
-{ \
-TCGv_ptr ra, rb;  \
-if (unlikely(!ctx->fpu_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_FPU); \
-return;   \
-} \
-gen_update_nip(ctx, ctx->nip - 4);\
-ra = gen_fprp_ptr(rA(ctx->opcode));   \
-rb = gen_fprp_ptr(rB(ctx->opcode));   \
-gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
-  cpu_env, ra, rb);   \
-tcg_temp_free_ptr(ra);\
-tcg_temp_free_ptr(rb);\
-}
-
-#define GEN_DFP_BF_A_DCM(name)\
-static void gen_##name(DisasContext *ctx) \
-{ \
-TCGv_ptr ra;  \
-TCGv_i32 dcm; \
-if (unlikely(!ctx->fpu_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_FPU); \
-return;   \
-} \
-gen_update_nip(ctx, ctx->nip - 4);\
-ra = gen_fprp_ptr(rA(ctx->opcode));   \
-dcm = tcg_const_i32(DCM(ctx->opcode));\
-gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
-  cpu_env, ra, dcm);  \
-tcg_temp_free_ptr(ra);\
-tcg_temp_free_i32(dcm);   \
-}
-
-#define GEN_DFP_T_B_U32_U32_Rc(name, u32f1, u32f2)\
-static void gen_##name(DisasContext *ctx) \
-{ \
-TCGv_ptr rt, rb;  \
-TCGv_i32 u32_1, u32_2;\
-if (unlikely(!ctx->fpu_enabled)) {\
-gen_exception(ctx, POWERPC_EXCP_FPU); \
-return;   \
-} \
-gen_update_nip(ctx, ctx->nip - 4);\
-rt = gen_fprp_ptr(rD(ctx->opcode));   \
-rb = gen_fprp_ptr(rB(ctx->opcode));   \
-u32_1 = tcg_const_i32(u32f1(ctx->opcode));\
-u32_2 = tcg_const_i32(u32f2(ctx->opcode));\
-gen_helper_##name(cpu_env, rt, rb, u32_1, u32_2); \
-if (unlikely(Rc(ctx->opcode) != 0)) { \
-gen_set_cr1_from_fpscr(ctx);  \
-} \
-tcg_temp_free_ptr(rt);\
-tcg_temp_free_ptr(rb);\
-tcg_temp_free_i32(u32_1); \
-tcg_temp_free_i32(u32_2); \
-}
-
-#define GEN_DFP_T_A_B_I32_Rc(name, i32fld)   \
-static void gen_##name(DisasContext *ctx)\
-{\
-TCGv_ptr 

[Qemu-devel] [PATCH for-2.7 0/1] ide: fix halted IO segfault at reset

2016-07-26 Thread John Snow


For convenience, this branch is available at:
https://github.com/jnsnow/qemu.git branch ide-reset-segfault
https://github.com/jnsnow/qemu/tree/ide-reset-segfault

This version is tagged ide-reset-segfault-v1:
https://github.com/jnsnow/qemu/releases/tag/ide-reset-segfault-v1

John Snow (1):
  ide: fix halted IO segfault at reset

 hw/ide/core.c | 1 +
 1 file changed, 1 insertion(+)

-- 
2.7.4




[Qemu-devel] [PATCH for-2.7 1/1] ide: fix halted IO segfault at reset

2016-07-26 Thread John Snow
If one attempts to perform a system_reset after a failed IO request
that causes the VM to enter a paused state, QEMU will segfault trying
to free up the pending IO requests.

These requests have already been completed and freed, though, so all
we need to do is free them before we enter the paused state.

Existing AHCI tests verify that halted requests are still resumed
successfully after a STOP event.

Signed-off-by: John Snow 
---
 hw/ide/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 081c9eb..d117b7c 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -823,6 +823,7 @@ static void ide_dma_cb(void *opaque, int ret)
 }
 if (ret < 0) {
 if (ide_handle_rw_error(s, -ret, ide_dma_cmd_to_retry(s->dma_cmd))) {
+s->bus->dma->aiocb = NULL;
 return;
 }
 }
-- 
2.7.4




[Qemu-devel] [Bug 1606708] [NEW] QEMU crashes when switching consoles using SDL

2016-07-26 Thread José Miguel
Public bug reported:

I've trying to use QEMU with SDL, and I noticed that it doesn't behave
well, specially when switching from VGA to any console. Resuming,
switching is erratic when using SDL, and its effects go from creating a
new window, doing nothing, showing a window that disappears inmediately
or even crash.

Tested with:
Arch Linux with all packages updated (2016/7/26)
TWM as window manager
QEMU (both stable 2.6.0-1 and latest git commit f49ee63)
Command: qemu-system-x86_64 -display sdl

sdl2 version 2.0.4-2

How to reproduce:
1. Open QEMU with the given command
2. Try to switch console (Ctrl-Alt-2 for example)

Expected behaviour:
As in GTK, the window should now show the desired console

Actual behaviour:
Here I have to say I can't explain it very well. Almost always it just creates 
a new window that shows the desired console, but it is closed inmediatley. If 
not, it opens a new window that keeps open, and it sometimes is responsive, but 
further attempts to switch consoles end causing a crash, and QEMU has to be 
SIGKILLed

** Affects: qemu
 Importance: Undecided
 Status: New

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1606708

Title:
  QEMU crashes when switching consoles using SDL

Status in QEMU:
  New

Bug description:
  I've trying to use QEMU with SDL, and I noticed that it doesn't behave
  well, specially when switching from VGA to any console. Resuming,
  switching is erratic when using SDL, and its effects go from creating
  a new window, doing nothing, showing a window that disappears
  inmediately or even crash.

  Tested with:
  Arch Linux with all packages updated (2016/7/26)
  TWM as window manager
  QEMU (both stable 2.6.0-1 and latest git commit f49ee63)
  Command: qemu-system-x86_64 -display sdl

  sdl2 version 2.0.4-2

  How to reproduce:
  1. Open QEMU with the given command
  2. Try to switch console (Ctrl-Alt-2 for example)

  Expected behaviour:
  As in GTK, the window should now show the desired console

  Actual behaviour:
  Here I have to say I can't explain it very well. Almost always it just 
creates a new window that shows the desired console, but it is closed 
inmediatley. If not, it opens a new window that keeps open, and it sometimes is 
responsive, but further attempts to switch consoles end causing a crash, and 
QEMU has to be SIGKILLed

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1606708/+subscriptions



[Qemu-devel] [PATCH v6 33/33] RFC: vhost: do not update last avail idx on get_vring_base() failure

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

The state.num value will probably be 0 in this case, but I guess that
doesn't make sense to update.

Signed-off-by: Marc-André Lureau 
---
 hw/virtio/vhost.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index b0e8ecc..3d0c807 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -945,8 +945,9 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
 r = dev->vhost_ops->vhost_get_vring_base(dev, );
 if (r < 0) {
 VHOST_OPS_DEBUG("vhost VQ %d ring restore failed: %d", idx, r);
+} else {
+virtio_queue_set_last_avail_idx(vdev, idx, state.num);
 }
-virtio_queue_set_last_avail_idx(vdev, idx, state.num);
 virtio_queue_invalidate_signalled_used(vdev, idx);
 
 /* In the cross-endian case, we need to reset the vring endianness to
-- 
2.9.0




[Qemu-devel] [PATCH v6 32/33] vhost-user-test: add flags mismatch test

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Check that qemu disconnects the backend that doesn't have the previously
acked features.

Signed-off-by: Marc-André Lureau 
---
 tests/vhost-user-test.c | 59 -
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 9c1438d..8e2b63c 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -126,6 +126,13 @@ static VhostUserMsg m __attribute__ ((unused));
 #define VHOST_USER_VERSION(0x1)
 /*/
 
+enum {
+TEST_FLAGS_OK,
+TEST_FLAGS_DISCONNECT,
+TEST_FLAGS_BAD,
+TEST_FLAGS_END,
+};
+
 typedef struct TestServer {
 gchar *socket_path;
 gchar *mig_path;
@@ -139,6 +146,7 @@ typedef struct TestServer {
 int log_fd;
 uint64_t rings;
 bool test_fail;
+int test_flags;
 int queues;
 } TestServer;
 
@@ -264,6 +272,10 @@ static void chr_read(void *opaque, const uint8_t *buf, int 
size)
 if (s->queues > 1) {
 msg.payload.u64 |= 0x1ULL << VIRTIO_NET_F_MQ;
 }
+if (s->test_flags >= TEST_FLAGS_BAD) {
+msg.payload.u64 = 0;
+s->test_flags = TEST_FLAGS_END;
+}
 p = (uint8_t *) 
 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
 break;
@@ -271,6 +283,10 @@ static void chr_read(void *opaque, const uint8_t *buf, int 
size)
 case VHOST_USER_SET_FEATURES:
g_assert_cmpint(msg.payload.u64 & (0x1ULL << 
VHOST_USER_F_PROTOCOL_FEATURES),
!=, 0ULL);
+if (s->test_flags == TEST_FLAGS_DISCONNECT) {
+qemu_chr_disconnect(chr);
+s->test_flags = TEST_FLAGS_BAD;
+}
 break;
 
 case VHOST_USER_GET_PROTOCOL_FEATURES:
@@ -396,6 +412,16 @@ static TestServer *test_server_new(const gchar *name)
 return server;
 }
 
+static void chr_event(void *opaque, int event)
+{
+TestServer *s = opaque;
+
+if (s->test_flags == TEST_FLAGS_END &&
+event == CHR_EVENT_CLOSED) {
+s->test_flags = TEST_FLAGS_OK;
+}
+}
+
 static void test_server_create_chr(TestServer *server, const gchar *opt)
 {
 gchar *chr_path;
@@ -404,7 +430,8 @@ static void test_server_create_chr(TestServer *server, 
const gchar *opt)
 server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
 g_free(chr_path);
 
-qemu_chr_add_handlers(server->chr, chr_can_read, chr_read, NULL, server);
+qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
+  chr_event, server);
 }
 
 static void test_server_listen(TestServer *server)
@@ -743,6 +770,33 @@ static void test_connect_fail(void)
 g_free(path);
 }
 
+static void test_flags_mismatch_subprocess(void)
+{
+TestServer *s = test_server_new("flags-mismatch");
+char *cmd;
+
+s->test_flags = TEST_FLAGS_DISCONNECT;
+g_thread_new("connect", connect_thread, s);
+cmd = GET_QEMU_CMDE(s, 2, ",server", "");
+qtest_start(cmd);
+g_free(cmd);
+
+wait_for_fds(s);
+wait_for_rings_started(s, 2);
+
+qtest_end();
+test_server_free(s);
+}
+
+static void test_flags_mismatch(void)
+{
+gchar *path = g_strdup_printf("/%s/vhost-user/flags-mismatch/subprocess",
+  qtest_get_arch());
+g_test_trap_subprocess(path, 0, 0);
+g_test_trap_assert_passed();
+g_free(path);
+}
+
 #endif
 
 static QVirtioPCIDevice *virtio_net_pci_init(QPCIBus *bus, int slot)
@@ -877,6 +931,9 @@ int main(int argc, char **argv)
 qtest_add_func("/vhost-user/connect-fail/subprocess",
test_connect_fail_subprocess);
 qtest_add_func("/vhost-user/connect-fail", test_connect_fail);
+qtest_add_func("/vhost-user/flags-mismatch/subprocess",
+   test_flags_mismatch_subprocess);
+qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch);
 #endif
 
 ret = g_test_run();
-- 
2.9.0




[Qemu-devel] [PATCH v6 31/33] vhost: add vhost_net_set_backend()

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Not all vhost-user backends support ops->vhost_net_set_backend(). It is
a nicer to provide an assert/error than to crash trying to
call. Furthermore, it improves a bit the code by hiding vhost_ops
details.

Signed-off-by: Marc-André Lureau 
---
 hw/net/vhost_net.c|  9 +++--
 hw/virtio/vhost.c | 10 ++
 include/hw/virtio/vhost.h |  4 
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index dd41a8e..dc61dc1 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -242,8 +242,7 @@ static int vhost_net_start_one(struct vhost_net *net,
 qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
 file.fd = net->backend;
 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
-const VhostOps *vhost_ops = net->dev.vhost_ops;
-r = vhost_ops->vhost_net_set_backend(>dev, );
+r = vhost_net_set_backend(>dev, );
 if (r < 0) {
 r = -errno;
 goto fail;
@@ -255,8 +254,7 @@ fail:
 file.fd = -1;
 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
 while (file.index-- > 0) {
-const VhostOps *vhost_ops = net->dev.vhost_ops;
-int r = vhost_ops->vhost_net_set_backend(>dev, );
+int r = vhost_net_set_backend(>dev, );
 assert(r >= 0);
 }
 }
@@ -277,8 +275,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
 
 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
-const VhostOps *vhost_ops = net->dev.vhost_ops;
-int r = vhost_ops->vhost_net_set_backend(>dev, );
+int r = vhost_net_set_backend(>dev, );
 assert(r >= 0);
 }
 }
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 2d0d1d1..b0e8ecc 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1369,3 +1369,13 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice 
*vdev)
 vhost_log_put(hdev, true);
 hdev->started = false;
 }
+
+int vhost_net_set_backend(struct vhost_dev *hdev,
+  struct vhost_vring_file *file)
+{
+if (hdev->vhost_ops->vhost_net_set_backend) {
+return hdev->vhost_ops->vhost_net_set_backend(hdev, file);
+}
+
+return -1;
+}
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 2106ed8..e433089 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -86,4 +86,8 @@ uint64_t vhost_get_features(struct vhost_dev *hdev, const int 
*feature_bits,
 void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
 uint64_t features);
 bool vhost_has_free_slot(void);
+
+int vhost_net_set_backend(struct vhost_dev *hdev,
+  struct vhost_vring_file *file);
+
 #endif
-- 
2.9.0




[Qemu-devel] [PATCH v6 30/33] vhost-user: add error report in vhost_user_write()

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Similar to vhost_user_read() error report, it is useful to have early
error report.

Signed-off-by: Marc-André Lureau 
---
 hw/virtio/vhost-user.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 819481d..1995fd2 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -176,7 +176,7 @@ static int vhost_user_write(struct vhost_dev *dev, 
VhostUserMsg *msg,
 int *fds, int fd_num)
 {
 CharDriverState *chr = dev->opaque;
-int size = VHOST_USER_HDR_SIZE + msg->size;
+int ret, size = VHOST_USER_HDR_SIZE + msg->size;
 
 /*
  * For non-vring specific requests, like VHOST_USER_SET_MEM_TABLE,
@@ -188,11 +188,18 @@ static int vhost_user_write(struct vhost_dev *dev, 
VhostUserMsg *msg,
 }
 
 if (qemu_chr_fe_set_msgfds(chr, fds, fd_num) < 0) {
+error_report("Failed to set msg fds.");
 return -1;
 }
 
-return qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size) == size ?
-0 : -1;
+ret = qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size);
+if (ret != size) {
+error_report("Failed to write msg."
+ " Wrote %d instead of %d.", ret, size);
+return -1;
+}
+
+return 0;
 }
 
 static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
-- 
2.9.0




[Qemu-devel] [PATCH v6 26/33] tests: plug some leaks in virtio-net-test

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Found thanks to valgrind.

Signed-off-by: Marc-André Lureau 
---
 tests/virtio-net-test.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
index a34a939..361506f 100644
--- a/tests/virtio-net-test.c
+++ b/tests/virtio-net-test.c
@@ -149,6 +149,7 @@ static void rx_stop_cont_test(const QVirtioBus *bus, 
QVirtioDevice *dev,
 char test[] = "TEST";
 char buffer[64];
 int len = htonl(sizeof(test));
+QDict *rsp;
 struct iovec iov[] = {
 {
 .iov_base = ,
@@ -165,7 +166,8 @@ static void rx_stop_cont_test(const QVirtioBus *bus, 
QVirtioDevice *dev,
 free_head = qvirtqueue_add(vq, req_addr, 64, true, false);
 qvirtqueue_kick(bus, dev, vq, free_head);
 
-qmp("{ 'execute' : 'stop'}");
+rsp = qmp("{ 'execute' : 'stop'}");
+QDECREF(rsp);
 
 ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
 g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len));
@@ -173,8 +175,10 @@ static void rx_stop_cont_test(const QVirtioBus *bus, 
QVirtioDevice *dev,
 /* We could check the status, but this command is more importantly to
  * ensure the packet data gets queued in QEMU, before we do 'cont'.
  */
-qmp("{ 'execute' : 'query-status'}");
-qmp("{ 'execute' : 'cont'}");
+rsp = qmp("{ 'execute' : 'query-status'}");
+QDECREF(rsp);
+rsp = qmp("{ 'execute' : 'cont'}");
+QDECREF(rsp);
 
 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_NET_TIMEOUT_US);
 memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
@@ -230,8 +234,10 @@ static void pci_basic(gconstpointer data)
 /* End test */
 close(sv[0]);
 qvirtqueue_cleanup(_pci, >vq, alloc);
+qvirtqueue_cleanup(_pci, >vq, alloc);
 pc_alloc_uninit(alloc);
 qvirtio_pci_device_disable(dev);
+g_free(dev->pdev);
 g_free(dev);
 qpci_free_pc(bus);
 test_end();
-- 
2.9.0




[Qemu-devel] [PATCH v6 28/33] tests: add /vhost-user/connect-fail test

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Check early connection failure and resume.

Signed-off-by: Marc-André Lureau 
---
 tests/vhost-user-test.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 27b10c1..2db8f3d 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -131,6 +131,7 @@ typedef struct TestServer {
 CompatGCond data_cond;
 int log_fd;
 uint64_t rings;
+bool test_fail;
 } TestServer;
 
 static const char *tmpfs;
@@ -221,6 +222,12 @@ static void chr_read(void *opaque, const uint8_t *buf, int 
size)
 uint8_t *p = (uint8_t *) 
 int fd;
 
+if (s->test_fail) {
+qemu_chr_disconnect(chr);
+/* now switch to non-failure */
+s->test_fail = false;
+}
+
 if (size != VHOST_USER_HDR_SIZE) {
 g_test_message("Wrong message size received %d\n", size);
 return;
@@ -685,6 +692,34 @@ static void test_reconnect(void)
 g_test_trap_assert_passed();
 g_free(path);
 }
+
+static void test_connect_fail_subprocess(void)
+{
+TestServer *s = test_server_new("connect-fail");
+char *cmd;
+
+s->test_fail = true;
+g_thread_new("connect", connect_thread, s);
+cmd = GET_QEMU_CMDE(s, 2, ",server", "");
+qtest_start(cmd);
+g_free(cmd);
+
+wait_for_fds(s);
+wait_for_rings_started(s, 2);
+
+qtest_end();
+test_server_free(s);
+}
+
+static void test_connect_fail(void)
+{
+gchar *path = g_strdup_printf("/%s/vhost-user/connect-fail/subprocess",
+  qtest_get_arch());
+g_test_trap_subprocess(path, 0, 0);
+g_test_trap_assert_passed();
+g_free(path);
+}
+
 #endif
 
 int main(int argc, char **argv)
@@ -735,6 +770,9 @@ int main(int argc, char **argv)
 qtest_add_func("/vhost-user/reconnect/subprocess",
test_reconnect_subprocess);
 qtest_add_func("/vhost-user/reconnect", test_reconnect);
+qtest_add_func("/vhost-user/connect-fail/subprocess",
+   test_connect_fail_subprocess);
+qtest_add_func("/vhost-user/connect-fail", test_connect_fail);
 #endif
 
 ret = g_test_run();
-- 
2.9.0




[Qemu-devel] [PATCH v6 24/33] char: add and use tcp_chr_wait_connected

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Add a chr_wait_connected for the tcp backend, and use it in the
open_socket() function.

Signed-off-by: Marc-André Lureau 
---
 qemu-char.c | 63 ++---
 1 file changed, 44 insertions(+), 19 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 6eba615..a50b8fb 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3139,6 +3139,32 @@ static gboolean tcp_chr_accept(QIOChannel *channel,
 return TRUE;
 }
 
+static int tcp_chr_wait_connected(CharDriverState *chr, Error **errp)
+{
+TCPCharDriver *s = chr->opaque;
+QIOChannelSocket *sioc;
+
+while (!s->connected) {
+if (s->is_listen) {
+fprintf(stderr, "QEMU waiting for connection on: %s\n",
+chr->filename);
+qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), true, NULL);
+tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
+qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
+} else {
+sioc = qio_channel_socket_new();
+if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
+object_unref(OBJECT(sioc));
+return -1;
+}
+tcp_chr_new_client(chr, sioc);
+object_unref(OBJECT(sioc));
+}
+}
+
+return 0;
+}
+
 int qemu_chr_wait_connected(CharDriverState *chr, Error **errp)
 {
 if (chr->chr_wait_connected) {
@@ -4402,6 +4428,7 @@ static CharDriverState *qmp_chardev_open_socket(const 
char *id,
 s->addr = QAPI_CLONE(SocketAddress, sock->addr);
 
 chr->opaque = s;
+chr->chr_wait_connected = tcp_chr_wait_connected;
 chr->chr_write = tcp_chr_write;
 chr->chr_sync_read = tcp_chr_sync_read;
 chr->chr_close = tcp_chr_close;
@@ -4425,32 +4452,30 @@ static CharDriverState *qmp_chardev_open_socket(const 
char *id,
 s->reconnect_time = reconnect;
 }
 
-sioc = qio_channel_socket_new();
 if (s->reconnect_time) {
+sioc = qio_channel_socket_new();
 qio_channel_socket_connect_async(sioc, s->addr,
  qemu_chr_socket_connected,
  chr, NULL);
-} else if (s->is_listen) {
-if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
-goto error;
-}
-s->listen_ioc = sioc;
-if (is_waitconnect) {
-fprintf(stderr, "QEMU waiting for connection on: %s\n",
-chr->filename);
-tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
-}
-qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
-if (!s->ioc) {
-s->listen_tag = qio_channel_add_watch(
-QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, 
NULL);
-}
 } else {
-if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
+if (s->is_listen) {
+sioc = qio_channel_socket_new();
+if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
+goto error;
+}
+s->listen_ioc = sioc;
+if (is_waitconnect &&
+qemu_chr_wait_connected(chr, errp) < 0) {
+goto error;
+}
+if (!s->ioc) {
+s->listen_tag = qio_channel_add_watch(
+QIO_CHANNEL(s->listen_ioc), G_IO_IN,
+tcp_chr_accept, chr, NULL);
+}
+} else if (qemu_chr_wait_connected(chr, errp) < 0) {
 goto error;
 }
-tcp_chr_new_client(chr, sioc);
-object_unref(OBJECT(sioc));
 }
 
 return chr;
-- 
2.9.0




[Qemu-devel] [PATCH v6 27/33] tests: fix vhost-user-test leak

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Spotted by valgrind.

Signed-off-by: Marc-André Lureau 
---
 tests/vhost-user-test.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 46d0588..27b10c1 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -683,6 +683,7 @@ static void test_reconnect(void)
   qtest_get_arch());
 g_test_trap_subprocess(path, 0, 0);
 g_test_trap_assert_passed();
+g_free(path);
 }
 #endif
 
-- 
2.9.0




[Qemu-devel] [PATCH v6 29/33] tests: add a simple /vhost-user/multiqueue test

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

This test just checks that 2 virtio-net queues can be setup over
vhost-user and waits for them to be started.

Signed-off-by: Marc-André Lureau 
---
 tests/Makefile.include  |   2 +-
 tests/vhost-user-test.c | 108 +++-
 2 files changed, 107 insertions(+), 3 deletions(-)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 9286148..a6ee20a 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -617,7 +617,7 @@ tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o 
$(libqos-usb-obj-y)
 tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
 tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o
 tests/postcopy-test$(EXESUF): tests/postcopy-test.o
-tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o 
qemu-timer.o $(qtest-obj-y) $(test-io-obj-y)
+tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o 
qemu-timer.o $(qtest-obj-y) $(test-io-obj-y) $(libqos-pc-obj-y) 
$(libqos-virtio-obj-y)
 tests/qemu-iotests/socket_scm_helper$(EXESUF): 
tests/qemu-iotests/socket_scm_helper.o
 tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y)
 tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o 
$(test-block-obj-y)
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 2db8f3d..9c1438d 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -17,6 +17,11 @@
 #include "sysemu/char.h"
 #include "sysemu/sysemu.h"
 
+#include "libqos/pci-pc.h"
+#include "libqos/virtio-pci.h"
+#include "libqos/malloc-pc.h"
+#include "hw/virtio/virtio-net.h"
+
 #include 
 #include 
 
@@ -46,6 +51,7 @@
 #define VHOST_MEMORY_MAX_NREGIONS8
 
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
+#define VHOST_USER_PROTOCOL_F_MQ 0
 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1
 
 #define VHOST_LOG_PAGE 0x1000
@@ -68,6 +74,7 @@ typedef enum VhostUserRequest {
 VHOST_USER_SET_VRING_ERR = 14,
 VHOST_USER_GET_PROTOCOL_FEATURES = 15,
 VHOST_USER_SET_PROTOCOL_FEATURES = 16,
+VHOST_USER_GET_QUEUE_NUM = 17,
 VHOST_USER_SET_VRING_ENABLE = 18,
 VHOST_USER_MAX
 } VhostUserRequest;
@@ -132,6 +139,7 @@ typedef struct TestServer {
 int log_fd;
 uint64_t rings;
 bool test_fail;
+int queues;
 } TestServer;
 
 static const char *tmpfs;
@@ -253,6 +261,9 @@ static void chr_read(void *opaque, const uint8_t *buf, int 
size)
 msg.size = sizeof(m.payload.u64);
 msg.payload.u64 = 0x1ULL << VHOST_F_LOG_ALL |
 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
+if (s->queues > 1) {
+msg.payload.u64 |= 0x1ULL << VIRTIO_NET_F_MQ;
+}
 p = (uint8_t *) 
 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
 break;
@@ -267,6 +278,9 @@ static void chr_read(void *opaque, const uint8_t *buf, int 
size)
 msg.flags |= VHOST_USER_REPLY_MASK;
 msg.size = sizeof(m.payload.u64);
 msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
+if (s->queues > 1) {
+msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ;
+}
 p = (uint8_t *) 
 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
 break;
@@ -279,7 +293,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int 
size)
 p = (uint8_t *) 
 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
 
-assert(msg.payload.state.index < 2);
+assert(msg.payload.state.index < s->queues * 2);
 s->rings &= ~(0x1ULL << msg.payload.state.index);
 break;
 
@@ -319,10 +333,18 @@ static void chr_read(void *opaque, const uint8_t *buf, 
int size)
 break;
 
 case VHOST_USER_SET_VRING_BASE:
-assert(msg.payload.state.index < 2);
+assert(msg.payload.state.index < s->queues * 2);
 s->rings |= 0x1ULL << msg.payload.state.index;
 break;
 
+case VHOST_USER_GET_QUEUE_NUM:
+msg.flags |= VHOST_USER_REPLY_MASK;
+msg.size = sizeof(m.payload.u64);
+msg.payload.u64 = s->queues;
+p = (uint8_t *) 
+qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
+break;
+
 default:
 break;
 }
@@ -369,6 +391,7 @@ static TestServer *test_server_new(const gchar *name)
 g_cond_init(>data_cond);
 
 server->log_fd = -1;
+server->queues = 1;
 
 return server;
 }
@@ -722,6 +745,86 @@ static void test_connect_fail(void)
 
 #endif
 
+static QVirtioPCIDevice *virtio_net_pci_init(QPCIBus *bus, int slot)
+{
+QVirtioPCIDevice *dev;
+
+dev = qvirtio_pci_device_find(bus, VIRTIO_ID_NET);
+g_assert(dev != NULL);
+g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_NET);
+
+qvirtio_pci_device_enable(dev);
+qvirtio_reset(_pci, >vdev);
+qvirtio_set_acknowledge(_pci, >vdev);
+qvirtio_set_driver(_pci, >vdev);
+
+return dev;
+}

[Qemu-devel] [PATCH v6 20/33] Revert "vhost-net: do not crash if backend is not present"

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Now that get_vhost_net() returns non-null after a successful
vhost_net_init(), we no longer need to check this case.

This reverts commit ecd34898596c60f79886061618dd7e01001113ad.

Signed-off-by: Marc-André Lureau 
---
 hw/net/vhost_net.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 4e6495e..54cf015 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -429,15 +429,10 @@ VHostNetState *get_vhost_net(NetClientState *nc)
 int vhost_set_vring_enable(NetClientState *nc, int enable)
 {
 VHostNetState *net = get_vhost_net(nc);
-const VhostOps *vhost_ops;
+const VhostOps *vhost_ops = net->dev.vhost_ops;
 
 nc->vring_enable = enable;
 
-if (!net) {
-return 0;
-}
-
-vhost_ops = net->dev.vhost_ops;
 if (vhost_ops->vhost_set_vring_enable) {
 return vhost_ops->vhost_set_vring_enable(>dev, enable);
 }
-- 
2.9.0




[Qemu-devel] [PATCH v6 23/33] char: add chr_wait_connected callback

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

A function to wait on the backend to be connected, to be used in the
following patches.

Signed-off-by: Marc-André Lureau 
---
 include/sysemu/char.h | 8 
 qemu-char.c   | 9 +
 2 files changed, 17 insertions(+)

diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 0ea9eac..ee7e554 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -70,6 +70,7 @@ struct CharDriverState {
 int (*get_msgfds)(struct CharDriverState *s, int* fds, int num);
 int (*set_msgfds)(struct CharDriverState *s, int *fds, int num);
 int (*chr_add_client)(struct CharDriverState *chr, int fd);
+int (*chr_wait_connected)(struct CharDriverState *chr, Error **errp);
 IOEventHandler *chr_event;
 IOCanReadHandler *chr_can_read;
 IOReadHandler *chr_read;
@@ -158,6 +159,13 @@ void qemu_chr_disconnect(CharDriverState *chr);
  */
 void qemu_chr_cleanup(void);
 
+/**
+ * @qemu_chr_wait_connected:
+ *
+ * Wait for characted backend to be connected.
+ */
+int qemu_chr_wait_connected(CharDriverState *chr, Error **errp);
+
 /**
  * @qemu_chr_new_noreplay:
  *
diff --git a/qemu-char.c b/qemu-char.c
index 1274f50..6eba615 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3139,6 +3139,15 @@ static gboolean tcp_chr_accept(QIOChannel *channel,
 return TRUE;
 }
 
+int qemu_chr_wait_connected(CharDriverState *chr, Error **errp)
+{
+if (chr->chr_wait_connected) {
+return chr->chr_wait_connected(chr, errp);
+}
+
+return 0;
+}
+
 static void tcp_chr_close(CharDriverState *chr)
 {
 TCPCharDriver *s = chr->opaque;
-- 
2.9.0




[Qemu-devel] [PATCH v6 19/33] vhost-user: add get_vhost_net() assertions

2016-07-26 Thread marcandre . lureau
From: Marc-André Lureau 

Add a few assertions to be more explicit about the runtime behaviour
after the previous patch: get_vhost_net() is non-null after
net_vhost_user_init().

Signed-off-by: Marc-André Lureau 
---
 hw/net/vhost_net.c | 1 +
 net/vhost-user.c   | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 7b76591..4e6495e 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -417,6 +417,7 @@ VHostNetState *get_vhost_net(NetClientState *nc)
 break;
 case NET_CLIENT_DRIVER_VHOST_USER:
 vhost_net = vhost_user_get_vhost_net(nc);
+assert(vhost_net);
 break;
 default:
 break;
diff --git a/net/vhost-user.c b/net/vhost-user.c
index d2a984d..39987a3 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -259,6 +259,8 @@ static int net_vhost_user_init(NetClientState *peer, const 
char *device,
 
 qemu_chr_add_handlers(chr, NULL, NULL, net_vhost_user_event, nc[0].name);
 
+assert(s->vhost_net);
+
 return 0;
 }
 
-- 
2.9.0




  1   2   3   4   >