[Qemu-devel] [PATCH] trace: Sort trace-events-subdirs

2018-05-27 Thread Philippe Mathieu-Daudé
Having these entries sorted helps to add new ones.

Signed-off-by: Philippe Mathieu-Daudé 
---
 Makefile.objs | 82 +--
 1 file changed, 41 insertions(+), 41 deletions(-)

diff --git a/Makefile.objs b/Makefile.objs
index c6c3554203..2c8cb72407 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -196,66 +196,66 @@ vhost-user-blk-obj-y = contrib/vhost-user-blk/
 
 ##
 trace-events-subdirs =
-trace-events-subdirs += util
-trace-events-subdirs += crypto
-trace-events-subdirs += io
-trace-events-subdirs += migration
+trace-events-subdirs += accel/kvm
+trace-events-subdirs += accel/tcg
+trace-events-subdirs += audio
 trace-events-subdirs += block
 trace-events-subdirs += chardev
+trace-events-subdirs += crypto
+trace-events-subdirs += hw/9pfs
+trace-events-subdirs += hw/acpi
+trace-events-subdirs += hw/alpha
+trace-events-subdirs += hw/arm
+trace-events-subdirs += hw/audio
 trace-events-subdirs += hw/block
 trace-events-subdirs += hw/block/dataplane
 trace-events-subdirs += hw/char
-trace-events-subdirs += hw/intc
-trace-events-subdirs += hw/net
-trace-events-subdirs += hw/rdma
-trace-events-subdirs += hw/rdma/vmw
-trace-events-subdirs += hw/virtio
-trace-events-subdirs += hw/audio
-trace-events-subdirs += hw/misc
-trace-events-subdirs += hw/misc/macio
-trace-events-subdirs += hw/usb
-trace-events-subdirs += hw/scsi
-trace-events-subdirs += hw/nvram
 trace-events-subdirs += hw/display
-trace-events-subdirs += hw/input
-trace-events-subdirs += hw/timer
 trace-events-subdirs += hw/dma
-trace-events-subdirs += hw/sparc
-trace-events-subdirs += hw/sparc64
-trace-events-subdirs += hw/sd
-trace-events-subdirs += hw/isa
-trace-events-subdirs += hw/mem
+trace-events-subdirs += hw/hppa
 trace-events-subdirs += hw/i386
 trace-events-subdirs += hw/i386/xen
-trace-events-subdirs += hw/9pfs
-trace-events-subdirs += hw/ppc
+trace-events-subdirs += hw/ide
+trace-events-subdirs += hw/input
+trace-events-subdirs += hw/intc
+trace-events-subdirs += hw/isa
+trace-events-subdirs += hw/mem
+trace-events-subdirs += hw/misc
+trace-events-subdirs += hw/misc/macio
+trace-events-subdirs += hw/net
+trace-events-subdirs += hw/nvram
 trace-events-subdirs += hw/pci
 trace-events-subdirs += hw/pci-host
+trace-events-subdirs += hw/ppc
+trace-events-subdirs += hw/rdma
+trace-events-subdirs += hw/rdma/vmw
 trace-events-subdirs += hw/s390x
+trace-events-subdirs += hw/scsi
+trace-events-subdirs += hw/sd
+trace-events-subdirs += hw/sparc
+trace-events-subdirs += hw/sparc64
+trace-events-subdirs += hw/timer
+trace-events-subdirs += hw/tpm
+trace-events-subdirs += hw/usb
 trace-events-subdirs += hw/vfio
-trace-events-subdirs += hw/acpi
-trace-events-subdirs += hw/arm
-trace-events-subdirs += hw/alpha
-trace-events-subdirs += hw/hppa
+trace-events-subdirs += hw/virtio
 trace-events-subdirs += hw/xen
-trace-events-subdirs += hw/ide
-trace-events-subdirs += hw/tpm
-trace-events-subdirs += ui
-trace-events-subdirs += audio
+trace-events-subdirs += io
+trace-events-subdirs += linux-user
+trace-events-subdirs += migration
+trace-events-subdirs += nbd
 trace-events-subdirs += net
+trace-events-subdirs += qapi
+trace-events-subdirs += qom
+trace-events-subdirs += scsi
 trace-events-subdirs += target/arm
 trace-events-subdirs += target/i386
 trace-events-subdirs += target/mips
-trace-events-subdirs += target/sparc
-trace-events-subdirs += target/s390x
 trace-events-subdirs += target/ppc
-trace-events-subdirs += qom
-trace-events-subdirs += linux-user
-trace-events-subdirs += qapi
-trace-events-subdirs += accel/tcg
-trace-events-subdirs += accel/kvm
-trace-events-subdirs += nbd
-trace-events-subdirs += scsi
+trace-events-subdirs += target/s390x
+trace-events-subdirs += target/sparc
+trace-events-subdirs += ui
+trace-events-subdirs += util
 
 trace-events-files = $(SRC_PATH)/trace-events 
$(trace-events-subdirs:%=$(SRC_PATH)/%/trace-events)
 
-- 
2.17.0




Re: [Qemu-devel] release retrospective, next release timing, numbering

2018-05-27 Thread Philippe Mathieu-Daudé
On 04/27/2018 12:51 PM, Peter Maydell wrote:
> Hi; I usually let people forget about releases for a month or
> so before bringing this topic up, but:
[...]
> That will make the next release be 3.0.0.
[...]
> (3) retrospective, lessons learned 
[...]
>  * provide your opinions here ?

Maybe v3 is a good opportunity to update QEMU standards...

- Clarify which APIs are outdated
  (Add /* DEPRECATED (use: NiceApi3.0) */ comments around)

- Select some up-to-date and recommended (well-documented)
  boards/device/block examples for newcomers (add in Wiki)

Some more painful ideas:

- Public function/structures added/modified get documentation
  (kernel-doc / Sphinx)

- New feature gets unit-qtesting (make check-unit)

- New device gets acceptance qtesting (make check-qtest)

- New board gets integration qtesting (boot BIOS/FW, Avocado)

I understand each maintainer manage his tree with his own criterion, IMO
these might be the minimum requested for paid contributors.

Regards,

Phil.



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH V5 0/9] nvdimm: guarantee persistence of QEMU writes to persistent memory

2018-05-27 Thread Junyan He
  GEN qemu-doc.html
  GEN qemu-doc.txt
  GEN qemu.1
  CC  s390-ccw/bootmap.o
  GEN docs/interop/qemu-qmp-ref.html
./qemu-options.texi:2855: unknown command `address'
./qemu-options.texi:2855: unknown command `hidden'
make: *** [Makefile:915: qemu-doc.html] Error 1



It seems that this is not caused by my patch set? And I can not duplicate in 
local.

Pings, thanks


From: Qemu-devel  on behalf of 
Junyan He 
Sent: Monday, May 21, 2018 3:19:48 AM
To: junyan...@gmx.com
Cc: Haozhong Zhang; xiaoguangrong.e...@gmail.com; crosthwaite.pe...@gmail.com; 
m...@redhat.com; qemu-devel@nongnu.org; dgilb...@redhat.com; 
quint...@redhat.com; Junyan He; stefa...@redhat.com; imamm...@redhat.com; 
pbonz...@redhat.com; r...@twiddle.net; ehabk...@redhat.com
Subject: Re: [Qemu-devel] [PATCH V5 0/9] nvdimm: guarantee persistence of QEMU 
writes to persistent memory

   Ping for review, thanks

   Sent: Thursday, May 10, 2018 at 10:08 AM
   From: junyan...@gmx.com
   To: qemu-devel@nongnu.org
   Cc: "Haozhong Zhang" ,
   xiaoguangrong.e...@gmail.com, crosthwaite.pe...@gmail.com,
   m...@redhat.com, dgilb...@redhat.com, ehabk...@redhat.com,
   quint...@redhat.com, "Junyan He" ,
   stefa...@redhat.com, pbonz...@redhat.com, imamm...@redhat.com,
   r...@twiddle.net
   Subject: [Qemu-devel] [PATCH V5 0/9] nvdimm: guarantee persistence of
   QEMU writes to persistent memory
   From: Junyan He 
   QEMU writes to vNVDIMM backends in the vNVDIMM label emulation and
   live migration. If the backend is on the persistent memory, QEMU needs
   to take proper operations to ensure its writes persistent on the
   persistent memory. Otherwise, a host power failure may result in the
   loss the guest data on the persistent memory.
   This v3 patch series is based on Marcel's patch "mem: add share
   parameter to memory-backend-ram" [1] because of the changes in patch 1.
   [1]
   [1]https://lists.gnu.org/archive/html/qemu-devel/2018-02/msg03858.html
   Previous versions can be found at
   V4:
   [2]https://lists.gnu.org/archive/html/qemu-devel/2018-02/msg06993.html
   v3:
   [3]https://lists.gnu.org/archive/html/qemu-devel/2018-02/msg04365.html
   v2:
   [4]https://lists.gnu.org/archive/html/qemu-devel/2018-02/msg01579.html
   v1:
   [5]https://lists.gnu.org/archive/html/qemu-devel/2017-12/msg05040.html
   Changes in v5:
   * (Patch 9) Add post copy check and output some messages for nvdimm.
   Changes in v4:
   * (Patch 2) Fix compilation errors found by patchew.
   Changes in v3:
   * (Patch 5) Add a is_pmem flag to ram_handle_compressed() and handle
   PMEM writes in it, so we don't need the _common function.
   * (Patch 6) Expose qemu_get_buffer_common so we can remove the
   unnecessary qemu_get_buffer_to_pmem wrapper.
   * (Patch 8) Add a is_pmem flag to xbzrle_decode_buffer() and handle
   PMEM writes in it, so we can remove the unnecessary
   xbzrle_decode_buffer_{common, to_pmem}.
   * Move libpmem stubs to stubs/pmem.c and fix the compilation failures
   of test-{xbzrle,vmstate}.c.
   Changes in v2:
   * (Patch 1) Use a flags parameter in file ram allocation functions.
   * (Patch 2) Add a new option 'pmem' to hostmem-file.
   * (Patch 3) Use libpmem to operate on the persistent memory, rather
   than re-implementing those operations in QEMU.
   * (Patch 5-8) Consider the write persistence in the migration path.
   Haozhong Zhang (8):
   [1/9] memory, exec: switch file ram allocation functions to 'flags'
   parameters
   [2/9] hostmem-file: add the 'pmem' option
   [3/9] configure: add libpmem support
   [4/9] mem/nvdimm: ensure write persistence to PMEM in label emulation
   [5/9] migration/ram: ensure write persistence on loading zero pages to
   PMEM
   [6/9] migration/ram: ensure write persistence on loading normal pages
   to PMEM
   [7/9] migration/ram: ensure write persistence on loading compressed
   pages to PMEM
   [8/9] migration/ram: ensure write persistence on loading xbzrle pages
   to PMEM
   Junyan He (1):
   [9/9] migration/ram: Add check and info message to nvdimm post copy.
   Signed-off-by: Haozhong Zhang 
   Signed-off-by: Junyan He 
   ---
   backends/hostmem-file.c | 27 ++-
   configure | 35 +++
   docs/nvdimm.txt | 14 ++
   exec.c | 20 
   hw/mem/nvdimm.c | 9 -
   include/exec/memory.h | 12 ++--
   include/exec/ram_addr.h | 28 ++--
   include/migration/qemu-file-types.h | 2 ++
   include/qemu/pmem.h | 27 +++
   memory.c | 8 +---
   migration/qemu-file.c | 29 +++--
   migration/ram.c | 52
   ++--
   migration/ram.h | 2 +-
   migration/rdma.c | 2 +-
   

Re: [Qemu-devel] [RFC PATCH] mmio-exec: Make device return MemoryRegion rather than host pointer

2018-05-27 Thread Cédric Le Goater
On 04/26/2018 05:09 PM, Peter Maydell wrote:
> Our current interface for allowing a device to support execution from
> MMIO regions has the device return a pointer into host memory
> containing the contents to be used for execution.  Unfortunately the
> obvious implementation this encourages (and which our only in-tree
> user uses) is to have a single buffer which is reused for each new
> request_ptr call.  This doesn't work, because RCU means that removal
> of the old RAMBlock based on the host pointer may be deferred until a
> point after a new RAMBlock with the same pointer has been added to
> the list.  The RAMBlock APIs assume that the host-pointer to ram_addr
> mapping is unique, and mmio-exec is breaking that assumption.

yes. I have run into the same problem while implementing mmio-exec 
for the aspeed fmc controllers. 

The FW (U-boot) in some configuration does a CRC calculation which 
jumps from one code section to another. This trashes the MMIO cache 
a very large number of times and the RAM block list can contain up 
to 40 occurrences of the same cache ... it is nearly impossible not 
to hit the bug you describe.

This patch fixes the issue but maybe an another approach could be to 
introduce a cache allocator which would make sure that host-pointers
are unique ?

Thanks,

C. 

> Instead, change the API so that the device is responsible for
> allocating a new RAM MemoryRegion and populating it.  The
> MemoryRegion will be g_free()d when the region is eventually
> invalidated or otherwise unneeded.
> 
> HACKS:
>  * Note that in order for the refcounting to work correctly without
>having to manufacture a device purely to be the owner of the
>MemoryRegion, we must pass OBJECT(newmr) as the owner (so the MR is
>its own owner!) and NULL as the name (or the property created on the
>owner causes the refcount to go negative during finalization)...
> 
> QUESTIONS:
>  * do we really need to postpone things from
>memory_region_invalidate_mmio_ptr() to
>memory_region_do_invalidate_mmio_ptr(), given that the deletion of
>the memory region and ramblock is RCU-deferred anyway?
>  * should we add the subregion at elevated prio so it definitely hits
>first?  I've left it the way the existing code does for the
>moment...
>  * is there any way to avoid the weird self-owning MemoryRegion
>and corresponding need to pass a NULL name pointer?
> 
> NOTES:
>  * This change means that hw/misc/mmio_interface.c is no longer
>used; if this gets beyond RFC stage then another patch to
>delete it can follow.
>  * The "request_mmio_exec mustn't fail after it has called
>memory_region_mmio_ptr_alloc()" requirement is a bit ugly, but
>could probably be removed.
> 
> Signed-off-by: Peter Maydell 
> ---
> This is decidedly RFC, but it is sufficient to get the xilinx-spips
> mmio-execution test case to run without crashing. Mostly looking for
> feedback on whether this is the right general direction or a load
> of rubbish :-)
> 
>  include/exec/memory.h | 44 
>  hw/ssi/xilinx_spips.c | 22 
>  memory.c  | 78 ---
>  3 files changed, 105 insertions(+), 39 deletions(-)
> 
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 31eae0a640..e55e06a166 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -139,14 +139,32 @@ struct MemoryRegionOps {
>  unsigned size,
>  MemTxAttrs attrs);
>  /* Instruction execution pre-callback:
> - * @addr is the address of the access relative to the @mr.
> - * @size is the size of the area returned by the callback.
> - * @offset is the location of the pointer inside @mr.
> + * @opaque is the opaque pointer for the MemoryRegion.
> + * @alloc_token is a token to pass to memory_region_mmio_ptr_alloc()
> + * @offset contains the address of the access relative to the @mr.
>   *
> - * Returns a pointer to a location which contains guest code.
> + * The request_mmio_exec callback must:
> + *  - adjust the offset downwards as desired and determine the size
> + *of the region it wants to provide cached guest code for.
> + *This must start on a guest page boundary and be a multiple
> + *of a guest page in size.
> + *  - call memory_region_mmio_ptr_alloc(@alloc_token, size)
> + *  - fill in the contents of the RAM
> + * Ownership of @newmr remains with the caller; it will be
> + * automatically freed when no longer in use.
> + *
> + * If the callback cannot satisfy the request then it should
> + * return false. Otherwise it must
> + *  - update @offset to the offset of the memory within the MemoryRegion
> + *this is a callback for (ie the possibly rounded down value)
> + *  - return true
> + * Note that if you return false then 

[Qemu-devel] What is the best git-way to add a new board?

2018-05-27 Thread Philippe Mathieu-Daudé
Hi,

What is the best git-way to add a new board?
Thinking about testing/review.

The following ways occurred to me:


1/ how RISC-V boards got merged

  Add devices individually,
  finally add the board and default-configs/Makefile rules at once.

PRO: commits are easier to cherry-pick/rebase
CON: you can not test a single patch until applying the whole series
 harder (less interest) to write qtests


1bis/ example of the Smartfusion2 board

  Variant of 1/, but also modify the default-configs/Makefile to
  build each device.

PRO: single patch can be test without much troubles,
 unit/acceptance tests can be run without applying the whole series,
 different people can work in parallel.
CON: no integration test until the last 'board' commit


2/ Reverse Polish testing

  Add a board stub (all devices as UnimplementedDevice) and Makefile
  rule, then for each new device, replace the unimp board entry,
modify the default-configs/Makefile,
add unit/acceptance tests

PRO: you can add an integration test since the first board commit :)
   (enforcing Test Driven Development),
 allow unpaid contributor to slowly push his work upstream
   instead of painful rebases or his work lost by change of
   interest or worth issues.
CON: not acceptable by upstream except with good integration test
 integration test might not be upstream-able due to license
   incompatibilities (JTAG-extracted firmwares...)

The use of UnimplementedDevice is now a bit enforced by the
ignore_memory_transaction_failures flag.


Regards,

Phil.



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] cmdline: How to connect a SD card to a specific SD controller?

2018-05-27 Thread Philippe Mathieu-Daudé
Hi,

I'd like to connect a specific SD card to a specific SDHCI from command
line, and I'm getting a bit lost with command line options.

I'm using an updated version of this patch, but this is not relevant to
this thread:
http://lists.nongnu.org/archive/html/qemu-devel/2018-05/msg01914.html

In the following example, I'd like to connect an UHS-I enabled SD card
to the first SHDCI of the Exynos4210 board (Nuri).

I tried:

$ ./arm-softmmu/qemu-system-arm -M nuri \
  -device sd-card,id=sd0,uhs=1 \
  -drive if=sd,id=sd0,driver=null-co,size=4G \
  -monitor stdio -S

But then the QTree looks unexpected:

(qemu) info qtree
bus: main-system-bus
  type System
  dev: generic-sdhci, id ""
gpio-out "sysbus-irq" 1
sd-spec-version = 2 (0x2)
uhs = 0 (0x0)
capareg = 99090560 (0x5e80080)
maxcurr = 0 (0x0)
pending-insert-quirk = false
dma = ""
mmio 1254/0100
bus: sd-bus
  type sdhci-bus
  dev: sd-card, id "sd0"
drive = ""
spi = false
uhs = 1 (0x1)
  dev: sd-card, id ""
drive = ""
spi = false
uhs = 0 (0x0)

  ^ 2 cards

  dev: generic-sdhci, id ""
gpio-out "sysbus-irq" 1
sd-spec-version = 2 (0x2)
uhs = 0 (0x0)
capareg = 99090560 (0x5e80080)
maxcurr = 0 (0x0)
pending-insert-quirk = false
dma = ""
mmio 1253/0100
bus: sd-bus
  type sdhci-bus
  dev: sd-card, id ""
drive = ""
spi = false
uhs = 0 (0x0)
  dev: generic-sdhci, id ""
gpio-out "sysbus-irq" 1
sd-spec-version = 2 (0x2)
uhs = 0 (0x0)
capareg = 99090560 (0x5e80080)
maxcurr = 0 (0x0)
pending-insert-quirk = false
dma = ""
mmio 1252/0100
bus: sd-bus
  type sdhci-bus
  dev: sd-card, id ""
drive = ""
spi = false
uhs = 0 (0x0)
  dev: generic-sdhci, id ""
gpio-out "sysbus-irq" 1
sd-spec-version = 2 (0x2)
uhs = 0 (0x0)
capareg = 99090560 (0x5e80080)
maxcurr = 0 (0x0)
pending-insert-quirk = false
dma = ""
mmio 1251/0100
bus: sd-bus
  type sdhci-bus
  dev: sd-card, id ""
drive = "sd0"

^--- drive is here

spi = false
uhs = 0 (0x0)

in hw/sd/core.c we have:

static SDState *get_card(SDBus *sdbus)
{
/* We only ever have one child on the bus so just return it */
BusChild *kid = QTAILQ_FIRST(>qbus.children);

if (!kid) {
return NULL;
}
return SD_CARD(kid->child);
}

Spec v1 allow multiple cards per bus but Spec v2 (and up) restrict to 1
per bus.


in exynos4210_init() we have:

di = drive_get(IF_SD, 0, n);
blk = di ? blk_by_legacy_dinfo(di) : NULL;
carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"),
TYPE_SD_CARD);

so there are no restriction in connecting various slaves to the same bus.

I also wonder about this drive_get(), is this an outdated API?

Only used in 3 boards:

$ git grep 'drive_get(IF_SD'
hw/arm/exynos4210.c:397:di = drive_get(IF_SD, 0, n);
hw/arm/omap1.c:3990:dinfo = drive_get(IF_SD, 0, 0);
hw/arm/omap2.c:2489:dinfo = drive_get(IF_SD, 0, 0);
hw/arm/pxa2xx.c:2098:dinfo = drive_get(IF_SD, 0, 0);
hw/arm/pxa2xx.c::dinfo = drive_get(IF_SD, 0, 0);

versus drive_get_next() used in others:

hw/arm/mcimx7d-sabre.c:70:di = drive_get_next(IF_SD);
hw/arm/raspi.c:200:di = drive_get_next(IF_SD);
hw/arm/xilinx_zynq.c:269:di = drive_get_next(IF_SD);
hw/arm/xlnx-zcu102.c:114:DriveInfo *di = drive_get_next(IF_SD);
hw/sd/milkymist-memcard.c:279:dinfo = drive_get_next(IF_SD);
hw/sd/pl181.c:508:dinfo = drive_get_next(IF_SD);
hw/sd/ssi-sd.c:254:dinfo = drive_get_next(IF_SD);

Now trying with the PC machine:

$ x86_64-softmmu/qemu-system-x86_64 -M pc \
  -device sdhci-pci,id=sdhci1 \
  -device sdhci-pci,id=sdhci2,sd-spec-version=3,uhs=2 \
  -device sd-card,id=sdcard0 \
  -device sd-card,uhs=1,id=sdcard1 \
  -monitor stdio -S

(qemu) info qtree
bus: main-system-bus
  type System
  dev: i440FX-pcihost, id ""
bus: pci.0
  type PCI
  dev: sdhci-pci, id "sdhci2"
sd-spec-version = 3 (0x3)
uhs = 2 (0x2)
capareg = 91763892 (0x57834b4)
maxcurr = 0 (0x0)
addr = 05.0
romfile = ""
rombar = 1 (0x1)
multifunction = false
command_serr_enable = true
x-pcie-lnksta-dllla = true
x-pcie-extcap-init = true
class Class 0805, addr 00:05.0, pci id 1b36:0007 (sub 1af4:1100)
bar 0: mem at 0x [0xfe]
bus: sd-bus
  type sdhci-bus
  dev: sd-card, id "sdcard1"
drive = ""
spi = false
uhs = 1 (0x1)
  dev: sd-card, id "sdcard0"
drive = ""
spi = false
uhs = 0 (0x0)

  ^--- 2 cards...

  dev: sdhci-pci, id "sdhci1"
sd-spec-version = 2 (0x2)

[Qemu-devel] [PATCH v6 08/10] iscsi: Implement copy offloading

2018-05-27 Thread Fam Zheng
Issue EXTENDED COPY (LID1) command to implement the copy_range API.

The parameter data construction code is modified from libiscsi's
iscsi-dd.c.

Signed-off-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
---
 block/iscsi.c| 219 +++
 include/scsi/constants.h |   3 +
 2 files changed, 222 insertions(+)

diff --git a/block/iscsi.c b/block/iscsi.c
index 6a365cb07b..5ea75646d9 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -2205,6 +2205,221 @@ static void coroutine_fn 
iscsi_co_invalidate_cache(BlockDriverState *bs,
 iscsi_allocmap_invalidate(iscsilun);
 }
 
+static int coroutine_fn iscsi_co_copy_range_from(BlockDriverState *bs,
+ BdrvChild *src,
+ uint64_t src_offset,
+ BdrvChild *dst,
+ uint64_t dst_offset,
+ uint64_t bytes,
+ BdrvRequestFlags flags)
+{
+return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, 
flags);
+}
+
+static struct scsi_task *iscsi_xcopy_task(int param_len)
+{
+struct scsi_task *task;
+
+task = g_new0(struct scsi_task, 1);
+
+task->cdb[0] = EXTENDED_COPY;
+task->cdb[10]= (param_len >> 24) & 0xFF;
+task->cdb[11]= (param_len >> 16) & 0xFF;
+task->cdb[12]= (param_len >> 8) & 0xFF;
+task->cdb[13]= param_len & 0xFF;
+task->cdb_size   = 16;
+task->xfer_dir   = SCSI_XFER_WRITE;
+task->expxferlen = param_len;
+
+return task;
+}
+
+static void iscsi_populate_target_desc(unsigned char *desc, IscsiLun *lun)
+{
+struct scsi_inquiry_device_designator *dd = lun->dd;
+
+memset(desc, 0, 32);
+desc[0] = IDENT_DESCR_TGT_DESCR;
+desc[4] = dd->code_set;
+desc[5] = (dd->designator_type & 0xF)
+| ((dd->association & 3) << 4);
+desc[7] = dd->designator_length;
+memcpy(desc + 8, dd->designator, dd->designator_length);
+
+desc[28] = 0;
+desc[29] = (lun->block_size >> 16) & 0xFF;
+desc[30] = (lun->block_size >> 8) & 0xFF;
+desc[31] = lun->block_size & 0xFF;
+}
+
+static void iscsi_xcopy_desc_hdr(uint8_t *hdr, int dc, int cat, int src_index,
+ int dst_index)
+{
+hdr[0] = 0x02; /* BLK_TO_BLK_SEG_DESCR */
+hdr[1] = ((dc << 1) | cat) & 0xFF;
+hdr[2] = (XCOPY_BLK2BLK_SEG_DESC_SIZE >> 8) & 0xFF;
+/* don't account for the first 4 bytes in descriptor header*/
+hdr[3] = (XCOPY_BLK2BLK_SEG_DESC_SIZE - 4 /* SEG_DESC_SRC_INDEX_OFFSET */) 
& 0xFF;
+hdr[4] = (src_index >> 8) & 0xFF;
+hdr[5] = src_index & 0xFF;
+hdr[6] = (dst_index >> 8) & 0xFF;
+hdr[7] = dst_index & 0xFF;
+}
+
+static void iscsi_xcopy_populate_desc(uint8_t *desc, int dc, int cat,
+  int src_index, int dst_index, int 
num_blks,
+  uint64_t src_lba, uint64_t dst_lba)
+{
+iscsi_xcopy_desc_hdr(desc, dc, cat, src_index, dst_index);
+
+/* The caller should verify the request size */
+assert(num_blks < 65536);
+desc[10] = (num_blks >> 8) & 0xFF;
+desc[11] = num_blks & 0xFF;
+desc[12] = (src_lba >> 56) & 0xFF;
+desc[13] = (src_lba >> 48) & 0xFF;
+desc[14] = (src_lba >> 40) & 0xFF;
+desc[15] = (src_lba >> 32) & 0xFF;
+desc[16] = (src_lba >> 24) & 0xFF;
+desc[17] = (src_lba >> 16) & 0xFF;
+desc[18] = (src_lba >> 8) & 0xFF;
+desc[19] = src_lba & 0xFF;
+desc[20] = (dst_lba >> 56) & 0xFF;
+desc[21] = (dst_lba >> 48) & 0xFF;
+desc[22] = (dst_lba >> 40) & 0xFF;
+desc[23] = (dst_lba >> 32) & 0xFF;
+desc[24] = (dst_lba >> 24) & 0xFF;
+desc[25] = (dst_lba >> 16) & 0xFF;
+desc[26] = (dst_lba >> 8) & 0xFF;
+desc[27] = dst_lba & 0xFF;
+}
+
+static void iscsi_xcopy_populate_header(unsigned char *buf, int list_id, int 
str,
+int list_id_usage, int prio,
+int tgt_desc_len,
+int seg_desc_len, int inline_data_len)
+{
+buf[0] = list_id;
+buf[1] = ((str & 1) << 5) | ((list_id_usage & 3) << 3) | (prio & 7);
+buf[2] = (tgt_desc_len >> 8) & 0xFF;
+buf[3] = tgt_desc_len & 0xFF;
+buf[8] = (seg_desc_len >> 24) & 0xFF;
+buf[9] = (seg_desc_len >> 16) & 0xFF;
+buf[10] = (seg_desc_len >> 8) & 0xFF;
+buf[11] = seg_desc_len & 0xFF;
+buf[12] = (inline_data_len >> 24) & 0xFF;
+buf[13] = (inline_data_len >> 16) & 0xFF;
+buf[14] = (inline_data_len >> 8) & 0xFF;
+buf[15] = inline_data_len & 0xFF;
+}
+
+static void iscsi_xcopy_data(struct iscsi_data *data,
+ IscsiLun *src, int64_t src_lba,
+ IscsiLun *dst, int64_t dst_lba,
+ 

[Qemu-devel] [PATCH v6 09/10] block-backend: Add blk_co_copy_range

2018-05-27 Thread Fam Zheng
It's a BlockBackend wrapper of the BDS interface.

Signed-off-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
---
 block/block-backend.c  | 18 ++
 include/sysemu/block-backend.h |  4 
 2 files changed, 22 insertions(+)

diff --git a/block/block-backend.c b/block/block-backend.c
index 89f47b00ea..d55c328736 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2211,3 +2211,21 @@ void blk_unregister_buf(BlockBackend *blk, void *host)
 {
 bdrv_unregister_buf(blk_bs(blk), host);
 }
+
+int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
+   BlockBackend *blk_out, int64_t off_out,
+   int bytes, BdrvRequestFlags flags)
+{
+int r;
+r = blk_check_byte_request(blk_in, off_in, bytes);
+if (r) {
+return r;
+}
+r = blk_check_byte_request(blk_out, off_out, bytes);
+if (r) {
+return r;
+}
+return bdrv_co_copy_range(blk_in->root, off_in,
+  blk_out->root, off_out,
+  bytes, flags);
+}
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 92ab624fac..8d03d493c2 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -232,4 +232,8 @@ void blk_set_force_allow_inactivate(BlockBackend *blk);
 void blk_register_buf(BlockBackend *blk, void *host, size_t size);
 void blk_unregister_buf(BlockBackend *blk, void *host);
 
+int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
+   BlockBackend *blk_out, int64_t off_out,
+   int bytes, BdrvRequestFlags flags);
+
 #endif
-- 
2.14.3




[Qemu-devel] [PATCH v6 04/10] qcow2: Implement copy offloading

2018-05-27 Thread Fam Zheng
The two callbacks are implemented quite similarly to the read/write
functions: bdrv_co_copy_range_from maps for read and calls into bs->file
or bs->backing depending on the allocation status; bdrv_co_copy_range_to
maps for write and calls into bs->file.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Fam Zheng 
---
 block/qcow2.c | 226 ++
 1 file changed, 196 insertions(+), 30 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 6d532470a8..e32a3c1518 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1762,6 +1762,39 @@ static int coroutine_fn 
qcow2_co_block_status(BlockDriverState *bs,
 return status;
 }
 
+static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
+QCowL2Meta **pl2meta,
+bool link_l2)
+{
+int ret = 0;
+QCowL2Meta *l2meta = *pl2meta;
+
+while (l2meta != NULL) {
+QCowL2Meta *next;
+
+if (!ret && link_l2) {
+ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
+if (ret) {
+goto out;
+}
+}
+
+/* Take the request off the list of running requests */
+if (l2meta->nb_clusters != 0) {
+QLIST_REMOVE(l2meta, next_in_flight);
+}
+
+qemu_co_queue_restart_all(>dependent_requests);
+
+next = l2meta->next;
+g_free(l2meta);
+l2meta = next;
+}
+out:
+*pl2meta = l2meta;
+return ret;
+}
+
 static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
 uint64_t bytes, QEMUIOVector *qiov,
 int flags)
@@ -2048,24 +2081,9 @@ static coroutine_fn int 
qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
 }
 }
 
-while (l2meta != NULL) {
-QCowL2Meta *next;
-
-ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
-if (ret < 0) {
-goto fail;
-}
-
-/* Take the request off the list of running requests */
-if (l2meta->nb_clusters != 0) {
-QLIST_REMOVE(l2meta, next_in_flight);
-}
-
-qemu_co_queue_restart_all(>dependent_requests);
-
-next = l2meta->next;
-g_free(l2meta);
-l2meta = next;
+ret = qcow2_handle_l2meta(bs, , true);
+if (ret) {
+goto fail;
 }
 
 bytes -= cur_bytes;
@@ -2076,18 +2094,7 @@ static coroutine_fn int 
qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
 ret = 0;
 
 fail:
-while (l2meta != NULL) {
-QCowL2Meta *next;
-
-if (l2meta->nb_clusters != 0) {
-QLIST_REMOVE(l2meta, next_in_flight);
-}
-qemu_co_queue_restart_all(>dependent_requests);
-
-next = l2meta->next;
-g_free(l2meta);
-l2meta = next;
-}
+qcow2_handle_l2meta(bs, , false);
 
 qemu_co_mutex_unlock(>lock);
 
@@ -3274,6 +3281,163 @@ static coroutine_fn int 
qcow2_co_pdiscard(BlockDriverState *bs,
 return ret;
 }
 
+static int coroutine_fn
+qcow2_co_copy_range_from(BlockDriverState *bs,
+ BdrvChild *src, uint64_t src_offset,
+ BdrvChild *dst, uint64_t dst_offset,
+ uint64_t bytes, BdrvRequestFlags flags)
+{
+BDRVQcow2State *s = bs->opaque;
+int ret;
+unsigned int cur_bytes; /* number of bytes in current iteration */
+BdrvChild *child = NULL;
+
+assert(!bs->encrypted);
+qemu_co_mutex_lock(>lock);
+
+while (bytes != 0) {
+uint64_t copy_offset = 0;
+/* prepare next request */
+cur_bytes = MIN(bytes, INT_MAX);
+
+ret = qcow2_get_cluster_offset(bs, src_offset, _bytes, 
_offset);
+if (ret < 0) {
+goto out;
+}
+
+switch (ret) {
+case QCOW2_CLUSTER_UNALLOCATED:
+if (bs->backing && bs->backing->bs) {
+int64_t backing_length = bdrv_getlength(bs->backing->bs);
+if (src_offset >= backing_length) {
+flags |= BDRV_REQ_ZERO_WRITE;
+} else {
+child = bs->backing;
+cur_bytes = MIN(cur_bytes, backing_length - src_offset);
+copy_offset = src_offset;
+}
+} else {
+flags |= BDRV_REQ_ZERO_WRITE;
+}
+break;
+
+case QCOW2_CLUSTER_ZERO_PLAIN:
+case QCOW2_CLUSTER_ZERO_ALLOC:
+flags |= BDRV_REQ_ZERO_WRITE;
+break;
+
+case QCOW2_CLUSTER_COMPRESSED:
+ret = -ENOTSUP;
+goto out;
+break;
+
+case QCOW2_CLUSTER_NORMAL:
+child = bs->file;
+copy_offset += offset_into_cluster(s, src_offset);
+if 

[Qemu-devel] [PATCH v6 10/10] qemu-img: Convert with copy offloading

2018-05-27 Thread Fam Zheng
The new blk_co_copy_range interface offers a more efficient way in the
case of network based storage. Make use of it to allow faster convert
operation.

Since copy offloading cannot do zero detection ('-S') and compression
(-c), only try it when these options are not used.

Signed-off-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
---
 qemu-img.c | 50 --
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 976b437da0..75f1610aa0 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1547,6 +1547,7 @@ typedef struct ImgConvertState {
 bool compressed;
 bool target_has_backing;
 bool wr_in_order;
+bool copy_range;
 int min_sparse;
 size_t cluster_sectors;
 size_t buf_sectors;
@@ -1740,6 +1741,37 @@ static int coroutine_fn convert_co_write(ImgConvertState 
*s, int64_t sector_num,
 return 0;
 }
 
+static int coroutine_fn convert_co_copy_range(ImgConvertState *s, int64_t 
sector_num,
+  int nb_sectors)
+{
+int n, ret;
+
+while (nb_sectors > 0) {
+BlockBackend *blk;
+int src_cur;
+int64_t bs_sectors, src_cur_offset;
+int64_t offset;
+
+convert_select_part(s, sector_num, _cur, _cur_offset);
+offset = (sector_num - src_cur_offset) << BDRV_SECTOR_BITS;
+blk = s->src[src_cur];
+bs_sectors = s->src_sectors[src_cur];
+
+n = MIN(nb_sectors, bs_sectors - (sector_num - src_cur_offset));
+
+ret = blk_co_copy_range(blk, offset, s->target,
+sector_num << BDRV_SECTOR_BITS,
+n << BDRV_SECTOR_BITS, 0);
+if (ret < 0) {
+return ret;
+}
+
+sector_num += n;
+nb_sectors -= n;
+}
+return 0;
+}
+
 static void coroutine_fn convert_co_do_copy(void *opaque)
 {
 ImgConvertState *s = opaque;
@@ -1762,6 +1794,7 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
 int n;
 int64_t sector_num;
 enum ImgConvertBlockStatus status;
+bool copy_range;
 
 qemu_co_mutex_lock(>lock);
 if (s->ret != -EINPROGRESS || s->sector_num >= s->total_sectors) {
@@ -1791,7 +1824,9 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
 s->allocated_sectors, 0);
 }
 
-if (status == BLK_DATA) {
+retry:
+copy_range = s->copy_range && s->status == BLK_DATA;
+if (status == BLK_DATA && !copy_range) {
 ret = convert_co_read(s, sector_num, n, buf);
 if (ret < 0) {
 error_report("error while reading sector %" PRId64
@@ -1813,7 +1848,15 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
 }
 
 if (s->ret == -EINPROGRESS) {
-ret = convert_co_write(s, sector_num, n, buf, status);
+if (copy_range) {
+ret = convert_co_copy_range(s, sector_num, n);
+if (ret) {
+s->copy_range = false;
+goto retry;
+}
+} else {
+ret = convert_co_write(s, sector_num, n, buf, status);
+}
 if (ret < 0) {
 error_report("error while writing sector %" PRId64
  ": %s", sector_num, strerror(-ret));
@@ -1936,6 +1979,7 @@ static int img_convert(int argc, char **argv)
 ImgConvertState s = (ImgConvertState) {
 /* Need at least 4k of zeros for sparse detection */
 .min_sparse = 8,
+.copy_range = true,
 .buf_sectors= IO_BUF_SIZE / BDRV_SECTOR_SIZE,
 .wr_in_order= true,
 .num_coroutines = 8,
@@ -1976,6 +2020,7 @@ static int img_convert(int argc, char **argv)
 break;
 case 'c':
 s.compressed = true;
+s.copy_range = false;
 break;
 case 'o':
 if (!is_valid_option_list(optarg)) {
@@ -2017,6 +2062,7 @@ static int img_convert(int argc, char **argv)
 }
 
 s.min_sparse = sval / BDRV_SECTOR_SIZE;
+s.copy_range = false;
 break;
 }
 case 'p':
-- 
2.14.3




[Qemu-devel] [PATCH v6 07/10] iscsi: Create and use iscsi_co_wait_for_task

2018-05-27 Thread Fam Zheng
This loop is repeated a growing number times. Make a helper.

Signed-off-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Eric Blake 
---
 block/iscsi.c | 54 +-
 1 file changed, 17 insertions(+), 37 deletions(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index 6d0035d4b9..6a365cb07b 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -556,6 +556,17 @@ static inline bool iscsi_allocmap_is_valid(IscsiLun 
*iscsilun,
offset / iscsilun->cluster_size) == size);
 }
 
+static void coroutine_fn iscsi_co_wait_for_task(IscsiTask *iTask,
+IscsiLun *iscsilun)
+{
+while (!iTask->complete) {
+iscsi_set_events(iscsilun);
+qemu_mutex_unlock(>mutex);
+qemu_coroutine_yield();
+qemu_mutex_lock(>mutex);
+}
+}
+
 static int coroutine_fn
 iscsi_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 QEMUIOVector *iov, int flags)
@@ -617,12 +628,7 @@ retry:
 scsi_task_set_iov_out(iTask.task, (struct scsi_iovec *) iov->iov,
   iov->niov);
 #endif
-while (!iTask.complete) {
-iscsi_set_events(iscsilun);
-qemu_mutex_unlock(>mutex);
-qemu_coroutine_yield();
-qemu_mutex_lock(>mutex);
-}
+iscsi_co_wait_for_task(, iscsilun);
 
 if (iTask.task != NULL) {
 scsi_free_scsi_task(iTask.task);
@@ -693,13 +699,7 @@ retry:
 ret = -ENOMEM;
 goto out_unlock;
 }
-
-while (!iTask.complete) {
-iscsi_set_events(iscsilun);
-qemu_mutex_unlock(>mutex);
-qemu_coroutine_yield();
-qemu_mutex_lock(>mutex);
-}
+iscsi_co_wait_for_task(, iscsilun);
 
 if (iTask.do_retry) {
 if (iTask.task != NULL) {
@@ -863,13 +863,8 @@ retry:
 #if LIBISCSI_API_VERSION < (20160603)
 scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov, 
iov->niov);
 #endif
-while (!iTask.complete) {
-iscsi_set_events(iscsilun);
-qemu_mutex_unlock(>mutex);
-qemu_coroutine_yield();
-qemu_mutex_lock(>mutex);
-}
 
+iscsi_co_wait_for_task(, iscsilun);
 if (iTask.task != NULL) {
 scsi_free_scsi_task(iTask.task);
 iTask.task = NULL;
@@ -906,12 +901,7 @@ retry:
 return -ENOMEM;
 }
 
-while (!iTask.complete) {
-iscsi_set_events(iscsilun);
-qemu_mutex_unlock(>mutex);
-qemu_coroutine_yield();
-qemu_mutex_lock(>mutex);
-}
+iscsi_co_wait_for_task(, iscsilun);
 
 if (iTask.task != NULL) {
 scsi_free_scsi_task(iTask.task);
@@ -1143,12 +1133,7 @@ retry:
 goto out_unlock;
 }
 
-while (!iTask.complete) {
-iscsi_set_events(iscsilun);
-qemu_mutex_unlock(>mutex);
-qemu_coroutine_yield();
-qemu_mutex_lock(>mutex);
-}
+iscsi_co_wait_for_task(, iscsilun);
 
 if (iTask.task != NULL) {
 scsi_free_scsi_task(iTask.task);
@@ -1244,12 +1229,7 @@ retry:
 return -ENOMEM;
 }
 
-while (!iTask.complete) {
-iscsi_set_events(iscsilun);
-qemu_mutex_unlock(>mutex);
-qemu_coroutine_yield();
-qemu_mutex_lock(>mutex);
-}
+iscsi_co_wait_for_task(, iscsilun);
 
 if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
 iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
-- 
2.14.3




[Qemu-devel] [PATCH v6 02/10] raw: Check byte range uniformly

2018-05-27 Thread Fam Zheng
We don't verify the request range against s->size in the I/O callbacks
except for raw_co_pwritev. This is inconsistent (especially for
raw_co_pwrite_zeroes and raw_co_pdiscard), so fix them, in the meanwhile
make the helper reusable by the coming new callbacks.

Note that in most cases the block layer already verifies the request
byte range against our reported image length, before invoking the driver
callbacks.  The exception is during image creating, after
blk_set_allow_write_beyond_eof(blk, true) is called. But in that case,
the requests are not directly from the user or guest. So there is no
visible behavior change in adding the check code.

The int64_t -> uint64_t inconsistency, as shown by the type casting, is
pre-existing due to the interface.

Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Eric Blake 
Signed-off-by: Fam Zheng 
---
 block/raw-format.c | 64 +-
 1 file changed, 39 insertions(+), 25 deletions(-)

diff --git a/block/raw-format.c b/block/raw-format.c
index fe33693a2d..b69a0674b3 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -167,16 +167,37 @@ static void raw_reopen_abort(BDRVReopenState *state)
 state->opaque = NULL;
 }
 
+/* Check and adjust the offset, against 'offset' and 'size' options. */
+static inline int raw_adjust_offset(BlockDriverState *bs, uint64_t *offset,
+uint64_t bytes, bool is_write)
+{
+BDRVRawState *s = bs->opaque;
+
+if (s->has_size && (*offset > s->size || bytes > (s->size - *offset))) {
+/* There's not enough space for the write, or the read request is
+ * out-of-range. Don't read/write anything to prevent leaking out of
+ * the size specified in options. */
+return is_write ? -ENOSPC : -EINVAL;;
+}
+
+if (*offset > INT64_MAX - s->offset) {
+return -EINVAL;
+}
+*offset += s->offset;
+
+return 0;
+}
+
 static int coroutine_fn raw_co_preadv(BlockDriverState *bs, uint64_t offset,
   uint64_t bytes, QEMUIOVector *qiov,
   int flags)
 {
-BDRVRawState *s = bs->opaque;
+int ret;
 
-if (offset > UINT64_MAX - s->offset) {
-return -EINVAL;
+ret = raw_adjust_offset(bs, , bytes, false);
+if (ret) {
+return ret;
 }
-offset += s->offset;
 
 BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
 return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
@@ -186,23 +207,11 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState 
*bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov,
int flags)
 {
-BDRVRawState *s = bs->opaque;
 void *buf = NULL;
 BlockDriver *drv;
 QEMUIOVector local_qiov;
 int ret;
 
-if (s->has_size && (offset > s->size || bytes > (s->size - offset))) {
-/* There's not enough space for the data. Don't write anything and just
- * fail to prevent leaking out of the size specified in options. */
-return -ENOSPC;
-}
-
-if (offset > UINT64_MAX - s->offset) {
-ret = -EINVAL;
-goto fail;
-}
-
 if (bs->probed && offset < BLOCK_PROBE_BUF_SIZE && bytes) {
 /* Handling partial writes would be a pain - so we just
  * require that guests have 512-byte request alignment if
@@ -237,7 +246,10 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState 
*bs, uint64_t offset,
 qiov = _qiov;
 }
 
-offset += s->offset;
+ret = raw_adjust_offset(bs, , bytes, true);
+if (ret) {
+goto fail;
+}
 
 BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
 ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
@@ -267,22 +279,24 @@ static int coroutine_fn 
raw_co_pwrite_zeroes(BlockDriverState *bs,
  int64_t offset, int bytes,
  BdrvRequestFlags flags)
 {
-BDRVRawState *s = bs->opaque;
-if (offset > UINT64_MAX - s->offset) {
-return -EINVAL;
+int ret;
+
+ret = raw_adjust_offset(bs, (uint64_t *), bytes, true);
+if (ret) {
+return ret;
 }
-offset += s->offset;
 return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
 }
 
 static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
 int64_t offset, int bytes)
 {
-BDRVRawState *s = bs->opaque;
-if (offset > UINT64_MAX - s->offset) {
-return -EINVAL;
+int ret;
+
+ret = raw_adjust_offset(bs, (uint64_t *), bytes, true);
+if (ret) {
+return ret;
 }
-offset += s->offset;
 return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
 }
 
-- 
2.14.3




[Qemu-devel] [PATCH v6 03/10] raw: Implement copy offloading

2018-05-27 Thread Fam Zheng
Just pass down to ->file.

Signed-off-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
---
 block/raw-format.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/block/raw-format.c b/block/raw-format.c
index b69a0674b3..f2e468df6f 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -497,6 +497,36 @@ static int raw_probe_geometry(BlockDriverState *bs, 
HDGeometry *geo)
 return bdrv_probe_geometry(bs->file->bs, geo);
 }
 
+static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
+   BdrvChild *src, uint64_t 
src_offset,
+   BdrvChild *dst, uint64_t 
dst_offset,
+   uint64_t bytes, 
BdrvRequestFlags flags)
+{
+int ret;
+
+ret = raw_adjust_offset(bs, _offset, bytes, false);
+if (ret) {
+return ret;
+}
+return bdrv_co_copy_range_from(bs->file, src_offset, dst, dst_offset,
+   bytes, flags);
+}
+
+static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
+ BdrvChild *src, uint64_t 
src_offset,
+ BdrvChild *dst, uint64_t 
dst_offset,
+ uint64_t bytes, BdrvRequestFlags 
flags)
+{
+int ret;
+
+ret = raw_adjust_offset(bs, _offset, bytes, true);
+if (ret) {
+return ret;
+}
+return bdrv_co_copy_range_to(src, src_offset, bs->file, dst_offset, bytes,
+ flags);
+}
+
 BlockDriver bdrv_raw = {
 .format_name  = "raw",
 .instance_size= sizeof(BDRVRawState),
@@ -513,6 +543,8 @@ BlockDriver bdrv_raw = {
 .bdrv_co_pwrite_zeroes = _co_pwrite_zeroes,
 .bdrv_co_pdiscard = _co_pdiscard,
 .bdrv_co_block_status = _co_block_status,
+.bdrv_co_copy_range_from = _co_copy_range_from,
+.bdrv_co_copy_range_to  = _co_copy_range_to,
 .bdrv_truncate= _truncate,
 .bdrv_getlength   = _getlength,
 .has_variable_length  = true,
-- 
2.14.3




[Qemu-devel] [PATCH v6 06/10] iscsi: Query and save device designator when opening

2018-05-27 Thread Fam Zheng
The device designator data returned in INQUIRY command will be useful to
fill in source/target fields during copy offloading. Do this when
connecting to the target and save the data for later use.

Signed-off-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
---
 block/iscsi.c| 41 +
 include/scsi/constants.h |  2 ++
 2 files changed, 43 insertions(+)

diff --git a/block/iscsi.c b/block/iscsi.c
index 3fd7203916..6d0035d4b9 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -68,6 +68,7 @@ typedef struct IscsiLun {
 QemuMutex mutex;
 struct scsi_inquiry_logical_block_provisioning lbp;
 struct scsi_inquiry_block_limits bl;
+struct scsi_inquiry_device_designator *dd;
 unsigned char *zeroblock;
 /* The allocmap tracks which clusters (pages) on the iSCSI target are
  * allocated and which are not. In case a target returns zeros for
@@ -1740,6 +1741,30 @@ static QemuOptsList runtime_opts = {
 },
 };
 
+static void iscsi_save_designator(IscsiLun *lun,
+  struct scsi_inquiry_device_identification 
*inq_di)
+{
+struct scsi_inquiry_device_designator *desig, *copy = NULL;
+
+for (desig = inq_di->designators; desig; desig = desig->next) {
+if (desig->association ||
+desig->designator_type > SCSI_DESIGNATOR_TYPE_NAA) {
+continue;
+}
+/* NAA works better than T10 vendor ID based designator. */
+if (!copy || copy->designator_type < desig->designator_type) {
+copy = desig;
+}
+}
+if (copy) {
+lun->dd = g_new(struct scsi_inquiry_device_designator, 1);
+*lun->dd = *copy;
+lun->dd->next = NULL;
+lun->dd->designator = g_malloc(copy->designator_length);
+memcpy(lun->dd->designator, copy->designator, copy->designator_length);
+}
+}
+
 static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
   Error **errp)
 {
@@ -1922,6 +1947,7 @@ static int iscsi_open(BlockDriverState *bs, QDict 
*options, int flags,
 struct scsi_task *inq_task;
 struct scsi_inquiry_logical_block_provisioning *inq_lbp;
 struct scsi_inquiry_block_limits *inq_bl;
+struct scsi_inquiry_device_identification *inq_di;
 switch (inq_vpd->pages[i]) {
 case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
 inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
@@ -1947,6 +1973,17 @@ static int iscsi_open(BlockDriverState *bs, QDict 
*options, int flags,
sizeof(struct scsi_inquiry_block_limits));
 scsi_free_scsi_task(inq_task);
 break;
+case SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION:
+inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
+
SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
+(void **) _di, errp);
+if (inq_task == NULL) {
+ret = -EINVAL;
+goto out;
+}
+iscsi_save_designator(iscsilun, inq_di);
+scsi_free_scsi_task(inq_task);
+break;
 default:
 break;
 }
@@ -2003,6 +2040,10 @@ static void iscsi_close(BlockDriverState *bs)
 iscsi_logout_sync(iscsi);
 }
 iscsi_destroy_context(iscsi);
+if (iscsilun->dd) {
+g_free(iscsilun->dd->designator);
+g_free(iscsilun->dd);
+}
 g_free(iscsilun->zeroblock);
 iscsi_allocmap_free(iscsilun);
 qemu_mutex_destroy(>mutex);
diff --git a/include/scsi/constants.h b/include/scsi/constants.h
index a141dd71f8..54733b7110 100644
--- a/include/scsi/constants.h
+++ b/include/scsi/constants.h
@@ -311,4 +311,6 @@
 #define MMC_PROFILE_HDDVD_RW_DL 0x005A
 #define MMC_PROFILE_INVALID 0x
 
+#define IDENT_DESCR_TGT_DESCR 0xE4
+
 #endif
-- 
2.14.3




[Qemu-devel] [PATCH v6 05/10] file-posix: Implement bdrv_co_copy_range

2018-05-27 Thread Fam Zheng
With copy_file_range(2), we can implement the bdrv_co_copy_range
semantics.

Signed-off-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
---
 block/file-posix.c  | 96 +++--
 include/block/raw-aio.h | 10 --
 2 files changed, 101 insertions(+), 5 deletions(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index 5a602cfe37..550a201750 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -59,6 +59,7 @@
 #ifdef __linux__
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -187,6 +188,8 @@ typedef struct RawPosixAIOData {
 #define aio_ioctl_cmd   aio_nbytes /* for QEMU_AIO_IOCTL */
 off_t aio_offset;
 int aio_type;
+int aio_fd2;
+off_t aio_offset2;
 } RawPosixAIOData;
 
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -1446,6 +1449,47 @@ static ssize_t handle_aiocb_write_zeroes(RawPosixAIOData 
*aiocb)
 return -ENOTSUP;
 }
 
+static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,
+ off_t *out_off, size_t len, unsigned int flags)
+{
+#ifdef __NR_copy_file_range
+return syscall(__NR_copy_file_range, in_fd, in_off, out_fd,
+   out_off, len, flags);
+#else
+errno = ENOSYS;
+return -1;
+#endif
+}
+
+static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
+{
+uint64_t bytes = aiocb->aio_nbytes;
+off_t in_off = aiocb->aio_offset;
+off_t out_off = aiocb->aio_offset2;
+
+while (bytes) {
+ssize_t ret = copy_file_range(aiocb->aio_fildes, _off,
+  aiocb->aio_fd2, _off,
+  bytes, 0);
+if (ret == -EINTR) {
+continue;
+}
+if (ret < 0) {
+if (errno == ENOSYS) {
+return -ENOTSUP;
+} else {
+return -errno;
+}
+}
+if (!ret) {
+/* No progress (e.g. when beyond EOF), fall back to buffer I/O. */
+return -ENOTSUP;
+}
+bytes -= ret;
+}
+return 0;
+}
+
 static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
 {
 int ret = -EOPNOTSUPP;
@@ -1526,6 +1570,9 @@ static int aio_worker(void *arg)
 case QEMU_AIO_WRITE_ZEROES:
 ret = handle_aiocb_write_zeroes(aiocb);
 break;
+case QEMU_AIO_COPY_RANGE:
+ret = handle_aiocb_copy_range(aiocb);
+break;
 default:
 fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
 ret = -EINVAL;
@@ -1536,9 +1583,10 @@ static int aio_worker(void *arg)
 return ret;
 }
 
-static int paio_submit_co(BlockDriverState *bs, int fd,
-  int64_t offset, QEMUIOVector *qiov,
-  int bytes, int type)
+static int paio_submit_co_full(BlockDriverState *bs, int fd,
+   int64_t offset, int fd2, int64_t offset2,
+   QEMUIOVector *qiov,
+   int bytes, int type)
 {
 RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
 ThreadPool *pool;
@@ -1546,6 +1594,8 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
 acb->bs = bs;
 acb->aio_type = type;
 acb->aio_fildes = fd;
+acb->aio_fd2 = fd2;
+acb->aio_offset2 = offset2;
 
 acb->aio_nbytes = bytes;
 acb->aio_offset = offset;
@@ -1561,6 +1611,13 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
 return thread_pool_submit_co(pool, aio_worker, acb);
 }
 
+static inline int paio_submit_co(BlockDriverState *bs, int fd,
+ int64_t offset, QEMUIOVector *qiov,
+ int bytes, int type)
+{
+return paio_submit_co_full(bs, fd, offset, -1, 0, qiov, bytes, type);
+}
+
 static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd,
 int64_t offset, QEMUIOVector *qiov, int bytes,
 BlockCompletionFunc *cb, void *opaque, int type)
@@ -2451,6 +2508,35 @@ static void raw_abort_perm_update(BlockDriverState *bs)
 raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
 }
 
+static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
+   BdrvChild *src, uint64_t 
src_offset,
+   BdrvChild *dst, uint64_t 
dst_offset,
+   uint64_t bytes, 
BdrvRequestFlags flags)
+{
+return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, 
flags);
+}
+
+static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
+ BdrvChild *src, uint64_t 
src_offset,
+ BdrvChild *dst, uint64_t 
dst_offset,
+ uint64_t bytes, BdrvRequestFlags 
flags)
+{
+BDRVRawState *s = bs->opaque;
+BDRVRawState *src_s;
+
+assert(dst->bs == 

[Qemu-devel] [PATCH v6 00/10] qemu-img convert with copy offloading

2018-05-27 Thread Fam Zheng
v6: Pick up rev-by from Stefan and Eric.
Tweak patch 2 commit message.

v5: - Fix raw offset/bytes check for read. [Eric]
- Fix qcow2_handle_l2meta. [Stefan]
- Add coroutine_fn whereever appropriate. [Stefan]

v4: - Fix raw offset and size. [Eric]
- iscsi: Drop unnecessary return values and variables in favor of
  constants. [Stefan]
- qcow2: Handle small backing case. [Stefan]
- file-posix: Translate ENOSYS to ENOTSUP. [Stefan]
- API documentation and commit message. [Stefan]
- Add rev-by to patches 3, 5 - 10. [Stefan, Eric]

This series introduces block layer API for copy offloading and makes use of it
in qemu-img convert.

For now we implemented the operation in local file protocol with
copy_file_range(2).  Besides that it's possible to add similar to iscsi, nfs
and potentially more.

As far as its usage goes, in addition to qemu-img convert, we can emulate
offloading in scsi-disk (handle EXTENDED COPY command), and use the API in
block jobs too.

Fam Zheng (10):
  block: Introduce API for copy offloading
  raw: Check byte range uniformly
  raw: Implement copy offloading
  qcow2: Implement copy offloading
  file-posix: Implement bdrv_co_copy_range
  iscsi: Query and save device designator when opening
  iscsi: Create and use iscsi_co_wait_for_task
  iscsi: Implement copy offloading
  block-backend: Add blk_co_copy_range
  qemu-img: Convert with copy offloading

 block/block-backend.c  |  18 +++
 block/file-posix.c |  96 -
 block/io.c |  97 +
 block/iscsi.c  | 314 -
 block/qcow2.c  | 226 +
 block/raw-format.c |  96 +
 include/block/block.h  |  32 +
 include/block/block_int.h  |  38 +
 include/block/raw-aio.h|  10 +-
 include/scsi/constants.h   |   5 +
 include/sysemu/block-backend.h |   4 +
 qemu-img.c |  50 ++-
 12 files changed, 887 insertions(+), 99 deletions(-)

-- 
2.14.3




[Qemu-devel] [PATCH v6 01/10] block: Introduce API for copy offloading

2018-05-27 Thread Fam Zheng
Introduce the bdrv_co_copy_range() API for copy offloading.  Block
drivers implementing this API support efficient copy operations that
avoid reading each block from the source device and writing it to the
destination devices.  Examples of copy offload primitives are SCSI
EXTENDED COPY and Linux copy_file_range(2).

Signed-off-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
---
 block/io.c| 97 +++
 include/block/block.h | 32 
 include/block/block_int.h | 38 +++
 3 files changed, 167 insertions(+)

diff --git a/block/io.c b/block/io.c
index ca96b487eb..b7beaeeb9f 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2835,3 +2835,100 @@ void bdrv_unregister_buf(BlockDriverState *bs, void 
*host)
 bdrv_unregister_buf(child->bs, host);
 }
 }
+
+static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
+uint64_t src_offset,
+BdrvChild *dst,
+uint64_t dst_offset,
+uint64_t bytes,
+BdrvRequestFlags flags,
+bool recurse_src)
+{
+int ret;
+
+if (!src || !dst || !src->bs || !dst->bs) {
+return -ENOMEDIUM;
+}
+ret = bdrv_check_byte_request(src->bs, src_offset, bytes);
+if (ret) {
+return ret;
+}
+
+ret = bdrv_check_byte_request(dst->bs, dst_offset, bytes);
+if (ret) {
+return ret;
+}
+if (flags & BDRV_REQ_ZERO_WRITE) {
+return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, flags);
+}
+
+if (!src->bs->drv->bdrv_co_copy_range_from
+|| !dst->bs->drv->bdrv_co_copy_range_to
+|| src->bs->encrypted || dst->bs->encrypted) {
+return -ENOTSUP;
+}
+if (recurse_src) {
+return src->bs->drv->bdrv_co_copy_range_from(src->bs,
+ src, src_offset,
+ dst, dst_offset,
+ bytes, flags);
+} else {
+return dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
+   src, src_offset,
+   dst, dst_offset,
+   bytes, flags);
+}
+}
+
+/* Copy range from @src to @dst.
+ *
+ * See the comment of bdrv_co_copy_range for the parameter and return value
+ * semantics. */
+int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
+ BdrvChild *dst, uint64_t dst_offset,
+ uint64_t bytes, BdrvRequestFlags 
flags)
+{
+return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
+   bytes, flags, true);
+}
+
+/* Copy range from @src to @dst.
+ *
+ * See the comment of bdrv_co_copy_range for the parameter and return value
+ * semantics. */
+int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
+   BdrvChild *dst, uint64_t dst_offset,
+   uint64_t bytes, BdrvRequestFlags flags)
+{
+return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
+   bytes, flags, false);
+}
+
+int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
+BdrvChild *dst, uint64_t dst_offset,
+uint64_t bytes, BdrvRequestFlags flags)
+{
+BdrvTrackedRequest src_req, dst_req;
+BlockDriverState *src_bs = src->bs;
+BlockDriverState *dst_bs = dst->bs;
+int ret;
+
+bdrv_inc_in_flight(src_bs);
+bdrv_inc_in_flight(dst_bs);
+tracked_request_begin(_req, src_bs, src_offset,
+  bytes, BDRV_TRACKED_READ);
+tracked_request_begin(_req, dst_bs, dst_offset,
+  bytes, BDRV_TRACKED_WRITE);
+
+wait_serialising_requests(_req);
+wait_serialising_requests(_req);
+ret = bdrv_co_copy_range_from(src, src_offset,
+  dst, dst_offset,
+  bytes, flags);
+
+tracked_request_end(_req);
+tracked_request_end(_req);
+bdrv_dec_in_flight(src_bs);
+bdrv_dec_in_flight(dst_bs);
+return ret;
+}
diff --git a/include/block/block.h b/include/block/block.h
index 3894edda9d..6cc6c7e699 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -611,4 +611,36 @@ bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, 
const char *name,
  */
 void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size);
 void 

Re: [Qemu-devel] [PATCH v5 3/7] hw/mdio: Generalize phy initialization routine

2018-05-27 Thread Philippe Mathieu-Daudé
Hi Alistair,

On 02/27/2018 07:33 PM, Alistair Francis wrote:
> On Fri, Sep 22, 2017 at 10:13 AM, Philippe Mathieu-Daudé
>  wrote:
>> From: Grant Likely 
>>
>> There really isn't anything tdk-specific about tdk_init() other than the
>> phy id registers. The function should instead be generalized for any
>> phy, at least as far as the ID registers are concerned. For the most
>> part the read/write behaviour should be very similar across PHYs.
>>
>> This patch renames tdk_{read,write,init}() to mdio_phy_*() so it can be
>> used for any PHY.
>>
>> More work definitely needs to be done here to make it easy to override
>> the default behaviour for specific PHYs, but this at least is a
>> reasonable start.
>>
>> Signed-off-by: Grant Likely 
>> Signed-off-by: Philippe Mathieu-Daudé 
>> [PMD: just rebased]
>> ---
>>  include/hw/net/mdio.h   |  2 +-
>>  hw/net/etraxfs_eth.c|  2 +-
>>  hw/net/mdio.c   | 14 +++---
>>  hw/net/xilinx_axienet.c |  2 +-
>>  4 files changed, 10 insertions(+), 10 deletions(-)
>>
>> diff --git a/include/hw/net/mdio.h b/include/hw/net/mdio.h
>> index 7ffa4389b9..b3b4f497c0 100644
>> --- a/include/hw/net/mdio.h
>> +++ b/include/hw/net/mdio.h
>> @@ -86,7 +86,7 @@ struct qemu_mdio {
>>  struct qemu_phy *devs[32];
>>  };
>>
>> -void tdk_init(struct qemu_phy *phy);
>> +void mdio_phy_init(struct qemu_phy *phy, uint16_t id1, uint16_t id2);
>>  void mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy,
>>   unsigned int addr);
>>  uint16_t mdio_read_req(struct qemu_mdio *bus, uint8_t addr, uint8_t req);
>> diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
>> index f8d8f8441d..4c5415771f 100644
>> --- a/hw/net/etraxfs_eth.c
>> +++ b/hw/net/etraxfs_eth.c
>> @@ -333,7 +333,7 @@ static int fs_eth_init(SysBusDevice *sbd)
>>  qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
>>
>>
>> -tdk_init(>phy);
>> +mdio_phy_init(>phy, 0x0300, 0xe400);
>>  mdio_attach(>mdio_bus, >phy, s->phyaddr);
>>  return 0;
>>  }
>> diff --git a/hw/net/mdio.c b/hw/net/mdio.c
>> index 3d70d99077..33bfbb4623 100644
>> --- a/hw/net/mdio.c
>> +++ b/hw/net/mdio.c
>> @@ -43,7 +43,7 @@
>>   * linux driver (PHYID and Diagnostics reg).
>>   * TODO: Add friendly names for the register nums.
>>   */
>> -static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
>> +static unsigned int mdio_phy_read(struct qemu_phy *phy, unsigned int req)
>>  {
>>  int regnum;
>>  unsigned r = 0;
>> @@ -107,7 +107,7 @@ static unsigned int tdk_read(struct qemu_phy *phy, 
>> unsigned int req)
>>  return r;
>>  }
>>
>> -static void tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int 
>> data)
>> +static void mdio_phy_write(struct qemu_phy *phy, unsigned int req, unsigned 
>> int data)
>>  {
>>  int regnum;
>>
>> @@ -120,18 +120,18 @@ static void tdk_write(struct qemu_phy *phy, unsigned 
>> int req, unsigned int data)
>>  }
>>  }
>>
>> -void tdk_init(struct qemu_phy *phy)
>> +void mdio_phy_init(struct qemu_phy *phy, uint16_t id1, uint16_t id2)
>>  {
>>  phy->regs[PHY_CTRL] = 0x3100;
>>  /* PHY Id. */
>> -phy->regs[PHY_ID1] = 0x0300;
>> -phy->regs[PHY_ID2] = 0xe400;
>> +phy->regs[PHY_ID1] = id1;
>> +phy->regs[PHY_ID2] = id2;
> 
> These should be set by QEMU properties instead of values to the init() 
> function.

I agree, but this is not (yet) a QOM'ified device.
I believe if I start to QOM'ify it this series will finish in 1 more
year. This is however a nice cleanup so far, and the QOM device can come
in a follow up series.

> 
> Alistair
> 
>>  /* Autonegotiation advertisement reg. */
>>  phy->regs[PHY_AUTONEG_ADV] = 0x01e1;
>>  phy->link = 1;
>>
>> -phy->read = tdk_read;
>> -phy->write = tdk_write;
>> +phy->read = mdio_phy_read;
>> +phy->write = mdio_phy_write;
>>  }
>>
>>  void mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int 
>> addr)
>> diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
>> index 1e859fdaae..408cd6e675 100644
>> --- a/hw/net/xilinx_axienet.c
>> +++ b/hw/net/xilinx_axienet.c
>> @@ -791,7 +791,7 @@ static void xilinx_enet_realize(DeviceState *dev, Error 
>> **errp)
>>object_get_typename(OBJECT(dev)), dev->id, s);
>>  qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
>>
>> -tdk_init(>TEMAC.phy);
>> +mdio_phy_init(>TEMAC.phy, 0x0300, 0xe400);
>>  mdio_attach(>TEMAC.mdio_bus, >TEMAC.phy, s->c_phyaddr);
>>
>>  s->TEMAC.parent = s;
>> --
>> 2.14.1
>>
>>



Re: [Qemu-devel] [PATCH 07/20] target/openrisc: Form the spr index from tcg

2018-05-27 Thread Richard Henderson
On 05/27/2018 08:31 PM, Philippe Mathieu-Daudé wrote:
> On 05/27/2018 11:13 AM, Richard Henderson wrote:
>> Rather than pass base+offset to the helper, pass the full index.
>> In most cases the base is r0 and optimization yields a constant.
> 
> and while here you use generic TCGv instead of 32bit version.

We always used target_ulong for the variable part of the address.


r~



Re: [Qemu-devel] [PATCH 14/20] target/openrisc: Use identical sizes for ITLB and DTLB

2018-05-27 Thread Philippe Mathieu-Daudé
On 05/27/2018 11:13 AM, Richard Henderson wrote:
> The sizes are already the same, however, we can improve things
> if they are identical by design.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  target/openrisc/cpu.h| 10 --
>  target/openrisc/machine.c|  4 ++--
>  target/openrisc/mmu.c|  4 ++--
>  target/openrisc/sys_helper.c | 16 
>  4 files changed, 16 insertions(+), 18 deletions(-)
> 
> diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
> index c48802ad8f..53abe965e8 100644
> --- a/target/openrisc/cpu.h
> +++ b/target/openrisc/cpu.h
> @@ -222,10 +222,8 @@ enum {
>  
>  /* TLB size */
>  enum {
> -DTLB_SIZE = 64,
> -DTLB_MASK = (DTLB_SIZE-1),
> -ITLB_SIZE = 64,
> -ITLB_MASK = (ITLB_SIZE-1),
> +TLB_SIZE = 64,
> +TLB_MASK = TLB_SIZE - 1,
>  };
>  
>  /* TLB prot */
> @@ -254,8 +252,8 @@ typedef struct OpenRISCTLBEntry {
>  
>  #ifndef CONFIG_USER_ONLY
>  typedef struct CPUOpenRISCTLBContext {
> -OpenRISCTLBEntry itlb[ITLB_SIZE];
> -OpenRISCTLBEntry dtlb[DTLB_SIZE];
> +OpenRISCTLBEntry itlb[TLB_SIZE];
> +OpenRISCTLBEntry dtlb[TLB_SIZE];
>  
>  int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
>   hwaddr *physical,
> diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
> index b795b56dc6..3fc837b925 100644
> --- a/target/openrisc/machine.c
> +++ b/target/openrisc/machine.c
> @@ -42,9 +42,9 @@ static const VMStateDescription vmstate_cpu_tlb = {
>  .minimum_version_id = 1,
>  .minimum_version_id_old = 1,
>  .fields = (VMStateField[]) {
> -VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, ITLB_SIZE, 0,
> +VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, TLB_SIZE, 0,
>   vmstate_tlb_entry, OpenRISCTLBEntry),
> -VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, DTLB_SIZE, 0,
> +VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, TLB_SIZE, 0,
>   vmstate_tlb_entry, OpenRISCTLBEntry),
>  VMSTATE_END_OF_LIST()
>  }
> diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
> index 11b8187cda..ee3016a8b9 100644
> --- a/target/openrisc/mmu.c
> +++ b/target/openrisc/mmu.c
> @@ -41,7 +41,7 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr 
> *physical, int *prot,
>   target_ulong address, int rw, bool supervisor)
>  {
>  int vpn = address >> TARGET_PAGE_BITS;
> -int idx = vpn & ITLB_MASK;
> +int idx = vpn & TLB_MASK;
>  int right = 0;
>  uint32_t mr = cpu->env.tlb.itlb[idx].mr;
>  uint32_t tr = cpu->env.tlb.itlb[idx].tr;
> @@ -74,7 +74,7 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr 
> *physical, int *prot,
>   target_ulong address, int rw, bool supervisor)
>  {
>  int vpn = address >> TARGET_PAGE_BITS;
> -int idx = vpn & DTLB_MASK;
> +int idx = vpn & TLB_MASK;
>  int right = 0;
>  uint32_t mr = cpu->env.tlb.dtlb[idx].mr;
>  uint32_t tr = cpu->env.tlb.dtlb[idx].tr;
> diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
> index 0a74c9522f..7254aa9830 100644
> --- a/target/openrisc/sys_helper.c
> +++ b/target/openrisc/sys_helper.c
> @@ -79,7 +79,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
> target_ulong rb)
>  idx = (spr - 1024);
>  env->shadow_gpr[idx / 32][idx % 32] = rb;
>  
> -case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
> +case TO_SPR(1, 512) ... TO_SPR(1, 512 + TLB_SIZE - 1): /* DTLBW0MR 0-127 
> */
>  idx = spr - TO_SPR(1, 512);
>  mr = env->tlb.dtlb[idx].mr;
>  if (mr & 1) {
> @@ -90,7 +90,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
> target_ulong rb)
>  }
>  env->tlb.dtlb[idx].mr = rb;
>  break;
> -case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
> +case TO_SPR(1, 640) ... TO_SPR(1, 640 + TLB_SIZE - 1): /* DTLBW0TR 0-127 
> */
>  idx = spr - TO_SPR(1, 640);
>  env->tlb.dtlb[idx].tr = rb;
>  break;
> @@ -102,7 +102,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
> spr, target_ulong rb)
>  case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>  break;
>  
> -case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1):   /* ITLBW0MR 0-127 
> */
> +case TO_SPR(2, 512) ... TO_SPR(2, 512 + TLB_SIZE - 1): /* ITLBW0MR 0-127 
> */
>  idx = spr - TO_SPR(2, 512);
>  mr = env->tlb.itlb[idx].mr;
>  if (mr & 1) {
> @@ -113,7 +113,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
> spr, target_ulong rb)
>  }
>  env->tlb.itlb[idx].mr = rb;
>  break;
> -case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
> +case TO_SPR(2, 640) ... 

Re: [Qemu-devel] [PATCH 01/20] target/openrisc: Remove DISAS_JUMP & DISAS_TB_JUMP

2018-05-27 Thread Philippe Mathieu-Daudé
On 05/27/2018 11:13 AM, Richard Henderson wrote:
> These values are unused.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  target/openrisc/translate.c | 4 
>  1 file changed, 4 deletions(-)
> 
> diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
> index e7c96ca990..f4f2f37e28 100644
> --- a/target/openrisc/translate.c
> +++ b/target/openrisc/translate.c
> @@ -41,9 +41,7 @@
>## __VA_ARGS__)
>  
>  /* is_jmp field values */
> -#define DISAS_JUMPDISAS_TARGET_0 /* only pc was modified dynamically */
>  #define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
> -#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
>  
>  typedef struct DisasContext {
>  DisasContextBase base;
> @@ -1467,8 +1465,6 @@ static void openrisc_tr_tb_stop(DisasContextBase 
> *dcbase, CPUState *cs)
>  gen_goto_tb(dc, 0, dc->base.pc_next);
>  break;
>  case DISAS_NORETURN:
> -case DISAS_JUMP:
> -case DISAS_TB_JUMP:
>  break;
>  case DISAS_UPDATE:
>  /* indicate that the hash table must be used
> 



Re: [Qemu-devel] [PATCH 05/20] target/openrisc: Split out is_user

2018-05-27 Thread Philippe Mathieu-Daudé
On 05/27/2018 11:13 AM, Richard Henderson wrote:
> This allows us to limit the amount of ifdefs and isolate
> the test for usermode.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  target/openrisc/translate.c | 27 ---
>  1 file changed, 12 insertions(+), 15 deletions(-)
> 
> diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
> index a8afb9a562..61e6deef69 100644
> --- a/target/openrisc/translate.c
> +++ b/target/openrisc/translate.c
> @@ -54,6 +54,15 @@ typedef struct DisasContext {
>  target_ulong jmp_pc_imm;
>  } DisasContext;
>  
> +static inline bool is_user(DisasContext *dc)
> +{
> +#ifdef CONFIG_USER_ONLY
> +return true;
> +#else
> +return dc->mem_idx == MMU_USER_IDX;
> +#endif
> +}
> +
>  /* Include the auto-generated decoder.  */
>  #include "decode.inc.c"
>  
> @@ -914,17 +923,13 @@ static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr 
> *a, uint32_t insn)
>  LOG_DIS("l.mfspr r%d, r%d, %d\n", a->d, a->a, a->k);
>  check_r0_write(a->d);
>  
> -#ifdef CONFIG_USER_ONLY
> -gen_illegal_exception(dc);
> -#else
> -if (dc->mem_idx == MMU_USER_IDX) {
> +if (is_user(dc)) {
>  gen_illegal_exception(dc);
>  } else {
>  TCGv_i32 ti = tcg_const_i32(a->k);
>  gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti);
>  tcg_temp_free_i32(ti);
>  }
> -#endif
>  return true;
>  }
>  
> @@ -932,17 +937,13 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr 
> *a, uint32_t insn)
>  {
>  LOG_DIS("l.mtspr r%d, r%d, %d\n", a->a, a->b, a->k);
>  
> -#ifdef CONFIG_USER_ONLY
> -gen_illegal_exception(dc);
> -#else
> -if (dc->mem_idx == MMU_USER_IDX) {
> +if (is_user(dc)) {
>  gen_illegal_exception(dc);
>  } else {
>  TCGv_i32 ti = tcg_const_i32(a->k);
>  gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti);
>  tcg_temp_free_i32(ti);
>  }
> -#endif
>  return true;
>  }
>  
> @@ -1204,16 +1205,12 @@ static bool trans_l_rfe(DisasContext *dc, arg_l_rfe 
> *a, uint32_t insn)
>  {
>  LOG_DIS("l.rfe\n");
>  
> -#ifdef CONFIG_USER_ONLY
> -gen_illegal_exception(dc);
> -#else
> -if (dc->mem_idx == MMU_USER_IDX) {
> +if (is_user(dc)) {
>  gen_illegal_exception(dc);
>  } else {
>  gen_helper_rfe(cpu_env);
>  dc->base.is_jmp = DISAS_EXIT;
>  }
> -#endif
>  return true;
>  }
>  
> 



Re: [Qemu-devel] [PATCH 07/20] target/openrisc: Form the spr index from tcg

2018-05-27 Thread Philippe Mathieu-Daudé
On 05/27/2018 11:13 AM, Richard Henderson wrote:
> Rather than pass base+offset to the helper, pass the full index.
> In most cases the base is r0 and optimization yields a constant.

and while here you use generic TCGv instead of 32bit version.

> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  target/openrisc/helper.h |  4 ++--
>  target/openrisc/sys_helper.c |  9 +++--
>  target/openrisc/translate.c  | 16 +---
>  3 files changed, 14 insertions(+), 15 deletions(-)
> 
> diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h
> index e37dabc77a..9db9bf3963 100644
> --- a/target/openrisc/helper.h
> +++ b/target/openrisc/helper.h
> @@ -56,5 +56,5 @@ FOP_CMP(le)
>  DEF_HELPER_FLAGS_1(rfe, 0, void, env)
>  
>  /* sys */
> -DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
> -DEF_HELPER_FLAGS_4(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(mtspr, 0, void, env, tl, tl)
> +DEF_HELPER_FLAGS_3(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl)
> diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
> index b284064381..a8d287d6ef 100644
> --- a/target/openrisc/sys_helper.c
> +++ b/target/openrisc/sys_helper.c
> @@ -27,13 +27,11 @@
>  
>  #define TO_SPR(group, number) (((group) << 11) + (number))
>  
> -void HELPER(mtspr)(CPUOpenRISCState *env,
> -   target_ulong ra, target_ulong rb, target_ulong offset)
> +void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
>  {
>  #ifndef CONFIG_USER_ONLY
>  OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
>  CPUState *cs = CPU(cpu);
> -int spr = (ra | offset);
>  int idx;
>  
>  switch (spr) {
> @@ -201,13 +199,12 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
>  #endif
>  }
>  
> -target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
> -   target_ulong rd, target_ulong ra, uint32_t offset)
> +target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
> +   target_ulong spr)
>  {
>  #ifndef CONFIG_USER_ONLY
>  OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
>  CPUState *cs = CPU(cpu);
> -int spr = (ra | offset);
>  int idx;
>  
>  switch (spr) {
> diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
> index c7bfb395b0..b26c473870 100644
> --- a/target/openrisc/translate.c
> +++ b/target/openrisc/translate.c
> @@ -926,9 +926,10 @@ static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr 
> *a, uint32_t insn)
>  if (is_user(dc)) {
>  gen_illegal_exception(dc);
>  } else {
> -TCGv_i32 ti = tcg_const_i32(a->k);
> -gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti);
> -tcg_temp_free_i32(ti);
> +TCGv spr = tcg_temp_new();
> +tcg_gen_ori_tl(spr, cpu_R[a->a], a->k);
> +gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], spr);
> +tcg_temp_free(spr);
>  }
>  return true;
>  }
> @@ -940,7 +941,7 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr 
> *a, uint32_t insn)
>  if (is_user(dc)) {
>  gen_illegal_exception(dc);
>  } else {
> -TCGv_i32 ti;
> +TCGv spr;
>  
>  /* For SR, we will need to exit the TB to recognize the new
>   * exception state.  For NPC, in theory this counts as a branch
> @@ -953,9 +954,10 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr 
> *a, uint32_t insn)
>  tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next);
>  tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
>  
> -ti = tcg_const_i32(a->k);
> -gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti);
> -tcg_temp_free_i32(ti);
> +spr = tcg_temp_new();
> +tcg_gen_ori_tl(spr, cpu_R[a->a], a->k);
> +gen_helper_mtspr(cpu_env, spr, cpu_R[a->b]);
> +tcg_temp_free(spr);
>  
>  /* For PPC, we want the value that was just written and not
> the generic update that we'd get from DISAS_EXIT.  */
> 



Re: [Qemu-devel] [PATCH 10/20] target/openrisc: Merge mmu_helper.c into mmu.c

2018-05-27 Thread Philippe Mathieu-Daudé
On 05/27/2018 11:13 AM, Richard Henderson wrote:
> With tlb_fill in mmu.c, we can simplify things further.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  target/openrisc/mmu.c | 11 ++
>  target/openrisc/mmu_helper.c  | 40 ---
>  target/openrisc/Makefile.objs |  2 +-
>  3 files changed, 12 insertions(+), 41 deletions(-)
>  delete mode 100644 target/openrisc/mmu_helper.c
> 
> diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
> index b2effaa6d7..9b4b5cf04f 100644
> --- a/target/openrisc/mmu.c
> +++ b/target/openrisc/mmu.c
> @@ -240,4 +240,15 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, 
> vaddr addr)
>  return phys_addr;
>  }
>  }
> +
> +void tlb_fill(CPUState *cs, target_ulong addr, int size,
> +  MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
> +{
> +int ret = openrisc_cpu_handle_mmu_fault(cs, addr, size,
> +access_type, mmu_idx);
> +if (ret) {
> +/* Raise Exception.  */
> +cpu_loop_exit_restore(cs, retaddr);
> +}
> +}
>  #endif
> diff --git a/target/openrisc/mmu_helper.c b/target/openrisc/mmu_helper.c
> deleted file mode 100644
> index 97e1d17b5a..00
> --- a/target/openrisc/mmu_helper.c
> +++ /dev/null
> @@ -1,40 +0,0 @@
> -/*
> - * OpenRISC MMU helper routines
> - *
> - * Copyright (c) 2011-2012 Jia Liu 
> - * Zhizhou Zhang 
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, see 
> .
> - */
> -
> -#include "qemu/osdep.h"
> -#include "cpu.h"
> -#include "exec/exec-all.h"
> -#include "exec/cpu_ldst.h"
> -
> -#ifndef CONFIG_USER_ONLY
> -
> -void tlb_fill(CPUState *cs, target_ulong addr, int size,
> -  MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
> -{
> -int ret;
> -
> -ret = openrisc_cpu_handle_mmu_fault(cs, addr, size, access_type, 
> mmu_idx);
> -
> -if (ret) {
> -/* Raise Exception.  */
> -cpu_loop_exit_restore(cs, retaddr);
> -}
> -}
> -#endif
> diff --git a/target/openrisc/Makefile.objs b/target/openrisc/Makefile.objs
> index 1b98a911ea..957ce02199 100644
> --- a/target/openrisc/Makefile.objs
> +++ b/target/openrisc/Makefile.objs
> @@ -1,7 +1,7 @@
>  obj-$(CONFIG_SOFTMMU) += machine.o
>  obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
>  obj-y += exception_helper.o fpu_helper.o \
> - interrupt_helper.o mmu_helper.o sys_helper.o
> + interrupt_helper.o sys_helper.o
>  obj-y += gdbstub.o
>  
>  DECODETREE = $(SRC_PATH)/scripts/decodetree.py
> 



Re: [Qemu-devel] [PATCH 11/20] target/openrisc: Reduce tlb to a single dimension

2018-05-27 Thread Philippe Mathieu-Daudé
On 05/27/2018 11:13 AM, Richard Henderson wrote:
> While we had defines for *_WAY, we didn't define more than 1.
> Reduce the complexity by eliminating this unused dimension.
> 
> Signed-off-by: Richard Henderson 
> ---
>  target/openrisc/cpu.h|  6 ++
>  target/openrisc/machine.c|  6 ++
>  target/openrisc/mmu.c| 30 --
>  target/openrisc/sys_helper.c | 20 ++--
>  4 files changed, 30 insertions(+), 32 deletions(-)
> 
> diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
> index 13107058cb..947ca00d8d 100644
> --- a/target/openrisc/cpu.h
> +++ b/target/openrisc/cpu.h
> @@ -222,10 +222,8 @@ enum {
>  
>  /* TLB size */
>  enum {
> -DTLB_WAYS = 1,
>  DTLB_SIZE = 64,
>  DTLB_MASK = (DTLB_SIZE-1),
> -ITLB_WAYS = 1,
>  ITLB_SIZE = 64,
>  ITLB_MASK = (ITLB_SIZE-1),
>  };
> @@ -256,8 +254,8 @@ typedef struct OpenRISCTLBEntry {
>  
>  #ifndef CONFIG_USER_ONLY
>  typedef struct CPUOpenRISCTLBContext {
> -OpenRISCTLBEntry itlb[ITLB_WAYS][ITLB_SIZE];
> -OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE];
> +OpenRISCTLBEntry itlb[ITLB_SIZE];
> +OpenRISCTLBEntry dtlb[DTLB_SIZE];
>  
>  int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
>   hwaddr *physical,
> diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
> index 73e0abcfd7..b795b56dc6 100644
> --- a/target/openrisc/machine.c
> +++ b/target/openrisc/machine.c
> @@ -42,11 +42,9 @@ static const VMStateDescription vmstate_cpu_tlb = {
>  .minimum_version_id = 1,
>  .minimum_version_id_old = 1,
>  .fields = (VMStateField[]) {
> -VMSTATE_STRUCT_2DARRAY(itlb, CPUOpenRISCTLBContext,
> - ITLB_WAYS, ITLB_SIZE, 0,
> +VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, ITLB_SIZE, 0,
>   vmstate_tlb_entry, OpenRISCTLBEntry),
> -VMSTATE_STRUCT_2DARRAY(dtlb, CPUOpenRISCTLBContext,
> - DTLB_WAYS, DTLB_SIZE, 0,
> +VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, DTLB_SIZE, 0,
>   vmstate_tlb_entry, OpenRISCTLBEntry),
>  VMSTATE_END_OF_LIST()
>  }
> diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
> index 9b4b5cf04f..23edd8c78c 100644
> --- a/target/openrisc/mmu.c
> +++ b/target/openrisc/mmu.c
> @@ -43,19 +43,21 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr 
> *physical, int *prot,
>  int vpn = address >> TARGET_PAGE_BITS;
>  int idx = vpn & ITLB_MASK;
>  int right = 0;
> +uint32_t mr = cpu->env.tlb.itlb[idx].mr;
> +uint32_t tr = cpu->env.tlb.itlb[idx].tr;
>  
> -if ((cpu->env.tlb.itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
> +if ((mr >> TARGET_PAGE_BITS) != vpn) {
>  return TLBRET_NOMATCH;
>  }
> -if (!(cpu->env.tlb.itlb[0][idx].mr & 1)) {
> +if (!(mr & 1)) {
>  return TLBRET_INVALID;
>  }
>  if (supervisor) {
> -if (cpu->env.tlb.itlb[0][idx].tr & SXE) {
> +if (tr & SXE) {
>  right |= PAGE_EXEC;
>  }
>  } else {
> -if (cpu->env.tlb.itlb[0][idx].tr & UXE) {
> +if (tr & UXE) {
>  right |= PAGE_EXEC;
>  }
>  }
> @@ -63,8 +65,7 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr 
> *physical, int *prot,
>  return TLBRET_BADADDR;
>  }
>  
> -*physical = (cpu->env.tlb.itlb[0][idx].tr & TARGET_PAGE_MASK) |
> -(address & (TARGET_PAGE_SIZE-1));
> +*physical = (tr & TARGET_PAGE_MASK) | (address & (TARGET_PAGE_SIZE-1));

TARGET_PAGE_SIZE - 1

>  *prot = right;
>  return TLBRET_MATCH;
>  }
> @@ -75,25 +76,27 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr 
> *physical, int *prot,
>  int vpn = address >> TARGET_PAGE_BITS;
>  int idx = vpn & DTLB_MASK;
>  int right = 0;
> +uint32_t mr = cpu->env.tlb.dtlb[idx].mr;
> +uint32_t tr = cpu->env.tlb.dtlb[idx].tr;
>  
> -if ((cpu->env.tlb.dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
> +if ((mr >> TARGET_PAGE_BITS) != vpn) {
>  return TLBRET_NOMATCH;
>  }
> -if (!(cpu->env.tlb.dtlb[0][idx].mr & 1)) {
> +if (!(mr & 1)) {
>  return TLBRET_INVALID;
>  }
>  if (supervisor) {
> -if (cpu->env.tlb.dtlb[0][idx].tr & SRE) {
> +if (tr & SRE) {
>  right |= PAGE_READ;
>  }
> -if (cpu->env.tlb.dtlb[0][idx].tr & SWE) {
> +if (tr & SWE) {
>  right |= PAGE_WRITE;
>  }
>  } else {
> -if (cpu->env.tlb.dtlb[0][idx].tr & URE) {
> +if (tr & URE) {
>  right |= PAGE_READ;
>  }
> -if (cpu->env.tlb.dtlb[0][idx].tr & UWE) {
> +if (tr & UWE) {
>  right |= PAGE_WRITE;
>  }
>  }
> @@ -105,8 +108,7 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr 
> *physical, int *prot,
>  

Re: [Qemu-devel] [PATCH 16/20] target/openrisc: Log interrupts

2018-05-27 Thread Philippe Mathieu-Daudé
On 05/27/2018 11:13 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  target/openrisc/interrupt.c | 30 +-
>  1 file changed, 25 insertions(+), 5 deletions(-)
> 
> diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
> index e28042856a..138ad17f00 100644
> --- a/target/openrisc/interrupt.c
> +++ b/target/openrisc/interrupt.c
> @@ -32,6 +32,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
>  #ifndef CONFIG_USER_ONLY
>  OpenRISCCPU *cpu = OPENRISC_CPU(cs);
>  CPUOpenRISCState *env = >env;
> +int exception = cs->exception_index;
>  
>  env->epcr = env->pc;
>  if (env->dflag) {
> @@ -41,12 +42,12 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
>  } else {
>  env->sr &= ~SR_DSX;
>  }
> -if (cs->exception_index == EXCP_SYSCALL) {
> +if (exception == EXCP_SYSCALL) {
>  env->epcr += 4;
>  }
>  /* When we have an illegal instruction the error effective address
> shall be set to the illegal instruction address.  */
> -if (cs->exception_index == EXCP_ILLEGAL) {
> +if (exception == EXCP_ILLEGAL) {
>  env->eear = env->pc;
>  }
>  
> @@ -60,8 +61,27 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
>  env->pmr &= ~PMR_SME;
>  env->lock_addr = -1;
>  
> -if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
> -hwaddr vect_pc = cs->exception_index << 8;
> +if (exception > 0 && exception < EXCP_NR) {
> +static const char * const int_name[EXCP_NR] = {
> +[EXCP_RESET]= "RESET",
> +[EXCP_BUSERR]   = "BUSERR (bus error)",
> +[EXCP_DPF]  = "DFP (data protection fault)",
> +[EXCP_IPF]  = "IPF (code protection fault)",
> +[EXCP_TICK] = "TICK (timer interrupt)",
> +[EXCP_ALIGN]= "ALIGN",
> +[EXCP_ILLEGAL]  = "ILLEGAL",
> +[EXCP_INT]  = "INT (device interrupt)",
> +[EXCP_DTLBMISS] = "DTLBMISS (data tlb miss)",
> +[EXCP_ITLBMISS] = "ITLBMISS (code tlb miss)",
> +[EXCP_RANGE]= "RANGE",
> +[EXCP_SYSCALL]  = "SYSCALL",
> +[EXCP_FPE]  = "FPE",
> +[EXCP_TRAP] = "TRAP",
> +};
> +
> +qemu_log_mask(CPU_LOG_INT, "INT: %s\n", int_name[exception]);
> +
> +hwaddr vect_pc = exception << 8;
>  if (env->cpucfgr & CPUCFGR_EVBARP) {
>  vect_pc |= env->evbar;
>  }
> @@ -70,7 +90,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
>  }
>  env->pc = vect_pc;
>  } else {
> -cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
> +cpu_abort(cs, "Unhandled exception 0x%x\n", exception);
>  }
>  #endif
>  
> 



Re: [Qemu-devel] [PATCH] vhost-blk: turn on pre-defined RO feature bit

2018-05-27 Thread Liu, Changpeng


> -Original Message-
> From: Stefan Hajnoczi [mailto:stefa...@redhat.com]
> Sent: Friday, May 25, 2018 6:20 PM
> To: Liu, Changpeng 
> Cc: qemu-devel@nongnu.org; m...@redhat.com
> Subject: Re: [PATCH] vhost-blk: turn on pre-defined RO feature bit
> 
> On Tue, May 22, 2018 at 02:39:28PM +, Liu, Changpeng wrote:
> >
> >
> > > -Original Message-
> > > From: Stefan Hajnoczi [mailto:stefa...@redhat.com]
> > > Sent: Tuesday, May 22, 2018 6:11 AM
> > > To: Liu, Changpeng 
> > > Cc: qemu-devel@nongnu.org; m...@redhat.com
> > > Subject: Re: [PATCH] vhost-blk: turn on pre-defined RO feature bit
> > >
> > > On Sat, May 19, 2018 at 06:20:16AM +0800, Changpeng Liu wrote:
> > > > Read only feature shouldn't be negotiable, because if the
> > > > backend device reported Read only feature supported, QEMU
> > > > host driver shouldn't change backend's RO attribute.
> > >
> > > I don't understand this patch.
> > >
> > > Does it make *all* virtio-blk devices read-only?
> > If the slave target reported RO feature, the disk in OS should be RO, 
> > currently
> > users should specify in QEMU command to enable RO.
> > >
> > > Or is the idea that the vhost-user slave has to clear the read-only bit
> > > if it is a writable device?
> > Exactly.
> 
> Thanks for explaining!
> 
> Please implement the read-only bit in contrib/vhost-user-blk we it can
> be tested.
Sounds good, will add the test together.
> 
> Thanks,
> Stefan



Re: [Qemu-devel] [PATCH] bochs-display: add missing break

2018-05-27 Thread Philippe Mathieu-Daudé
On 05/25/2018 01:53 AM, Gerd Hoffmann wrote:
> Fixes: CID 1391291
> Signed-off-by: Gerd Hoffmann 
> ---
>  hw/display/bochs-display.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c
> index c33524b558..1187d77576 100644
> --- a/hw/display/bochs-display.c
> +++ b/hw/display/bochs-display.c
> @@ -158,6 +158,7 @@ static int bochs_display_get_mode(BochsDisplayState *s,
>  /* best effort: support native endianess only */
>  mode->format = PIXMAN_r5g6b5;
>  mode->bytepp = 2;
> +break;

Reviewed-by: Philippe Mathieu-Daudé 

>  case 32:
>  mode->format = s->big_endian_fb
>  ? PIXMAN_BE_x8r8g8b8
> 



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH 00/20] target/openrisc improvements

2018-05-27 Thread no-reply
Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20180527141324.11937-1-richard.hender...@linaro.org
Subject: [Qemu-devel] [PATCH 00/20] target/openrisc improvements

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 t [tag update]patchew/20180525015042.31778-1-pet...@redhat.com -> 
patchew/20180525015042.31778-1-pet...@redhat.com
 t [tag update]patchew/20180525045344.28347-1-kra...@redhat.com -> 
patchew/20180525045344.28347-1-kra...@redhat.com
 t [tag update]
patchew/20180525153609.13187-1-marcandre.lur...@redhat.com -> 
patchew/20180525153609.13187-1-marcandre.lur...@redhat.com
 * [new tag]   
patchew/20180527141324.11937-1-richard.hender...@linaro.org -> 
patchew/20180527141324.11937-1-richard.hender...@linaro.org
Switched to a new branch 'test'
b9df0fdbbe target/or1k: Add support in scripts/qemu-binfmt-conf.sh
c17f7f48a0 target/openrisc: Add print_insn_or1k
2772ab0c8a target/openrisc: Reorg tlb lookup
3539987243 target/openrisc: Increase the TLB size
13446b9a88 target/openrisc: Log interrupts
762299f6ac target/openrisc: Stub out handle_mmu_fault for softmmu
e0b5725c60 target/openrisc: Use identical sizes for ITLB and DTLB
a363ba96f1 target/openrisc: Fix cpu_mmu_index
b6ec1f027c target/openrisc: Fix tlb flushing in mtspr
b0a589f797 target/openrisc: Reduce tlb to a single dimension
9e167a3b2e target/openrisc: Merge mmu_helper.c into mmu.c
15484f4429 target/openrisc: Remove indirect function calls for mmu
460253a4f3 target/openrisc: Merge tlb allocation into CPUOpenRISCState
40d1a2a12a target/openrisc: Form the spr index from tcg
5338b1f67e target/openrisc: Exit the TB after l.mtspr
c2d6b769e5 target/openrisc: Split out is_user
9bbb13a008 target/openrisc: Link more translation blocks
6714d16f2a target/openrisc: Fix singlestep_enabled
c4d2a9b70b target/openrisc: Use exit_tb instead of CPU_INTERRUPT_EXITTB
2eb8680a11 target/openrisc: Remove DISAS_JUMP & DISAS_TB_JUMP

=== OUTPUT BEGIN ===
Checking PATCH 1/20: target/openrisc: Remove DISAS_JUMP & DISAS_TB_JUMP...
Checking PATCH 2/20: target/openrisc: Use exit_tb instead of 
CPU_INTERRUPT_EXITTB...
Checking PATCH 3/20: target/openrisc: Fix singlestep_enabled...
Checking PATCH 4/20: target/openrisc: Link more translation blocks...
ERROR: space prohibited between function name and open parenthesis '('
#138: FILE: target/openrisc/translate.c:1453:
+tcg_gen_lookup_and_goto_ptr ();

ERROR: space prohibited between function name and open parenthesis '('
#155: FILE: target/openrisc/translate.c:1469:
+tcg_gen_lookup_and_goto_ptr ();

total: 2 errors, 0 warnings, 143 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 5/20: target/openrisc: Split out is_user...
Checking PATCH 6/20: target/openrisc: Exit the TB after l.mtspr...
Checking PATCH 7/20: target/openrisc: Form the spr index from tcg...
Checking PATCH 8/20: target/openrisc: Merge tlb allocation into 
CPUOpenRISCState...
Checking PATCH 9/20: target/openrisc: Remove indirect function calls for mmu...
Checking PATCH 10/20: target/openrisc: Merge mmu_helper.c into mmu.c...
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#45: 
deleted file mode 100644

total: 0 errors, 1 warnings, 23 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 11/20: target/openrisc: Reduce tlb to a single dimension...
ERROR: spaces required around that '-' (ctx:VxV)
#92: FILE: target/openrisc/mmu.c:68:
+*physical = (tr & TARGET_PAGE_MASK) | (address & (TARGET_PAGE_SIZE-1));
   ^

ERROR: spaces required around that '-' (ctx:VxV)
#136: FILE: target/openrisc/mmu.c:111:
+*physical = (tr & TARGET_PAGE_MASK) | (address & (TARGET_PAGE_SIZE-1));
   ^

total: 2 errors, 0 warnings, 169 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 12/20: target/openrisc: Fix 

[Qemu-devel] [PATCH 16/20] target/openrisc: Log interrupts

2018-05-27 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/openrisc/interrupt.c | 30 +-
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index e28042856a..138ad17f00 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -32,6 +32,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 #ifndef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = OPENRISC_CPU(cs);
 CPUOpenRISCState *env = >env;
+int exception = cs->exception_index;
 
 env->epcr = env->pc;
 if (env->dflag) {
@@ -41,12 +42,12 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 } else {
 env->sr &= ~SR_DSX;
 }
-if (cs->exception_index == EXCP_SYSCALL) {
+if (exception == EXCP_SYSCALL) {
 env->epcr += 4;
 }
 /* When we have an illegal instruction the error effective address
shall be set to the illegal instruction address.  */
-if (cs->exception_index == EXCP_ILLEGAL) {
+if (exception == EXCP_ILLEGAL) {
 env->eear = env->pc;
 }
 
@@ -60,8 +61,27 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 env->pmr &= ~PMR_SME;
 env->lock_addr = -1;
 
-if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
-hwaddr vect_pc = cs->exception_index << 8;
+if (exception > 0 && exception < EXCP_NR) {
+static const char * const int_name[EXCP_NR] = {
+[EXCP_RESET]= "RESET",
+[EXCP_BUSERR]   = "BUSERR (bus error)",
+[EXCP_DPF]  = "DFP (data protection fault)",
+[EXCP_IPF]  = "IPF (code protection fault)",
+[EXCP_TICK] = "TICK (timer interrupt)",
+[EXCP_ALIGN]= "ALIGN",
+[EXCP_ILLEGAL]  = "ILLEGAL",
+[EXCP_INT]  = "INT (device interrupt)",
+[EXCP_DTLBMISS] = "DTLBMISS (data tlb miss)",
+[EXCP_ITLBMISS] = "ITLBMISS (code tlb miss)",
+[EXCP_RANGE]= "RANGE",
+[EXCP_SYSCALL]  = "SYSCALL",
+[EXCP_FPE]  = "FPE",
+[EXCP_TRAP] = "TRAP",
+};
+
+qemu_log_mask(CPU_LOG_INT, "INT: %s\n", int_name[exception]);
+
+hwaddr vect_pc = exception << 8;
 if (env->cpucfgr & CPUCFGR_EVBARP) {
 vect_pc |= env->evbar;
 }
@@ -70,7 +90,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 }
 env->pc = vect_pc;
 } else {
-cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
+cpu_abort(cs, "Unhandled exception 0x%x\n", exception);
 }
 #endif
 
-- 
2.17.0




[Qemu-devel] [PATCH 12/20] target/openrisc: Fix tlb flushing in mtspr

2018-05-27 Thread Richard Henderson
The previous code was confused, avoiding the flush of the old entry
if the new entry is invalid.  We need to flush the old page if the
old entry is valid and the new page if the new entry is valid.

This bug was masked by over-flushing elsewhere.

Signed-off-by: Richard Henderson 
---
 target/openrisc/sys_helper.c | 21 +++--
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index 8ad7a7d898..e00aaa332e 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -32,6 +32,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 #ifndef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
 CPUState *cs = CPU(cpu);
+target_ulong mr;
 int idx;
 
 switch (spr) {
@@ -84,12 +85,15 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 
 case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
 idx = spr - TO_SPR(1, 512);
-if (!(rb & 1)) {
-tlb_flush_page(cs, env->tlb.dtlb[idx].mr & TARGET_PAGE_MASK);
+mr = env->tlb.dtlb[idx].mr;
+if (mr & 1) {
+tlb_flush_page(cs, mr & TARGET_PAGE_MASK);
+}
+if (rb & 1) {
+tlb_flush_page(cs, rb & TARGET_PAGE_MASK);
 }
 env->tlb.dtlb[idx].mr = rb;
 break;
-
 case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
 idx = spr - TO_SPR(1, 640);
 env->tlb.dtlb[idx].tr = rb;
@@ -101,14 +105,18 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
 case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
 break;
+
 case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1):   /* ITLBW0MR 0-127 */
 idx = spr - TO_SPR(2, 512);
-if (!(rb & 1)) {
-tlb_flush_page(cs, env->tlb.itlb[idx].mr & TARGET_PAGE_MASK);
+mr = env->tlb.itlb[idx].mr;
+if (mr & 1) {
+tlb_flush_page(cs, mr & TARGET_PAGE_MASK);
+}
+if (rb & 1) {
+tlb_flush_page(cs, rb & TARGET_PAGE_MASK);
 }
 env->tlb.itlb[idx].mr = rb;
 break;
-
 case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
 idx = spr - TO_SPR(2, 640);
 env->tlb.itlb[idx].tr = rb;
@@ -120,6 +128,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
 case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
 break;
+
 case TO_SPR(5, 1):  /* MACLO */
 env->mac = deposit64(env->mac, 0, 32, rb);
 break;
-- 
2.17.0




[Qemu-devel] [PATCH 10/20] target/openrisc: Merge mmu_helper.c into mmu.c

2018-05-27 Thread Richard Henderson
With tlb_fill in mmu.c, we can simplify things further.

Signed-off-by: Richard Henderson 
---
 target/openrisc/mmu.c | 11 ++
 target/openrisc/mmu_helper.c  | 40 ---
 target/openrisc/Makefile.objs |  2 +-
 3 files changed, 12 insertions(+), 41 deletions(-)
 delete mode 100644 target/openrisc/mmu_helper.c

diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index b2effaa6d7..9b4b5cf04f 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -240,4 +240,15 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, 
vaddr addr)
 return phys_addr;
 }
 }
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+  MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+int ret = openrisc_cpu_handle_mmu_fault(cs, addr, size,
+access_type, mmu_idx);
+if (ret) {
+/* Raise Exception.  */
+cpu_loop_exit_restore(cs, retaddr);
+}
+}
 #endif
diff --git a/target/openrisc/mmu_helper.c b/target/openrisc/mmu_helper.c
deleted file mode 100644
index 97e1d17b5a..00
--- a/target/openrisc/mmu_helper.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * OpenRISC MMU helper routines
- *
- * Copyright (c) 2011-2012 Jia Liu 
- * Zhizhou Zhang 
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see .
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/exec-all.h"
-#include "exec/cpu_ldst.h"
-
-#ifndef CONFIG_USER_ONLY
-
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
-  MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
-int ret;
-
-ret = openrisc_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
-
-if (ret) {
-/* Raise Exception.  */
-cpu_loop_exit_restore(cs, retaddr);
-}
-}
-#endif
diff --git a/target/openrisc/Makefile.objs b/target/openrisc/Makefile.objs
index 1b98a911ea..957ce02199 100644
--- a/target/openrisc/Makefile.objs
+++ b/target/openrisc/Makefile.objs
@@ -1,7 +1,7 @@
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
 obj-y += exception_helper.o fpu_helper.o \
- interrupt_helper.o mmu_helper.o sys_helper.o
+ interrupt_helper.o sys_helper.o
 obj-y += gdbstub.o
 
 DECODETREE = $(SRC_PATH)/scripts/decodetree.py
-- 
2.17.0




[Qemu-devel] [PATCH 18/20] target/openrisc: Reorg tlb lookup

2018-05-27 Thread Richard Henderson
While openrisc has a split i/d tlb, qemu does not.  Perform a
lookup on both i & d tlbs in parallel and put the composite
rights into qemu's tlb.  This avoids ping-ponging the qemu tlb
between EXEC and READ.

Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h |   8 --
 target/openrisc/mmu.c | 254 +++---
 2 files changed, 90 insertions(+), 172 deletions(-)

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index 8035654087..1efffa5269 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -237,14 +237,6 @@ enum {
 UXE = (1 << 7),
 };
 
-/* check if tlb available */
-enum {
-TLBRET_INVALID = -3,
-TLBRET_NOMATCH = -2,
-TLBRET_BADADDR = -1,
-TLBRET_MATCH = 0
-};
-
 typedef struct OpenRISCTLBEntry {
 uint32_t mr;
 uint32_t tr;
diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index 2f1f16fd6b..9a7170779d 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -29,148 +29,78 @@
 #endif
 
 #ifndef CONFIG_USER_ONLY
-static inline int get_phys_nommu(hwaddr *physical, int *prot,
- target_ulong address)
+static inline void get_phys_nommu(hwaddr *phys_addr, int *prot,
+  target_ulong address)
 {
-*physical = address;
+*phys_addr = address;
 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-return TLBRET_MATCH;
 }
 
-static int get_phys_code(OpenRISCCPU *cpu, hwaddr *physical, int *prot,
- target_ulong address, int rw, bool supervisor)
+static int get_phys_mmu(OpenRISCCPU *cpu, hwaddr *phys_addr, int *prot,
+target_ulong addr, int need, bool super)
 {
-int vpn = address >> TARGET_PAGE_BITS;
-int idx = vpn & TLB_MASK;
-int right = 0;
-uint32_t mr = cpu->env.tlb.itlb[idx].mr;
-uint32_t tr = cpu->env.tlb.itlb[idx].tr;
+int idx = (addr >> TARGET_PAGE_BITS) & TLB_MASK;
+uint32_t imr = cpu->env.tlb.itlb[idx].mr;
+uint32_t itr = cpu->env.tlb.itlb[idx].tr;
+uint32_t dmr = cpu->env.tlb.dtlb[idx].mr;
+uint32_t dtr = cpu->env.tlb.dtlb[idx].tr;
+int right, match, valid;
 
-if ((mr >> TARGET_PAGE_BITS) != vpn) {
-return TLBRET_NOMATCH;
-}
-if (!(mr & 1)) {
-return TLBRET_INVALID;
-}
-if (supervisor) {
-if (tr & SXE) {
-right |= PAGE_EXEC;
-}
-} else {
-if (tr & UXE) {
-right |= PAGE_EXEC;
+/* If the ITLB and DTLB indexes map to the same page, we want to
+   load all permissions all at once.  If the destination pages do
+   not match, zap the one we don't need.  */
+if (unlikely((itr ^ dtr) & TARGET_PAGE_MASK)) {
+if (need & PAGE_EXEC) {
+dmr = dtr = 0;
+} else {
+imr = itr = 0;
 }
 }
-if ((rw & 2) && ((right & PAGE_EXEC) == 0)) {
-return TLBRET_BADADDR;
-}
 
-*physical = (tr & TARGET_PAGE_MASK) | (address & (TARGET_PAGE_SIZE-1));
+/* Check if either of the entries matches the source address.  */
+match  = (imr ^ addr) & TARGET_PAGE_MASK ? 0 : PAGE_EXEC;
+match |= (dmr ^ addr) & TARGET_PAGE_MASK ? 0 : PAGE_READ | PAGE_WRITE;
+
+/* Check if either of the entries is valid.  */
+valid  = imr & 1 ? PAGE_EXEC : 0;
+valid |= dmr & 1 ? PAGE_READ | PAGE_WRITE : 0;
+valid &= match;
+
+/* Collect the permissions from the entries.  */
+right  = itr & (super ? SXE : UXE) ? PAGE_EXEC : 0;
+right |= dtr & (super ? SRE : URE) ? PAGE_READ : 0;
+right |= dtr & (super ? SWE : UWE) ? PAGE_WRITE : 0;
+right &= valid;
+
+/* Note that above we validated that itr and dtr match on page.
+   So oring them together changes nothing without having to
+   check which one we needed.  We also want to store to these
+   variables even on failure, as it avoids compiler warnings.  */
+*phys_addr = ((itr | dtr) & TARGET_PAGE_MASK) | (addr & ~TARGET_PAGE_MASK);
 *prot = right;
-return TLBRET_MATCH;
-}
 
-static int get_phys_data(OpenRISCCPU *cpu, hwaddr *physical, int *prot,
- target_ulong address, int rw, bool supervisor)
-{
-int vpn = address >> TARGET_PAGE_BITS;
-int idx = vpn & TLB_MASK;
-int right = 0;
-uint32_t mr = cpu->env.tlb.dtlb[idx].mr;
-uint32_t tr = cpu->env.tlb.dtlb[idx].tr;
+qemu_log_mask(CPU_LOG_MMU,
+  "MMU lookup: need %d match %d valid %d right %d -> %s\n",
+  need, match, valid, right, (need & right) ? "OK" : "FAIL");
 
-if ((mr >> TARGET_PAGE_BITS) != vpn) {
-return TLBRET_NOMATCH;
+/* Check the collective permissions are present.  */
+if (likely(need & right)) {
+return 0;  /* success! */
 }
-if (!(mr & 1)) {
-return TLBRET_INVALID;
-}
-if (supervisor) {
-if (tr & SRE) {
-right |= PAGE_READ;
-}
-if (tr & SWE) {
-

[Qemu-devel] [PATCH 20/20] target/or1k: Add support in scripts/qemu-binfmt-conf.sh

2018-05-27 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 scripts/qemu-binfmt-conf.sh | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
index 7ab7435fbd..75ed7c6b65 100755
--- a/scripts/qemu-binfmt-conf.sh
+++ b/scripts/qemu-binfmt-conf.sh
@@ -1,10 +1,10 @@
 #!/bin/sh
-# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC/s390/HPPA/Xtensa/microblaze
-# program execution by the kernel
+# Enable automatic program execution by the kernel.
 
 qemu_target_list="i386 i486 alpha arm armeb sparc32plus ppc ppc64 ppc64le m68k 
\
 mips mipsel mipsn32 mipsn32el mips64 mips64el \
-sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb 
microblaze microblazeel"
+sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
+microblaze microblazeel or1k"
 
 
i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
 
i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
@@ -124,6 +124,10 @@ 
microblazeel_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\
 
microblazeel_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
 microblazeel_family=microblazeel
 
+or1k_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5c'
+or1k_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
+or1k_family=or1k
+
 qemu_get_family() {
 cpu=${HOST_ARCH:-$(uname -m)}
 case "$cpu" in
-- 
2.17.0




[Qemu-devel] [PATCH 09/20] target/openrisc: Remove indirect function calls for mmu

2018-05-27 Thread Richard Henderson
There is no reason to use an indirect branch instead
of simply testing the SR bits that control mmu state.

Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h  | 11 -
 target/openrisc/cpu.c  |  4 --
 target/openrisc/interrupt.c|  2 -
 target/openrisc/interrupt_helper.c | 25 ++-
 target/openrisc/machine.c  | 26 
 target/openrisc/mmu.c  | 66 +-
 target/openrisc/sys_helper.c   | 15 ---
 7 files changed, 31 insertions(+), 118 deletions(-)

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index edc06be40e..13107058cb 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -378,17 +378,6 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu);
 void cpu_openrisc_timer_update(OpenRISCCPU *cpu);
 void cpu_openrisc_count_start(OpenRISCCPU *cpu);
 void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
-
-void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
-int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
-hwaddr *physical,
-int *prot, target_ulong address, int rw);
-int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu,
-   hwaddr *physical,
-   int *prot, target_ulong address, int rw);
-int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
-   hwaddr *physical,
-   int *prot, target_ulong address, int rw);
 #endif
 
 #define OPENRISC_CPU_TYPE_SUFFIX "-" TYPE_OPENRISC_CPU
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 20b115afae..b2711a961e 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -88,10 +88,6 @@ static void openrisc_cpu_initfn(Object *obj)
 OpenRISCCPU *cpu = OPENRISC_CPU(obj);
 
 cs->env_ptr = >env;
-
-#ifndef CONFIG_USER_ONLY
-cpu_openrisc_mmu_init(cpu);
-#endif
 }
 
 /* CPU models */
diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index 8b8b14ace0..d9cb363fea 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -62,8 +62,6 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 env->sr &= ~SR_TEE;
 env->pmr &= ~PMR_DME;
 env->pmr &= ~PMR_SME;
-env->tlb.cpu_openrisc_map_address_data = _openrisc_get_phys_nommu;
-env->tlb.cpu_openrisc_map_address_code = _openrisc_get_phys_nommu;
 env->lock_addr = -1;
 
 if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
diff --git a/target/openrisc/interrupt_helper.c 
b/target/openrisc/interrupt_helper.c
index dc97b38704..a2e9003969 100644
--- a/target/openrisc/interrupt_helper.c
+++ b/target/openrisc/interrupt_helper.c
@@ -29,31 +29,12 @@ void HELPER(rfe)(CPUOpenRISCState *env)
 #ifndef CONFIG_USER_ONLY
 int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^
  (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
-#endif
-cpu->env.pc = cpu->env.epcr;
-cpu_set_sr(>env, cpu->env.esr);
-cpu->env.lock_addr = -1;
-
-#ifndef CONFIG_USER_ONLY
-if (cpu->env.sr & SR_DME) {
-cpu->env.tlb.cpu_openrisc_map_address_data =
-_openrisc_get_phys_data;
-} else {
-cpu->env.tlb.cpu_openrisc_map_address_data =
-_openrisc_get_phys_nommu;
-}
-
-if (cpu->env.sr & SR_IME) {
-cpu->env.tlb.cpu_openrisc_map_address_code =
-_openrisc_get_phys_code;
-} else {
-cpu->env.tlb.cpu_openrisc_map_address_code =
-_openrisc_get_phys_nommu;
-}
-
 if (need_flush_tlb) {
 CPUState *cs = CPU(cpu);
 tlb_flush(cs);
 }
 #endif
+cpu->env.pc = cpu->env.epcr;
+cpu->env.lock_addr = -1;
+cpu_set_sr(>env, cpu->env.esr);
 }
diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
index c10d28b055..73e0abcfd7 100644
--- a/target/openrisc/machine.c
+++ b/target/openrisc/machine.c
@@ -24,31 +24,6 @@
 #include "hw/boards.h"
 #include "migration/cpu.h"
 
-static int env_post_load(void *opaque, int version_id)
-{
-CPUOpenRISCState *env = opaque;
-
-/* Restore MMU handlers */
-if (env->sr & SR_DME) {
-env->tlb.cpu_openrisc_map_address_data =
-_openrisc_get_phys_data;
-} else {
-env->tlb.cpu_openrisc_map_address_data =
-_openrisc_get_phys_nommu;
-}
-
-if (env->sr & SR_IME) {
-env->tlb.cpu_openrisc_map_address_code =
-_openrisc_get_phys_code;
-} else {
-env->tlb.cpu_openrisc_map_address_code =
-_openrisc_get_phys_nommu;
-}
-
-
-return 0;
-}
-
 static const VMStateDescription vmstate_tlb_entry = {
 .name = "tlb_entry",
 .version_id = 1,
@@ -102,7 +77,6 @@ static const VMStateDescription vmstate_env = {
 .name = "env",
 .version_id = 6,
 .minimum_version_id = 6,
-.post_load = env_post_load,
 .fields = (VMStateField[]) {
 VMSTATE_UINTTL_2DARRAY(shadow_gpr, 

[Qemu-devel] [PATCH 19/20] target/openrisc: Add print_insn_or1k

2018-05-27 Thread Richard Henderson
Rather than emit disassembly while translating, reuse the
generated decoder to build a separate disassembler.

Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h |   1 +
 target/openrisc/cpu.c |   6 ++
 target/openrisc/disas.c   | 171 ++
 target/openrisc/translate.c   | 114 ---
 target/openrisc/Makefile.objs |   3 +-
 5 files changed, 180 insertions(+), 115 deletions(-)
 create mode 100644 target/openrisc/disas.c

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index 1efffa5269..f1b31bc24a 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -348,6 +348,7 @@ void openrisc_translate_init(void);
 int openrisc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size,
   int rw, int mmu_idx);
 int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
+int print_insn_or1k(bfd_vma addr, disassemble_info *info);
 
 #define cpu_list cpu_openrisc_list
 #define cpu_signal_handler cpu_openrisc_signal_handler
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 75c83d15d1..d1ef4c737c 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -36,6 +36,11 @@ static bool openrisc_cpu_has_work(CPUState *cs)
 CPU_INTERRUPT_TIMER);
 }
 
+static void openrisc_disas_set_info(CPUState *cpu, disassemble_info *info)
+{
+info->print_insn = print_insn_or1k;
+}
+
 /* CPUClass::reset() */
 static void openrisc_cpu_reset(CPUState *s)
 {
@@ -151,6 +156,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void 
*data)
 #endif
 cc->gdb_num_core_regs = 32 + 3;
 cc->tcg_initialize = openrisc_translate_init;
+cc->disas_set_info = openrisc_disas_set_info;
 }
 
 /* Sort alphabetically by type name, except for "any". */
diff --git a/target/openrisc/disas.c b/target/openrisc/disas.c
new file mode 100644
index 00..db0caa1805
--- /dev/null
+++ b/target/openrisc/disas.c
@@ -0,0 +1,171 @@
+/*
+ * OpenRISC disassembler
+ *
+ * Copyright (c) 2018 Richard Henderson 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "disas/bfd.h"
+#include "qemu/bitops.h"
+#include "cpu.h"
+
+typedef disassemble_info DisasContext;
+
+/* Include the auto-generated decoder.  */
+#include "decode.inc.c"
+
+#define output(mnemonic, format, ...) \
+info->fprintf_func(info->stream, "%-9s " format, \
+   mnemonic, ##__VA_ARGS__)
+
+int print_insn_or1k(bfd_vma addr, disassemble_info *info)
+{
+bfd_byte buffer[4];
+uint32_t insn;
+int status;
+
+status = info->read_memory_func(addr, buffer, 4, info);
+if (status != 0)
+  {
+info->memory_error_func(status, addr, info);
+return -1;
+  }
+insn = bfd_getb32(buffer);
+
+if (!decode(info, insn)) {
+output(".long", "%#08x", insn);
+}
+return 4;
+}
+
+#define INSN(opcode, format, ...) \
+static bool trans_l_##opcode(disassemble_info *info,\
+arg_l_##opcode *a, uint32_t insn)   \
+{   \
+output("l." #opcode, format, ##__VA_ARGS__);\
+return true;\
+}
+
+INSN(add,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(addc,   "r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(sub,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(and,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(or, "r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(xor,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(sll,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(srl,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(sra,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(ror,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(exths,  "r%d, r%d", a->d, a->a)
+INSN(extbs,  "r%d, r%d", a->d, a->a)
+INSN(exthz,  "r%d, r%d", a->d, a->a)
+INSN(extbz,  "r%d, r%d", a->d, a->a)
+INSN(cmov,   "r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(ff1,"r%d, r%d", a->d, a->a)
+INSN(fl1,"r%d, r%d", a->d, a->a)
+INSN(mul,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(mulu,   "r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(div,"r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(divu,   "r%d, r%d, r%d", a->d, a->a, a->b)
+INSN(muld,   "r%d, r%d", a->a, a->b)
+INSN(muldu,  "r%d, r%d", 

[Qemu-devel] [PATCH 17/20] target/openrisc: Increase the TLB size

2018-05-27 Thread Richard Henderson
The architecture supports 128 TLB entries.  There is no reason
not to provide all of them.  In the process we need to fix a
bug that failed to parameterize the configuration register that
tells the operating system the number of entries.

Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h | 2 +-
 target/openrisc/cpu.c | 6 --
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index 53abe965e8..8035654087 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -222,7 +222,7 @@ enum {
 
 /* TLB size */
 enum {
-TLB_SIZE = 64,
+TLB_SIZE = 128,
 TLB_MASK = TLB_SIZE - 1,
 };
 
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index b2711a961e..75c83d15d1 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -53,8 +53,10 @@ static void openrisc_cpu_reset(CPUState *s)
 
 cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP |
UPR_PMP;
-cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
-cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
+cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2))
+  | (DMMUCFGR_NTS & (ctz32(TLB_SIZE) << 2));
+cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2))
+  | (IMMUCFGR_NTS & (ctz32(TLB_SIZE) << 2));
 
 #ifndef CONFIG_USER_ONLY
 cpu->env.picmr = 0x;
-- 
2.17.0




[Qemu-devel] [PATCH 13/20] target/openrisc: Fix cpu_mmu_index

2018-05-27 Thread Richard Henderson
The code in cpu_mmu_index does not properly honor SR_DME.
This bug has workarounds elsewhere in that we flush the
tlb more often than necessary, on the state changes that
should be reflected in a change of mmu_index.

Fixing this means that we can respect the mmu_index that
is given to tlb_flush.

Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h  | 23 +
 target/openrisc/interrupt.c|  4 
 target/openrisc/interrupt_helper.c | 15 +++---
 target/openrisc/mmu.c  | 33 +++---
 target/openrisc/sys_helper.c   |  4 
 target/openrisc/translate.c|  2 +-
 6 files changed, 49 insertions(+), 32 deletions(-)

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index 947ca00d8d..c48802ad8f 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -384,9 +384,12 @@ void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
 
 #include "exec/cpu-all.h"
 
-#define TB_FLAGS_DFLAG 1
-#define TB_FLAGS_R0_0  2
+#define TB_FLAGS_SMSR_SM
+#define TB_FLAGS_DME   SR_DME
+#define TB_FLAGS_IME   SR_IME
 #define TB_FLAGS_OVE   SR_OVE
+#define TB_FLAGS_DFLAG 2  /* reuse SR_TEE */
+#define TB_FLAGS_R0_0  4  /* reuse SR_IEE */
 
 static inline uint32_t cpu_get_gpr(const CPUOpenRISCState *env, int i)
 {
@@ -404,17 +407,21 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState 
*env,
 {
 *pc = env->pc;
 *cs_base = 0;
-*flags = (env->dflag
-  | (cpu_get_gpr(env, 0) == 0 ? TB_FLAGS_R0_0 : 0)
-  | (env->sr & SR_OVE));
+*flags = (env->dflag ? TB_FLAGS_DFLAG : 0)
+   | (cpu_get_gpr(env, 0) ? 0 : TB_FLAGS_R0_0)
+   | (env->sr & (SR_SM | SR_DME | SR_IME | SR_OVE));
 }
 
 static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
 {
-if (!(env->sr & SR_IME)) {
-return MMU_NOMMU_IDX;
+int ret = MMU_NOMMU_IDX;  /* mmu is disabled */
+
+if (env->sr & (ifetch ? SR_IME : SR_DME)) {
+/* The mmu is enabled; test supervisor state.  */
+ret = env->sr & SR_SM ? MMU_SUPERVISOR_IDX : MMU_USER_IDX;
 }
-return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
+
+return ret;
 }
 
 static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env)
diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index d9cb363fea..e28042856a 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -50,10 +50,6 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 env->eear = env->pc;
 }
 
-/* For machine-state changed between user-mode and supervisor mode,
-   we need flush TLB when we enter EXCP.  */
-tlb_flush(cs);
-
 env->esr = cpu_get_sr(env);
 env->sr &= ~SR_DME;
 env->sr &= ~SR_IME;
diff --git a/target/openrisc/interrupt_helper.c 
b/target/openrisc/interrupt_helper.c
index a2e9003969..9c5489f5f7 100644
--- a/target/openrisc/interrupt_helper.c
+++ b/target/openrisc/interrupt_helper.c
@@ -25,16 +25,7 @@
 
 void HELPER(rfe)(CPUOpenRISCState *env)
 {
-OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-#ifndef CONFIG_USER_ONLY
-int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^
- (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
-if (need_flush_tlb) {
-CPUState *cs = CPU(cpu);
-tlb_flush(cs);
-}
-#endif
-cpu->env.pc = cpu->env.epcr;
-cpu->env.lock_addr = -1;
-cpu_set_sr(>env, cpu->env.esr);
+env->pc = env->epcr;
+env->lock_addr = -1;
+cpu_set_sr(env, env->esr);
 }
diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index 23edd8c78c..11b8187cda 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -246,9 +246,36 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, 
vaddr addr)
 void tlb_fill(CPUState *cs, target_ulong addr, int size,
   MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
 {
-int ret = openrisc_cpu_handle_mmu_fault(cs, addr, size,
-access_type, mmu_idx);
-if (ret) {
+OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+int ret, prot = 0;
+hwaddr physical = 0;
+
+if (mmu_idx == MMU_NOMMU_IDX) {
+ret = get_phys_nommu(, , addr);
+} else {
+bool super = mmu_idx == MMU_SUPERVISOR_IDX;
+if (access_type == MMU_INST_FETCH) {
+ret = get_phys_code(cpu, , , addr, 2, super);
+} else {
+ret = get_phys_data(cpu, , , addr,
+access_type == MMU_DATA_STORE, super);
+}
+}
+
+if (ret == TLBRET_MATCH) {
+tlb_set_page(cs, addr & TARGET_PAGE_MASK,
+ physical & TARGET_PAGE_MASK, prot,
+ mmu_idx, TARGET_PAGE_SIZE);
+} else if (ret < 0) {
+int rw;
+if (access_type == MMU_INST_FETCH) {
+rw = 2;
+} else if (access_type == MMU_DATA_STORE) {
+rw = 1;
+} 

[Qemu-devel] [PATCH 15/20] target/openrisc: Stub out handle_mmu_fault for softmmu

2018-05-27 Thread Richard Henderson
This hook is only used by CONFIG_USER_ONLY.

Signed-off-by: Richard Henderson 
---
 target/openrisc/mmu.c | 35 +--
 1 file changed, 5 insertions(+), 30 deletions(-)

diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index ee3016a8b9..2f1f16fd6b 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -177,42 +177,17 @@ static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU 
*cpu,
 cpu->env.lock_addr = -1;
 }
 
-#ifndef CONFIG_USER_ONLY
 int openrisc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
   int rw, int mmu_idx)
 {
+#ifdef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = OPENRISC_CPU(cs);
-int ret = 0;
-hwaddr physical = 0;
-int prot = 0;
-
-ret = get_phys_addr(cpu, , , address, rw);
-
-if (ret == TLBRET_MATCH) {
-tlb_set_page(cs, address & TARGET_PAGE_MASK,
- physical & TARGET_PAGE_MASK, prot,
- mmu_idx, TARGET_PAGE_SIZE);
-ret = 0;
-} else if (ret < 0) {
-cpu_openrisc_raise_mmu_exception(cpu, address, rw, ret);
-ret = 1;
-}
-
-return ret;
-}
+cpu_openrisc_raise_mmu_exception(cpu, address, rw, 0);
+return 1;
 #else
-int openrisc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
-  int rw, int mmu_idx)
-{
-OpenRISCCPU *cpu = OPENRISC_CPU(cs);
-int ret = 0;
-
-cpu_openrisc_raise_mmu_exception(cpu, address, rw, ret);
-ret = 1;
-
-return ret;
-}
+g_assert_not_reached ();
 #endif
+}
 
 #ifndef CONFIG_USER_ONLY
 hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
-- 
2.17.0




[Qemu-devel] [PATCH 05/20] target/openrisc: Split out is_user

2018-05-27 Thread Richard Henderson
This allows us to limit the amount of ifdefs and isolate
the test for usermode.

Signed-off-by: Richard Henderson 
---
 target/openrisc/translate.c | 27 ---
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index a8afb9a562..61e6deef69 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -54,6 +54,15 @@ typedef struct DisasContext {
 target_ulong jmp_pc_imm;
 } DisasContext;
 
+static inline bool is_user(DisasContext *dc)
+{
+#ifdef CONFIG_USER_ONLY
+return true;
+#else
+return dc->mem_idx == MMU_USER_IDX;
+#endif
+}
+
 /* Include the auto-generated decoder.  */
 #include "decode.inc.c"
 
@@ -914,17 +923,13 @@ static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr 
*a, uint32_t insn)
 LOG_DIS("l.mfspr r%d, r%d, %d\n", a->d, a->a, a->k);
 check_r0_write(a->d);
 
-#ifdef CONFIG_USER_ONLY
-gen_illegal_exception(dc);
-#else
-if (dc->mem_idx == MMU_USER_IDX) {
+if (is_user(dc)) {
 gen_illegal_exception(dc);
 } else {
 TCGv_i32 ti = tcg_const_i32(a->k);
 gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti);
 tcg_temp_free_i32(ti);
 }
-#endif
 return true;
 }
 
@@ -932,17 +937,13 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr 
*a, uint32_t insn)
 {
 LOG_DIS("l.mtspr r%d, r%d, %d\n", a->a, a->b, a->k);
 
-#ifdef CONFIG_USER_ONLY
-gen_illegal_exception(dc);
-#else
-if (dc->mem_idx == MMU_USER_IDX) {
+if (is_user(dc)) {
 gen_illegal_exception(dc);
 } else {
 TCGv_i32 ti = tcg_const_i32(a->k);
 gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti);
 tcg_temp_free_i32(ti);
 }
-#endif
 return true;
 }
 
@@ -1204,16 +1205,12 @@ static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a, 
uint32_t insn)
 {
 LOG_DIS("l.rfe\n");
 
-#ifdef CONFIG_USER_ONLY
-gen_illegal_exception(dc);
-#else
-if (dc->mem_idx == MMU_USER_IDX) {
+if (is_user(dc)) {
 gen_illegal_exception(dc);
 } else {
 gen_helper_rfe(cpu_env);
 dc->base.is_jmp = DISAS_EXIT;
 }
-#endif
 return true;
 }
 
-- 
2.17.0




[Qemu-devel] [PATCH 11/20] target/openrisc: Reduce tlb to a single dimension

2018-05-27 Thread Richard Henderson
While we had defines for *_WAY, we didn't define more than 1.
Reduce the complexity by eliminating this unused dimension.

Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h|  6 ++
 target/openrisc/machine.c|  6 ++
 target/openrisc/mmu.c| 30 --
 target/openrisc/sys_helper.c | 20 ++--
 4 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index 13107058cb..947ca00d8d 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -222,10 +222,8 @@ enum {
 
 /* TLB size */
 enum {
-DTLB_WAYS = 1,
 DTLB_SIZE = 64,
 DTLB_MASK = (DTLB_SIZE-1),
-ITLB_WAYS = 1,
 ITLB_SIZE = 64,
 ITLB_MASK = (ITLB_SIZE-1),
 };
@@ -256,8 +254,8 @@ typedef struct OpenRISCTLBEntry {
 
 #ifndef CONFIG_USER_ONLY
 typedef struct CPUOpenRISCTLBContext {
-OpenRISCTLBEntry itlb[ITLB_WAYS][ITLB_SIZE];
-OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE];
+OpenRISCTLBEntry itlb[ITLB_SIZE];
+OpenRISCTLBEntry dtlb[DTLB_SIZE];
 
 int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
  hwaddr *physical,
diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
index 73e0abcfd7..b795b56dc6 100644
--- a/target/openrisc/machine.c
+++ b/target/openrisc/machine.c
@@ -42,11 +42,9 @@ static const VMStateDescription vmstate_cpu_tlb = {
 .minimum_version_id = 1,
 .minimum_version_id_old = 1,
 .fields = (VMStateField[]) {
-VMSTATE_STRUCT_2DARRAY(itlb, CPUOpenRISCTLBContext,
- ITLB_WAYS, ITLB_SIZE, 0,
+VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, ITLB_SIZE, 0,
  vmstate_tlb_entry, OpenRISCTLBEntry),
-VMSTATE_STRUCT_2DARRAY(dtlb, CPUOpenRISCTLBContext,
- DTLB_WAYS, DTLB_SIZE, 0,
+VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, DTLB_SIZE, 0,
  vmstate_tlb_entry, OpenRISCTLBEntry),
 VMSTATE_END_OF_LIST()
 }
diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index 9b4b5cf04f..23edd8c78c 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -43,19 +43,21 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr 
*physical, int *prot,
 int vpn = address >> TARGET_PAGE_BITS;
 int idx = vpn & ITLB_MASK;
 int right = 0;
+uint32_t mr = cpu->env.tlb.itlb[idx].mr;
+uint32_t tr = cpu->env.tlb.itlb[idx].tr;
 
-if ((cpu->env.tlb.itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
+if ((mr >> TARGET_PAGE_BITS) != vpn) {
 return TLBRET_NOMATCH;
 }
-if (!(cpu->env.tlb.itlb[0][idx].mr & 1)) {
+if (!(mr & 1)) {
 return TLBRET_INVALID;
 }
 if (supervisor) {
-if (cpu->env.tlb.itlb[0][idx].tr & SXE) {
+if (tr & SXE) {
 right |= PAGE_EXEC;
 }
 } else {
-if (cpu->env.tlb.itlb[0][idx].tr & UXE) {
+if (tr & UXE) {
 right |= PAGE_EXEC;
 }
 }
@@ -63,8 +65,7 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr *physical, 
int *prot,
 return TLBRET_BADADDR;
 }
 
-*physical = (cpu->env.tlb.itlb[0][idx].tr & TARGET_PAGE_MASK) |
-(address & (TARGET_PAGE_SIZE-1));
+*physical = (tr & TARGET_PAGE_MASK) | (address & (TARGET_PAGE_SIZE-1));
 *prot = right;
 return TLBRET_MATCH;
 }
@@ -75,25 +76,27 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr 
*physical, int *prot,
 int vpn = address >> TARGET_PAGE_BITS;
 int idx = vpn & DTLB_MASK;
 int right = 0;
+uint32_t mr = cpu->env.tlb.dtlb[idx].mr;
+uint32_t tr = cpu->env.tlb.dtlb[idx].tr;
 
-if ((cpu->env.tlb.dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
+if ((mr >> TARGET_PAGE_BITS) != vpn) {
 return TLBRET_NOMATCH;
 }
-if (!(cpu->env.tlb.dtlb[0][idx].mr & 1)) {
+if (!(mr & 1)) {
 return TLBRET_INVALID;
 }
 if (supervisor) {
-if (cpu->env.tlb.dtlb[0][idx].tr & SRE) {
+if (tr & SRE) {
 right |= PAGE_READ;
 }
-if (cpu->env.tlb.dtlb[0][idx].tr & SWE) {
+if (tr & SWE) {
 right |= PAGE_WRITE;
 }
 } else {
-if (cpu->env.tlb.dtlb[0][idx].tr & URE) {
+if (tr & URE) {
 right |= PAGE_READ;
 }
-if (cpu->env.tlb.dtlb[0][idx].tr & UWE) {
+if (tr & UWE) {
 right |= PAGE_WRITE;
 }
 }
@@ -105,8 +108,7 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr 
*physical, int *prot,
 return TLBRET_BADADDR;
 }
 
-*physical = (cpu->env.tlb.dtlb[0][idx].tr & TARGET_PAGE_MASK) |
-(address & (TARGET_PAGE_SIZE-1));
+*physical = (tr & TARGET_PAGE_MASK) | (address & (TARGET_PAGE_SIZE-1));
 *prot = right;
 return TLBRET_MATCH;
 }
diff --git a/target/openrisc/sys_helper.c 

[Qemu-devel] [PATCH 08/20] target/openrisc: Merge tlb allocation into CPUOpenRISCState

2018-05-27 Thread Richard Henderson
There is no reason to allocate this separately.  This was probably
copied from target/mips which makes the same mistake.

While doing so, move tlb into the clear-on-reset range.  While not
all of the TLB bits are guaranteed zero on reset, all of the valid
bits are cleared, and the rest of the bits are unspecified.
Therefore clearing the whole of the TLB is correct.

Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h  |  6 --
 target/openrisc/interrupt.c|  4 ++--
 target/openrisc/interrupt_helper.c |  8 +++
 target/openrisc/machine.c  | 15 ++---
 target/openrisc/mmu.c  | 34 ++
 target/openrisc/sys_helper.c   | 28 
 6 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index 35cab65f11..edc06be40e 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -301,6 +301,10 @@ typedef struct CPUOpenRISCState {
 
 uint32_t dflag;   /* In delay slot (boolean) */
 
+#ifndef CONFIG_USER_ONLY
+CPUOpenRISCTLBContext tlb;
+#endif
+
 /* Fields up to this point are cleared by a CPU reset */
 struct {} end_reset_fields;
 
@@ -310,8 +314,6 @@ typedef struct CPUOpenRISCState {
 uint32_t cpucfgr; /* CPU configure register */
 
 #ifndef CONFIG_USER_ONLY
-CPUOpenRISCTLBContext * tlb;
-
 QEMUTimer *timer;
 uint32_t ttmr;  /* Timer tick mode register */
 int is_counting;
diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index 3959671c59..8b8b14ace0 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -62,8 +62,8 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 env->sr &= ~SR_TEE;
 env->pmr &= ~PMR_DME;
 env->pmr &= ~PMR_SME;
-env->tlb->cpu_openrisc_map_address_data = _openrisc_get_phys_nommu;
-env->tlb->cpu_openrisc_map_address_code = _openrisc_get_phys_nommu;
+env->tlb.cpu_openrisc_map_address_data = _openrisc_get_phys_nommu;
+env->tlb.cpu_openrisc_map_address_code = _openrisc_get_phys_nommu;
 env->lock_addr = -1;
 
 if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
diff --git a/target/openrisc/interrupt_helper.c 
b/target/openrisc/interrupt_helper.c
index b865738f8b..dc97b38704 100644
--- a/target/openrisc/interrupt_helper.c
+++ b/target/openrisc/interrupt_helper.c
@@ -36,18 +36,18 @@ void HELPER(rfe)(CPUOpenRISCState *env)
 
 #ifndef CONFIG_USER_ONLY
 if (cpu->env.sr & SR_DME) {
-cpu->env.tlb->cpu_openrisc_map_address_data =
+cpu->env.tlb.cpu_openrisc_map_address_data =
 _openrisc_get_phys_data;
 } else {
-cpu->env.tlb->cpu_openrisc_map_address_data =
+cpu->env.tlb.cpu_openrisc_map_address_data =
 _openrisc_get_phys_nommu;
 }
 
 if (cpu->env.sr & SR_IME) {
-cpu->env.tlb->cpu_openrisc_map_address_code =
+cpu->env.tlb.cpu_openrisc_map_address_code =
 _openrisc_get_phys_code;
 } else {
-cpu->env.tlb->cpu_openrisc_map_address_code =
+cpu->env.tlb.cpu_openrisc_map_address_code =
 _openrisc_get_phys_nommu;
 }
 
diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
index 0a793eb14d..c10d28b055 100644
--- a/target/openrisc/machine.c
+++ b/target/openrisc/machine.c
@@ -30,18 +30,18 @@ static int env_post_load(void *opaque, int version_id)
 
 /* Restore MMU handlers */
 if (env->sr & SR_DME) {
-env->tlb->cpu_openrisc_map_address_data =
+env->tlb.cpu_openrisc_map_address_data =
 _openrisc_get_phys_data;
 } else {
-env->tlb->cpu_openrisc_map_address_data =
+env->tlb.cpu_openrisc_map_address_data =
 _openrisc_get_phys_nommu;
 }
 
 if (env->sr & SR_IME) {
-env->tlb->cpu_openrisc_map_address_code =
+env->tlb.cpu_openrisc_map_address_code =
 _openrisc_get_phys_code;
 } else {
-env->tlb->cpu_openrisc_map_address_code =
+env->tlb.cpu_openrisc_map_address_code =
 _openrisc_get_phys_nommu;
 }
 
@@ -77,10 +77,6 @@ static const VMStateDescription vmstate_cpu_tlb = {
 }
 };
 
-#define VMSTATE_CPU_TLB(_f, _s) \
-VMSTATE_STRUCT_POINTER(_f, _s, vmstate_cpu_tlb, CPUOpenRISCTLBContext)
-
-
 static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
 {
 CPUOpenRISCState *env = opaque;
@@ -143,7 +139,8 @@ static const VMStateDescription vmstate_env = {
 VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
 VMSTATE_UINT64(mac, CPUOpenRISCState),
 
-VMSTATE_CPU_TLB(tlb, CPUOpenRISCState),
+VMSTATE_STRUCT(tlb, CPUOpenRISCState, 1,
+   vmstate_cpu_tlb, CPUOpenRISCTLBContext),
 
 VMSTATE_TIMER_PTR(timer, CPUOpenRISCState),
 VMSTATE_UINT32(ttmr, CPUOpenRISCState),
diff --git a/target/openrisc/mmu.c 

[Qemu-devel] [PATCH 03/20] target/openrisc: Fix singlestep_enabled

2018-05-27 Thread Richard Henderson
We failed to store to cpu_pc before raising the exception,
which caused us to re-execute the same insn that we stepped.

Signed-off-by: Richard Henderson 
---
 target/openrisc/translate.c | 35 +--
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index dae673afa4..e566be6d3c 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1449,31 +1449,30 @@ static void openrisc_tr_tb_stop(DisasContextBase 
*dcbase, CPUState *cs)
 {
 DisasContext *dc = container_of(dcbase, DisasContext, base);
 
+/* If we have already exited the TB, nothing following has effect.  */
+if (dc->base.is_jmp == DISAS_NORETURN) {
+return;
+}
+
 if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
 tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
 }
 
 tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4);
-if (dc->base.is_jmp == DISAS_NEXT) {
-dc->base.is_jmp = DISAS_UPDATE;
-tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
-}
-if (unlikely(dc->base.singlestep_enabled)) {
-gen_exception(dc, EXCP_DEBUG);
-} else {
-switch (dc->base.is_jmp) {
-case DISAS_TOO_MANY:
-gen_goto_tb(dc, 0, dc->base.pc_next);
-break;
-case DISAS_NORETURN:
-break;
-case DISAS_UPDATE:
-case DISAS_EXIT:
+switch (dc->base.is_jmp) {
+case DISAS_TOO_MANY:
+gen_goto_tb(dc, 0, dc->base.pc_next);
+break;
+case DISAS_UPDATE:
+case DISAS_EXIT:
+if (unlikely(dc->base.singlestep_enabled)) {
+gen_exception(dc, EXCP_DEBUG);
+} else {
 tcg_gen_exit_tb(0);
-break;
-default:
-g_assert_not_reached();
 }
+break;
+default:
+g_assert_not_reached();
 }
 }
 
-- 
2.17.0




[Qemu-devel] [PATCH 04/20] target/openrisc: Link more translation blocks

2018-05-27 Thread Richard Henderson
Track direct jumps via dc->jmp_pc_imm.  Use that in
preference to jmp_pc when possible.  Emit goto_tb in
that case, and lookup_and_goto_tb otherwise.

Signed-off-by: Richard Henderson 
---
 target/openrisc/translate.c | 82 +
 1 file changed, 46 insertions(+), 36 deletions(-)

diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index e566be6d3c..a8afb9a562 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -42,13 +42,16 @@
 
 /* is_jmp field values */
 #define DISAS_EXITDISAS_TARGET_0  /* force exit to main loop */
-#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_JUMPDISAS_TARGET_1  /* exit via jmp_pc/jmp_pc_imm */
 
 typedef struct DisasContext {
 DisasContextBase base;
 uint32_t mem_idx;
 uint32_t tb_flags;
 uint32_t delayed_branch;
+
+/* If not -1, jmp_pc contains this value and so is a direct jump.  */
+target_ulong jmp_pc_imm;
 } DisasContext;
 
 /* Include the auto-generated decoder.  */
@@ -164,34 +167,6 @@ static void check_ov64s(DisasContext *dc)
 }   \
 } while (0)
 
-static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
-{
-if (unlikely(dc->base.singlestep_enabled)) {
-return false;
-}
-
-#ifndef CONFIG_USER_ONLY
-return (dc->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
-#else
-return true;
-#endif
-}
-
-static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
-{
-if (use_goto_tb(dc, dest)) {
-tcg_gen_movi_tl(cpu_pc, dest);
-tcg_gen_goto_tb(n);
-tcg_gen_exit_tb((uintptr_t)dc->base.tb + n);
-} else {
-tcg_gen_movi_tl(cpu_pc, dest);
-if (dc->base.singlestep_enabled) {
-gen_exception(dc, EXCP_DEBUG);
-}
-tcg_gen_exit_tb(0);
-}
-}
-
 static void gen_ove_cy(DisasContext *dc)
 {
 if (dc->tb_flags & SR_OVE) {
@@ -655,6 +630,7 @@ static bool trans_l_j(DisasContext *dc, arg_l_j *a, 
uint32_t insn)
 
 LOG_DIS("l.j %d\n", a->n);
 tcg_gen_movi_tl(jmp_pc, tmp_pc);
+dc->jmp_pc_imm = tmp_pc;
 dc->delayed_branch = 2;
 return true;
 }
@@ -669,6 +645,7 @@ static bool trans_l_jal(DisasContext *dc, arg_l_jal *a, 
uint32_t insn)
 /* Optimize jal being used to load the PC for PIC.  */
 if (tmp_pc != ret_pc) {
 tcg_gen_movi_tl(jmp_pc, tmp_pc);
+dc->jmp_pc_imm = tmp_pc;
 dc->delayed_branch = 2;
 }
 return true;
@@ -1381,6 +1358,8 @@ static void 
openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
 dc->mem_idx = cpu_mmu_index(env, false);
 dc->tb_flags = dc->base.tb->flags;
 dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
+dc->jmp_pc_imm = -1;
+
 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
 dc->base.max_insns = MIN(dc->base.max_insns, bound);
 }
@@ -1437,10 +1416,7 @@ static void openrisc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 if (dc->delayed_branch) {
 dc->delayed_branch--;
 if (!dc->delayed_branch) {
-tcg_gen_mov_tl(cpu_pc, jmp_pc);
-tcg_gen_discard_tl(jmp_pc);
-dc->base.is_jmp = DISAS_UPDATE;
-return;
+dc->base.is_jmp = DISAS_JUMP;
 }
 }
 }
@@ -1448,22 +1424,56 @@ static void openrisc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
 {
 DisasContext *dc = container_of(dcbase, DisasContext, base);
+target_ulong jmp_dest;
 
 /* If we have already exited the TB, nothing following has effect.  */
 if (dc->base.is_jmp == DISAS_NORETURN) {
 return;
 }
 
+/* Adjust the delayed branch state for the next TB.  */
 if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
 tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
 }
 
-tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4);
+/* For DISAS_TOO_MANY, jump to the next insn.  */
+jmp_dest = dc->base.pc_next;
+tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
+
 switch (dc->base.is_jmp) {
+case DISAS_JUMP:
+jmp_dest = dc->jmp_pc_imm;
+if (jmp_dest == -1) {
+/* The jump destination is indirect/computed; use jmp_pc.  */
+tcg_gen_mov_tl(cpu_pc, jmp_pc);
+tcg_gen_discard_tl(jmp_pc);
+if (unlikely(dc->base.singlestep_enabled)) {
+gen_exception(dc, EXCP_DEBUG);
+} else {
+tcg_gen_lookup_and_goto_ptr ();
+}
+break;
+}
+/* The jump destination is direct; use jmp_pc_imm.
+   However, we will have stored into jmp_pc as well;
+   we know now that it wasn't needed.  */
+tcg_gen_discard_tl(jmp_pc);
+/* fallthru */
+
 case DISAS_TOO_MANY:
-

[Qemu-devel] [PATCH 06/20] target/openrisc: Exit the TB after l.mtspr

2018-05-27 Thread Richard Henderson
A store to SR changes interrupt state, which should return
to the main loop to recognize that state.

Signed-off-by: Richard Henderson 
---
 target/openrisc/translate.c | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index 61e6deef69..c7bfb395b0 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -940,9 +940,31 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr 
*a, uint32_t insn)
 if (is_user(dc)) {
 gen_illegal_exception(dc);
 } else {
-TCGv_i32 ti = tcg_const_i32(a->k);
+TCGv_i32 ti;
+
+/* For SR, we will need to exit the TB to recognize the new
+ * exception state.  For NPC, in theory this counts as a branch
+ * (although the SPR only exists for use by an ICE).  Save all
+ * of the cpu state first, allowing it to be overwritten.
+ */
+if (dc->tb_flags & TB_FLAGS_DFLAG) {
+tcg_gen_movi_i32(cpu_dflag, 0);
+}
+tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next);
+tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
+
+ti = tcg_const_i32(a->k);
 gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti);
 tcg_temp_free_i32(ti);
+
+/* For PPC, we want the value that was just written and not
+   the generic update that we'd get from DISAS_EXIT.  */
+if (unlikely(dc->base.singlestep_enabled)) {
+gen_exception(dc, EXCP_DEBUG);
+} else {
+tcg_gen_exit_tb(0);
+}
+dc->base.is_jmp = DISAS_NORETURN;
 }
 return true;
 }
-- 
2.17.0




[Qemu-devel] [PATCH 14/20] target/openrisc: Use identical sizes for ITLB and DTLB

2018-05-27 Thread Richard Henderson
The sizes are already the same, however, we can improve things
if they are identical by design.

Signed-off-by: Richard Henderson 
---
 target/openrisc/cpu.h| 10 --
 target/openrisc/machine.c|  4 ++--
 target/openrisc/mmu.c|  4 ++--
 target/openrisc/sys_helper.c | 16 
 4 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index c48802ad8f..53abe965e8 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -222,10 +222,8 @@ enum {
 
 /* TLB size */
 enum {
-DTLB_SIZE = 64,
-DTLB_MASK = (DTLB_SIZE-1),
-ITLB_SIZE = 64,
-ITLB_MASK = (ITLB_SIZE-1),
+TLB_SIZE = 64,
+TLB_MASK = TLB_SIZE - 1,
 };
 
 /* TLB prot */
@@ -254,8 +252,8 @@ typedef struct OpenRISCTLBEntry {
 
 #ifndef CONFIG_USER_ONLY
 typedef struct CPUOpenRISCTLBContext {
-OpenRISCTLBEntry itlb[ITLB_SIZE];
-OpenRISCTLBEntry dtlb[DTLB_SIZE];
+OpenRISCTLBEntry itlb[TLB_SIZE];
+OpenRISCTLBEntry dtlb[TLB_SIZE];
 
 int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
  hwaddr *physical,
diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
index b795b56dc6..3fc837b925 100644
--- a/target/openrisc/machine.c
+++ b/target/openrisc/machine.c
@@ -42,9 +42,9 @@ static const VMStateDescription vmstate_cpu_tlb = {
 .minimum_version_id = 1,
 .minimum_version_id_old = 1,
 .fields = (VMStateField[]) {
-VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, ITLB_SIZE, 0,
+VMSTATE_STRUCT_ARRAY(itlb, CPUOpenRISCTLBContext, TLB_SIZE, 0,
  vmstate_tlb_entry, OpenRISCTLBEntry),
-VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, DTLB_SIZE, 0,
+VMSTATE_STRUCT_ARRAY(dtlb, CPUOpenRISCTLBContext, TLB_SIZE, 0,
  vmstate_tlb_entry, OpenRISCTLBEntry),
 VMSTATE_END_OF_LIST()
 }
diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index 11b8187cda..ee3016a8b9 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -41,7 +41,7 @@ static int get_phys_code(OpenRISCCPU *cpu, hwaddr *physical, 
int *prot,
  target_ulong address, int rw, bool supervisor)
 {
 int vpn = address >> TARGET_PAGE_BITS;
-int idx = vpn & ITLB_MASK;
+int idx = vpn & TLB_MASK;
 int right = 0;
 uint32_t mr = cpu->env.tlb.itlb[idx].mr;
 uint32_t tr = cpu->env.tlb.itlb[idx].tr;
@@ -74,7 +74,7 @@ static int get_phys_data(OpenRISCCPU *cpu, hwaddr *physical, 
int *prot,
  target_ulong address, int rw, bool supervisor)
 {
 int vpn = address >> TARGET_PAGE_BITS;
-int idx = vpn & DTLB_MASK;
+int idx = vpn & TLB_MASK;
 int right = 0;
 uint32_t mr = cpu->env.tlb.dtlb[idx].mr;
 uint32_t tr = cpu->env.tlb.dtlb[idx].tr;
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index 0a74c9522f..7254aa9830 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -79,7 +79,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 idx = (spr - 1024);
 env->shadow_gpr[idx / 32][idx % 32] = rb;
 
-case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
+case TO_SPR(1, 512) ... TO_SPR(1, 512 + TLB_SIZE - 1): /* DTLBW0MR 0-127 */
 idx = spr - TO_SPR(1, 512);
 mr = env->tlb.dtlb[idx].mr;
 if (mr & 1) {
@@ -90,7 +90,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 }
 env->tlb.dtlb[idx].mr = rb;
 break;
-case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
+case TO_SPR(1, 640) ... TO_SPR(1, 640 + TLB_SIZE - 1): /* DTLBW0TR 0-127 */
 idx = spr - TO_SPR(1, 640);
 env->tlb.dtlb[idx].tr = rb;
 break;
@@ -102,7 +102,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
 break;
 
-case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1):   /* ITLBW0MR 0-127 */
+case TO_SPR(2, 512) ... TO_SPR(2, 512 + TLB_SIZE - 1): /* ITLBW0MR 0-127 */
 idx = spr - TO_SPR(2, 512);
 mr = env->tlb.itlb[idx].mr;
 if (mr & 1) {
@@ -113,7 +113,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 }
 env->tlb.itlb[idx].mr = rb;
 break;
-case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
+case TO_SPR(2, 640) ... TO_SPR(2, 640 + TLB_SIZE - 1): /* ITLBW0TR 0-127 */
 idx = spr - TO_SPR(2, 640);
 env->tlb.itlb[idx].tr = rb;
 break;
@@ -246,11 +246,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 idx = (spr - 1024);
 return env->shadow_gpr[idx / 32][idx % 32];
 
-case TO_SPR(1, 512) ... TO_SPR(1, 

[Qemu-devel] [PATCH 07/20] target/openrisc: Form the spr index from tcg

2018-05-27 Thread Richard Henderson
Rather than pass base+offset to the helper, pass the full index.
In most cases the base is r0 and optimization yields a constant.

Signed-off-by: Richard Henderson 
---
 target/openrisc/helper.h |  4 ++--
 target/openrisc/sys_helper.c |  9 +++--
 target/openrisc/translate.c  | 16 +---
 3 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h
index e37dabc77a..9db9bf3963 100644
--- a/target/openrisc/helper.h
+++ b/target/openrisc/helper.h
@@ -56,5 +56,5 @@ FOP_CMP(le)
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
 
 /* sys */
-DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
-DEF_HELPER_FLAGS_4(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl, tl)
+DEF_HELPER_FLAGS_3(mtspr, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl)
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index b284064381..a8d287d6ef 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -27,13 +27,11 @@
 
 #define TO_SPR(group, number) (((group) << 11) + (number))
 
-void HELPER(mtspr)(CPUOpenRISCState *env,
-   target_ulong ra, target_ulong rb, target_ulong offset)
+void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
 {
 #ifndef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
 CPUState *cs = CPU(cpu);
-int spr = (ra | offset);
 int idx;
 
 switch (spr) {
@@ -201,13 +199,12 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
 #endif
 }
 
-target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
-   target_ulong rd, target_ulong ra, uint32_t offset)
+target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
+   target_ulong spr)
 {
 #ifndef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
 CPUState *cs = CPU(cpu);
-int spr = (ra | offset);
 int idx;
 
 switch (spr) {
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index c7bfb395b0..b26c473870 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -926,9 +926,10 @@ static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr 
*a, uint32_t insn)
 if (is_user(dc)) {
 gen_illegal_exception(dc);
 } else {
-TCGv_i32 ti = tcg_const_i32(a->k);
-gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti);
-tcg_temp_free_i32(ti);
+TCGv spr = tcg_temp_new();
+tcg_gen_ori_tl(spr, cpu_R[a->a], a->k);
+gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], spr);
+tcg_temp_free(spr);
 }
 return true;
 }
@@ -940,7 +941,7 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, 
uint32_t insn)
 if (is_user(dc)) {
 gen_illegal_exception(dc);
 } else {
-TCGv_i32 ti;
+TCGv spr;
 
 /* For SR, we will need to exit the TB to recognize the new
  * exception state.  For NPC, in theory this counts as a branch
@@ -953,9 +954,10 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr 
*a, uint32_t insn)
 tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next);
 tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
 
-ti = tcg_const_i32(a->k);
-gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti);
-tcg_temp_free_i32(ti);
+spr = tcg_temp_new();
+tcg_gen_ori_tl(spr, cpu_R[a->a], a->k);
+gen_helper_mtspr(cpu_env, spr, cpu_R[a->b]);
+tcg_temp_free(spr);
 
 /* For PPC, we want the value that was just written and not
the generic update that we'd get from DISAS_EXIT.  */
-- 
2.17.0




[Qemu-devel] [PATCH 01/20] target/openrisc: Remove DISAS_JUMP & DISAS_TB_JUMP

2018-05-27 Thread Richard Henderson
These values are unused.

Signed-off-by: Richard Henderson 
---
 target/openrisc/translate.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index e7c96ca990..f4f2f37e28 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -41,9 +41,7 @@
   ## __VA_ARGS__)
 
 /* is_jmp field values */
-#define DISAS_JUMPDISAS_TARGET_0 /* only pc was modified dynamically */
 #define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
-#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
 
 typedef struct DisasContext {
 DisasContextBase base;
@@ -1467,8 +1465,6 @@ static void openrisc_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cs)
 gen_goto_tb(dc, 0, dc->base.pc_next);
 break;
 case DISAS_NORETURN:
-case DISAS_JUMP:
-case DISAS_TB_JUMP:
 break;
 case DISAS_UPDATE:
 /* indicate that the hash table must be used
-- 
2.17.0




[Qemu-devel] [PATCH 02/20] target/openrisc: Use exit_tb instead of CPU_INTERRUPT_EXITTB

2018-05-27 Thread Richard Henderson
No need to use the interrupt mechanisms when we can
simply exit the tb directly.

Signed-off-by: Richard Henderson 
---
 target/openrisc/interrupt_helper.c | 3 +--
 target/openrisc/translate.c| 6 +++---
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/target/openrisc/interrupt_helper.c 
b/target/openrisc/interrupt_helper.c
index 56620e0571..b865738f8b 100644
--- a/target/openrisc/interrupt_helper.c
+++ b/target/openrisc/interrupt_helper.c
@@ -26,7 +26,6 @@
 void HELPER(rfe)(CPUOpenRISCState *env)
 {
 OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-CPUState *cs = CPU(cpu);
 #ifndef CONFIG_USER_ONLY
 int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^
  (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
@@ -53,8 +52,8 @@ void HELPER(rfe)(CPUOpenRISCState *env)
 }
 
 if (need_flush_tlb) {
+CPUState *cs = CPU(cpu);
 tlb_flush(cs);
 }
 #endif
-cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index f4f2f37e28..dae673afa4 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -41,6 +41,7 @@
   ## __VA_ARGS__)
 
 /* is_jmp field values */
+#define DISAS_EXITDISAS_TARGET_0  /* force exit to main loop */
 #define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
 
 typedef struct DisasContext {
@@ -1233,7 +1234,7 @@ static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a, 
uint32_t insn)
 gen_illegal_exception(dc);
 } else {
 gen_helper_rfe(cpu_env);
-dc->base.is_jmp = DISAS_UPDATE;
+dc->base.is_jmp = DISAS_EXIT;
 }
 #endif
 return true;
@@ -1467,8 +1468,7 @@ static void openrisc_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cs)
 case DISAS_NORETURN:
 break;
 case DISAS_UPDATE:
-/* indicate that the hash table must be used
-   to find the next TB */
+case DISAS_EXIT:
 tcg_gen_exit_tb(0);
 break;
 default:
-- 
2.17.0




[Qemu-devel] [PATCH 00/20] target/openrisc improvements

2018-05-27 Thread Richard Henderson
This is almost a grab-bag of little improvements to the port.

patches 1-3:
  Fix singlestepping for gdbstub.  This has apparently never
  worked, as the first commit has the same bug of not advancing
  the pc when stepping.

patches 4-5:
  Exit the TB after l.mtspr insns.  In particular, storing to
  SR changes exception state so we want to return to the main
  loop to recognize any pending interrupts immediately.

patches 6-19:
  Reorganize TLB handling.  There is a fundamental bug that is
  fixed in patch 13.  However the bug has been hidden by extra
  TLB flushing elsewhere in the port.  I remove some unnecessary
  indirection that the port inherited from somewhere -- probably
  the MIPS port.  Finally, I present the QEMU TLB a unified view
  of the OpenRISC split I/D TLB.

patch 20:
  Split out disassembly from translation.

patch 21:
  Add qemu-or1k to qemu-binfmt-conf.sh.


r~


Richard Henderson (20):
  target/openrisc: Remove DISAS_JUMP & DISAS_TB_JUMP
  target/openrisc: Use exit_tb instead of CPU_INTERRUPT_EXITTB
  target/openrisc: Fix singlestep_enabled
  target/openrisc: Link more translation blocks
  target/openrisc: Split out is_user
  target/openrisc: Exit the TB after l.mtspr
  target/openrisc: Form the spr index from tcg
  target/openrisc: Merge tlb allocation into CPUOpenRISCState
  target/openrisc: Remove indirect function calls for mmu
  target/openrisc: Merge mmu_helper.c into mmu.c
  target/openrisc: Reduce tlb to a single dimension
  target/openrisc: Fix tlb flushing in mtspr
  target/openrisc: Fix cpu_mmu_index
  target/openrisc: Use identical sizes for ITLB and DTLB
  target/openrisc: Stub out handle_mmu_fault for softmmu
  target/openrisc: Log interrupts
  target/openrisc: Increase the TLB size
  target/openrisc: Reorg tlb lookup
  target/openrisc: Add print_insn_or1k
  target/or1k: Add support in scripts/qemu-binfmt-conf.sh

 target/openrisc/cpu.h  |  61 +++---
 target/openrisc/helper.h   |   4 +-
 target/openrisc/cpu.c  |  16 +-
 target/openrisc/disas.c| 171 +
 target/openrisc/interrupt.c|  36 ++--
 target/openrisc/interrupt_helper.c |  35 +---
 target/openrisc/machine.c  |  39 +---
 target/openrisc/mmu.c  | 275 ++
 target/openrisc/mmu_helper.c   |  40 
 target/openrisc/sys_helper.c   |  85 
 target/openrisc/translate.c| 298 ++---
 scripts/qemu-binfmt-conf.sh|  10 +-
 target/openrisc/Makefile.objs  |   5 +-
 13 files changed, 492 insertions(+), 583 deletions(-)
 create mode 100644 target/openrisc/disas.c
 delete mode 100644 target/openrisc/mmu_helper.c

-- 
2.17.0




[Qemu-devel] [Bug 1396052] Re: migration failed when running BurnInTest in guest

2018-05-27 Thread Thomas Huth
** Changed in: qemu
   Status: Incomplete => Triaged

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

Title:
  migration failed when running BurnInTest in guest

Status in QEMU:
  Triaged

Bug description:
  Hi,  
  I found a live migration problem and have found out the reason, but I can't 
fix it up myself. I really need help.
  When live migration vm and it's block device in save time, it will occur 
probabilistic .

  Step:
  1.  start a windows vm,and run burnInTest(it will write dirty data to block 
device in migration)
  2.  migrate vm with it's block device.
  3.  a few minutes later,  dest vm was killed and migration will be failed 
(probabilistic )

  Reason:
  when migraion start, in source host libvirt will send command to qemu,and 
qemu will call mirror_run coroutine to copy blcok device data to dest vm block 
device.mirror_run running in qemu main thread.   When this 
finished(actually it still running because in following steps,there may 
generate dirty data by vm), qemu will  start migration_thread to migration ram 
and other device.
  In dest vm, qemu will call "bdrv_invalidate_cache --> 
qcow2_invalidate_cache" function after vm read "QEMU_VM_EOF" byte. 
qcow2_invalidate_cache fuction call qcow2_close ,  in qcow2_close fuction set 
"s->l1_table = NULL" and then call qcow2_cache_flush fuction.   In 
qcow2_cache_flush fuction will call 
"bdrv_flush-->bdrv_flush_co_entry-->bdrv_co_flush-->qemu_coroutine_yield".   
This will let itself back to mian loop.   If source vm send block device dirty 
data to dest vm at this time, in dest vm will occur the following segmentation 
fault.
  The primary reason is mirror_run and migration run in two thread.  
although qemu stopping vm before write "QEMU_VM_EOF" byte, it still can't 
ensure mirror_run coroutine do not write dirty data  after migration thread  
sending "QEMU_VM_EOF" byte.

  
  Program received signal SIGSEGV, Segmentation fault.
  0x7f90d250db24 in get_cluster_table (bs=0x7f90d493f500, 
offset=1832189952, new_l2_table=0x7f8fbd6faa88, 
  new_l2_index=0x7f8fbd6faaa0) at block/qcow2-cluster.c:573
  573 l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK;
  (gdb) bt
  #0  0x7f90d250db24 in get_cluster_table (bs=0x7f90d493f500, 
offset=1832189952, new_l2_table=0x7f8fbd6faa88, 
  new_l2_index=0x7f8fbd6faaa0) at block/qcow2-cluster.c:573
  #1  0x7f90d250e577 in handle_copied (bs=0x7f90d493f500, 
guest_offset=1832189952, host_offset=0x7f8fbd6fab18, 
  bytes=0x7f8fbd6fab20, m=0x7f8fbd6fabc8) at block/qcow2-cluster.c:927
  #2  0x7f90d250ef45 in qcow2_alloc_cluster_offset (bs=0x7f90d493f500, 
offset=1832189952, num=0x7f8fbd6fabfc, 
  host_offset=0x7f8fbd6fabc0, m=0x7f8fbd6fabc8) at 
block/qcow2-cluster.c:1269
  #3  0x7f90d250445f in qcow2_co_writev (bs=0x7f90d493f500, 
sector_num=3578496, remaining_sectors=2040, 
  qiov=0x7f8fbd6fae90) at block/qcow2.c:1171
  #4  0x7f90d24d4764 in bdrv_aligned_pwritev (bs=0x7f90d493f500, 
req=0x7f8fbd6facd0, offset=1832189952, bytes=1044480, 
  qiov=0x7f8fbd6fae90, flags=0) at block.c:3321
  #5  0x7f90d24d4d21 in bdrv_co_do_pwritev (bs=0x7f90d493f500, 
offset=1832189952, bytes=1044480, qiov=0x7f8fbd6fae90, 
  flags=0) at block.c:3447
  #6  0x7f90d24d3115 in bdrv_rw_co_entry (opaque=0x7f8fbd6fae10) at 
block.c:2710
  #7  0x7f90d24d31e7 in bdrv_prwv_co (bs=0x7f90d493f500, offset=1832189952, 
qiov=0x7f8fbd6fae90, is_write=true, flags=0)
  at block.c:2746
  #8  0x7f90d24d32eb in bdrv_rw_co (bs=0x7f90d493f500, sector_num=3578496, 
  buf=0x7f90d4e3d400 
"\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037
 
!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312",
 ..., nb_sectors=2040, is_write=true, flags=0) at 
block.c:2776
  #9  0x7f90d24d3429 in bdrv_write (bs=0x7f90d493f500, sector_num=3578496, 
  buf=0x7f90d4e3d400 
"\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037
 
!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312",
 ..., nb_sectors=2040) at block.c:2810
  #10 0x7f90d24cc2b5 in nbd_trip (opaque=0x7f90d4ba9aa0) at 

Re: [Qemu-devel] [PATCH] configure: print virglrenderer version

2018-05-27 Thread Ján Tomko

On Fri, May 25, 2018 at 05:36:09PM +0200, Marc-André Lureau wrote:

Signed-off-by: Marc-André Lureau 
---
configure | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature


Re: [Qemu-devel] [PATCH] bochs-display: add missing break

2018-05-27 Thread Ján Tomko

On Fri, May 25, 2018 at 06:53:44AM +0200, Gerd Hoffmann wrote:

Fixes: CID 1391291
Signed-off-by: Gerd Hoffmann 
---
hw/display/bochs-display.c | 1 +
1 file changed, 1 insertion(+)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature


Re: [Qemu-devel] [PATCH] migration: use g_free for ram load bitmap

2018-05-27 Thread Ján Tomko

On Fri, May 25, 2018 at 09:50:42AM +0800, Peter Xu wrote:

Buffers allocated with bitmap_new() should be freed with g_free().

Both reported by Coverity:

*** CID 1391300:  API usage errors  (ALLOC_FREE_MISMATCH)
/migration/ram.c: 3517 in ram_dirty_bitmap_reload()
3511  * the last one to sync, we need to notify the main send thread.
3512  */
3513 ram_dirty_bitmap_reload_notify(s);
3514
3515 ret = 0;
3516 out:

CID 1391300:  API usage errors  (ALLOC_FREE_MISMATCH)
Calling "free" frees "le_bitmap" using "free" but it should have been freed using 
"g_free".

3517 free(le_bitmap);
3518 return ret;
3519 }
3520
3521 static int ram_resume_prepare(MigrationState *s, void *opaque)
3522 {

*** CID 1391292:  API usage errors  (ALLOC_FREE_MISMATCH)
/migration/ram.c: 249 in ramblock_recv_bitmap_send()
243  * Mark as an end, in case the middle part is screwed up due to
244  * some "misterious" reason.
245  */
246 qemu_put_be64(file, RAMBLOCK_RECV_BITMAP_ENDING);
247 qemu_fflush(file);
248

CID 1391292:  API usage errors  (ALLOC_FREE_MISMATCH)
Calling "free" frees "le_bitmap" using "free" but it should have been freed using 
"g_free".

249 free(le_bitmap);
250
251 if (qemu_file_get_error(file)) {
252 return qemu_file_get_error(file);
253 }
254

Signed-off-by: Peter Xu 
---
migration/ram.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature