[Qemu-devel] Prevent overriding the input file with the output file when using qemu-img

2018-01-22 Thread River Chiang
Signed-off-by: River Chiang 

-- qemu-img.c
--
index 68b375f998..5ce594ea00 100644
@@ -2098,6 +2098,9 @@ static int img_convert(int argc, char **argv)
 if (s.src_num < 1) {
 error_report("Must specify image file name");
 goto fail_getopt;
+} else if (!strcmp(argv[optind], out_filename)) {
+error_report("Override the input file with the output file");
+goto fail_getopt;
 }


[Qemu-devel] [Bug 1185311] Re: could not hot-remove disabled NIC from Win2012 guest by 'devel_del id1'

2018-01-22 Thread Thomas Huth
Triaging old bug tickets... can you still reproduce this issue with the
latest version of QEMU? Or could we close this ticket nowadays?

** Changed in: qemu
   Status: New => Incomplete

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

Title:
  could not hot-remove disabled NIC from Win2012 guest by 'devel_del
  id1'

Status in QEMU:
  Incomplete

Bug description:
  # qemu-latest-upstream -mon chardev=qmp,mode=control,pretty=on \
   -chardev socket,id=qmp,host=localhost,port=1234,server,nowait -vnc :0 \
   -monitor stdio /images/win2012-64-virtio.qcow2 \
   -device virtio-net-pci,netdev=ndev1,id=id1 -netdev tap,id=ndev1 \
   -device e1000,netdev=ndev2,id=id2 -netdev tap,id=ndev2 \
   -device rtl8139,netdev=ndev3,id=id3 -netdev tap,id=ndev3 \
   -smp 4 -m 3000 -usbdevice tablet

  If disable nic in guest's "Network Connections" panel, nic could not
  be hot-removed through qemu monitor.

  1) if disable nic in guest
  (qemu) devel_del id1 (nic still in "Network Connections". if enable nic, nic 
can work)
  (qemu) devel_del id1
  (qemu) devel_del id1

  2) if enable nic in guest
  (qemu) devel_del id1 (nic will be removed, disappear from "Network 
Connections")
  (qemu) devel_del id1
  Device 'id1' not found

  Could not reproduced this problem with all linux guests & other Windows guests
  Problem exists with virtio-nic/e1000/rtl8139, it seems the problem of 
pci-hotplug in piix4.

  Could not reproduce this problem with Vmware + win2012 guest.

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



[Qemu-devel] [Bug 1176366] Re: TCPIP not working on qemu 1.4.50 (master)

2018-01-22 Thread Thomas Huth
Triaging old bug tickets... can you still reproduce this issue with the
latest version of QEMU? Or could we close this ticket nowadays?

** Changed in: qemu
   Status: New => Incomplete

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

Title:
  TCPIP not working on qemu 1.4.50 (master)

Status in QEMU:
  Incomplete

Bug description:
  whenever I try, in the guest OS, in this case it's NT 3.1, to enable
  TCP/IP, it crashes the whole emulator. With either the ne2000 isa,
  ne2000 pci or PCnet, still crashes

  below is attached a screenshot.

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



Re: [Qemu-devel] [PATCH v3] chardev/char-socket: add POLLHUP handler

2018-01-22 Thread Peter Xu
On Fri, Jan 19, 2018 at 01:47:15PM +0300, Klim Kireev wrote:
> The following behavior was observed for QEMU configured by libvirt
> to use guest agent as usual for the guests without virtio-serial
> driver (Windows or the guest remaining in BIOS stage).
> 
> In QEMU on first connect to listen character device socket
> the listen socket is removed from poll just after the accept().
> virtio_serial_guest_ready() returns 0 and the descriptor
> of the connected Unix socket is removed from poll and it will
> not be present in poll() until the guest will initialize the driver
> and change the state of the serial to "guest connected".
> 
> In libvirt connect() to guest agent is performed on restart and
> is run under VM state lock. Connect() is blocking and can
> wait forever.
> In this case libvirt can not perform ANY operation on that VM.
> 
> The bug can be easily reproduced this way:
> 
> Terminal 1:
> qemu-system-x86_64 -m 512 -device pci-serial,chardev=serial1 -chardev 
> socket,id=serial1,path=/tmp/console.sock,server,nowait
> (virtio-serial and isa-serial also fit)
> 
> Terminal 2:
> minicom -D unix\#/tmp/console.sock
> (type something and press enter)
> C-a x (to exit)
> 
> Do 3 times:
> minicom -D unix\#/tmp/console.sock
> C-a x
> 
> It needs 4 connections, because the first one is accepted by QEMU, then two 
> are queued by
> the kernel, and the 4th blocks.
> 
> The problem is that QEMU doesn't add a read watcher after succesful read
> until the guest device wants to acquire recieved data, so
> I propose to install a separate pullhup watcher regardless of
> whether the device waits for data or not.
> 
> Signed-off-by: Klim Kireev 
> ---
> Changelog:
> v2: Remove timer as a redundant feature
> 
> v3: Remove read call and return G_SOURCE_REMOVE
> 
>  chardev/char-socket.c | 25 -
>  1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/chardev/char-socket.c b/chardev/char-socket.c
> index 77cdf487eb..83fa7b70f0 100644
> --- a/chardev/char-socket.c
> +++ b/chardev/char-socket.c
> @@ -42,6 +42,7 @@ typedef struct {
>  QIOChannel *ioc; /* Client I/O channel */
>  QIOChannelSocket *sioc; /* Client master channel */
>  QIONetListener *listener;
> +guint hup_tag;
>  QCryptoTLSCreds *tls_creds;
>  int connected;
>  int max_size;
> @@ -352,6 +353,11 @@ static void tcp_chr_free_connection(Chardev *chr)
>  s->read_msgfds_num = 0;
>  }
>  
> +if (s->hup_tag != 0) {
> +g_source_remove(s->hup_tag);

Note that recently we are preparing the chardev to support non-default
gcontext.  So IMHO we'd better start to use GSource always, instead of
the old tags. g_source_remove() is tailored for default gcontext only.

Please refer to 938eb9e9c8 ("chardev: let g_idle_add() be with chardev
gcontext", 2018-01-12) as an example.

So even if the current patch works for now, it may break in a very
unpredictable way if we start to run chardevs in non-default
gcontexts.  Thanks,

> +s->hup_tag = 0;
> +}
> +
>  tcp_set_msgfds(chr, NULL, 0);
>  remove_fd_in_watch(chr);
>  object_unref(OBJECT(s->sioc));
> @@ -455,6 +461,15 @@ static gboolean tcp_chr_read(QIOChannel *chan, 
> GIOCondition cond, void *opaque)
>  return TRUE;
>  }
>  
> +static gboolean tcp_chr_hup(QIOChannel *channel,
> +   GIOCondition cond,
> +   void *opaque)
> +{
> +Chardev *chr = CHARDEV(opaque);
> +tcp_chr_disconnect(chr);
> +return G_SOURCE_REMOVE;
> +}
> +
>  static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
>  {
>  SocketChardev *s = SOCKET_CHARDEV(chr);
> @@ -528,6 +543,10 @@ static void tcp_chr_connect(void *opaque)
> tcp_chr_read,
> chr, chr->gcontext);
>  }
> +if (s->hup_tag == 0) {
> +s->hup_tag = qio_channel_add_watch(s->ioc, G_IO_HUP,
> +   tcp_chr_hup, chr, NULL);

-- 
Peter Xu



Re: [Qemu-devel] [RFC PATCH 0/3] vfio: ccw: basic channel path event handling

2018-01-22 Thread Dong Jia Shi
* Halil Pasic  [2018-01-16 16:57:13 +0100]:

> 
> 
> On 01/15/2018 09:59 AM, Dong Jia Shi wrote:
> > * Halil Pasic  [2018-01-12 19:10:20 +0100]:
> > 
> >>
> >>
> >> On 01/11/2018 04:04 AM, Dong Jia Shi wrote:
> >>> What are still missing, thus need to be offered in the next version are:
> >>> - I/O termination and FSM state handling if currently we have I/O on the 
> >>> status
> >>>   switched path.
> >>> - Vary on/off event is not sensible to a guest.
> >>
> >> I don't see a doc update. We do have documentation (in
> >> Documentation/s390/vfio-ccw.txt) in which the uapi interface with the
> >> regions and their purpose/usage  is at least kind of explained. You are
> >> changing this interface without updating the doc.
> >>
> >> I would like to see documentation on this because I'm under the
> >> impression either the design is pretty convoluted or I did not
> >> get it at all.
> > Ah, I missed the documentation part. Thanks for pointing out. I will add
> > it in the next cycle.
> > 
> 
> I would have preferred having a doc update in this cycle. E.g. as
> an answer to the cover letter.
Ok. If you prefer this, let's try to clarify questions right here and
update documentations in the next review cycle (if there is any).

> 
> As previously pointed out I don't really understand your design.
> I wanted to avoid summarizing the design myself (that is my understanding
> of it), to then question the design.
Fair enough.

> 
> To give you a feeling of what I mean here some bullet points:
> * Channel paths are css level resources (simplified).
Yes, and it's the means for the machine to talk to the device.

> * When a channel path malfunctions a CRW is generated and a machine
> check channel report pending is generated. Same goes for
> channel paths popping up (on HW level). Should not these get
> propagated?
AFAIR, channel path related CRW is not that reliable. I mean it seems
that it's not mandatory to generate CRWs for channel path malfunctions.
AFAIU, it depneds on machine models. For example, we won't get
CRW_ERC_INIT for a "path has come" event on many models I believe. And
that's why nobody noticed the misuse of CRW_ERC_IPARM and CRW_ERC_INIT
in the CRW handling logic for channel path CRWs.
Ref:
2daace78a8c9 s390: chp: handle CRW_ERC_INIT for channel-path status change

So my understanding for this is: it really a design decision for us to
propagate all of the channel path CRWs, or we just use other ways (like
using PNO and PNOM as this series shows).

Of course, CRW propagation is good to have. But as a discussion result
of a former thread, that is something we can consider only after we have
a good channel path re-modelling. That is the problem. We can try to
trigger CRW event in some work of machine checks handling enhancement
later.

> * Kind of instead of the CRW you introduce a per device interrupt
> for channel path events on the qemu/kvm boundary. AFAIU for a chp
> event you do an STSCH for each (affected?) subchannel
Until here, yes and right.

> and generate an irq. Right? Why is this a good idea.
This is not right. This series does not generate an irq for the guest.
In QEMU, when it gets the notification of a channel path status change
event, it read the newest SCHIB from the schib region, and update the
SCHIB (patch related parts) for the virtual subchannel. The guest will
get the new SCHIB whenever it calls STSCH then.

I think this is a good idea, because:
1. This is complies the Linux implementation. Path status change could
   be noticed by Linux.
2. This provides enhancement with a small work. On the contrary, channel
   path re-modelling needs a lot of work.

> * SCHIB.PMCW provides path information relevant for a given device.
> This information is retrieved using store subchannel. Is your series
> sufficient for making store subchannel work properly (correct and
> reasonably up to date)?
Introducing a SCHIB region is the basis of further STSCH hanlding work.
This series depends on it, and only focuses on the update of the channel
path related parts of it. And for these parts, this work I think is
basically correct (more review comments are surely to be welcomed).

For the rest parts, this does not change anything than what have. As
replied to Conny in other mail of this thread: I think, if the other
fields are handled by QEMU well, then we don't need to trigger update
events for them. Currently I don't find things that need extra trigger.

> Regarding PMCW it's supposed to get updated when io functions are
> preformed by the css, AFAIR. Is that right?
I think so. And also for some other cases, for example, when we
configure on/off a channel path.

>  If yes what are the implications? Are the manipulations you do on
>  some PMCW fields architecturally correct?
If "architecturally correct" means what guest sees/senses is all obey to
the PoP, then I think so. We don't have to emulate the internal
behaviors (which could not be seen by OS) 

[Qemu-devel] [PATCH v2 6/6] hw/sd: move sdcard legacy API to "hw/sd/sdcard_legacy.h"

2018-01-22 Thread Philippe Mathieu-Daudé
roughly 2 users left.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h| 17 ---
 include/hw/sd/sdcard_legacy.h | 51 +++
 hw/sd/omap_mmc.c  |  2 +-
 hw/sd/pl181.c |  1 +
 hw/sd/sd.c|  1 +
 5 files changed, 54 insertions(+), 18 deletions(-)
 create mode 100644 include/hw/sd/sdcard_legacy.h

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index 9bdb3c9285..74bfab9386 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -130,23 +130,6 @@ typedef struct {
 void (*set_readonly)(DeviceState *dev, bool readonly);
 } SDBusClass;
 
-/* Legacy functions to be used only by non-qdevified callers */
-SDState *sd_init(BlockBackend *bs, bool is_spi);
-int sd_do_command(SDState *sd, SDRequest *req,
-  uint8_t *response);
-void sd_write_data(SDState *sd, uint8_t value);
-uint8_t sd_read_data(SDState *sd);
-void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
-bool sd_data_ready(SDState *sd);
-/* sd_enable should not be used -- it is only used on the nseries boards,
- * where it is part of a broken implementation of the MMC card slot switch
- * (there should be two card slots which are multiplexed to a single MMC
- * controller, but instead we model it with one card and controller and
- * disable the card when the second slot is selected, so it looks like the
- * second slot is always empty).
- */
-void sd_enable(SDState *sd, bool enable);
-
 /* Functions to be used by qdevified callers (working via
  * an SDBus rather than directly with SDState)
  */
diff --git a/include/hw/sd/sdcard_legacy.h b/include/hw/sd/sdcard_legacy.h
new file mode 100644
index 00..882e13a8f1
--- /dev/null
+++ b/include/hw/sd/sdcard_legacy.h
@@ -0,0 +1,51 @@
+/*
+ * SD Memory Card emulation (deprecated legacy API)
+ *
+ * Copyright (c) 2006 Andrzej Zaborowski  
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in
+ *the documentation and/or other materials provided with the
+ *distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef HW_SDCARD_LEGACY_H
+#define HW_SDCARD_LEGACY_H
+
+#include "hw/sd/sd.h"
+
+/* Legacy functions to be used only by non-qdevified callers */
+SDState *sd_init(BlockBackend *blk, bool is_spi);
+int sd_do_command(SDState *card, SDRequest *request, uint8_t *response);
+void sd_write_data(SDState *card, uint8_t value);
+uint8_t sd_read_data(SDState *card);
+void sd_set_cb(SDState *card, qemu_irq readonly, qemu_irq insert);
+bool sd_data_ready(SDState *card);
+
+/* sd_enable should not be used -- it is only used on the nseries boards,
+ * where it is part of a broken implementation of the MMC card slot switch
+ * (there should be two card slots which are multiplexed to a single MMC
+ * controller, but instead we model it with one card and controller and
+ * disable the card when the second slot is selected, so it looks like the
+ * second slot is always empty).
+ */
+void sd_enable(SDState *card, bool enable);
+
+#endif /* HW_SDCARD_LEGACY_H */
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index 5b47cadf11..be14ac4f40 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -19,7 +19,7 @@
 #include "qemu/osdep.h"
 #include "hw/hw.h"
 #include "hw/arm/omap.h"
-#include "hw/sd/sd.h"
+#include "hw/sd/sdcard_legacy.h"
 
 struct omap_mmc_s {
 qemu_irq irq;
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index ce696c5d7d..7591d016cd 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -12,6 +12,7 @@
 #include "sysemu/blockdev.h"
 #include "hw/sysbus.h"
 #include "hw/sd/sd.h"
+#include "hw/sd/sdcard_legacy.h"
 #include "qemu/log.h"
 #include "qapi/error.h"
 
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 9880a5d090..6942aa4df3 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -35,6 +35,7 @@
 #include 

[Qemu-devel] [PATCH v2 5/6] hw/sd/ssi-sd: use the SDBus API, connect the SDCard to the bus

2018-01-22 Thread Philippe Mathieu-Daudé
On reset the bus will reset the card,
we can now drop the device_reset() call.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/ssi-sd.c | 32 +++-
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index f88f509e0a..ae04b6641b 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -47,7 +47,7 @@ typedef struct {
 int32_t arglen;
 int32_t response_pos;
 int32_t stopping;
-SDState *sd;
+SDBus sdbus;
 } ssi_sd_state;
 
 #define TYPE_SSI_SD "ssi-sd"
@@ -100,7 +100,7 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
 request.arg = (s->cmdarg[0] << 24) | (s->cmdarg[1] << 16)
| (s->cmdarg[2] << 8) | s->cmdarg[3];
 DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg);
-s->arglen = sd_do_command(s->sd, , longresp);
+s->arglen = sdbus_do_command(>sdbus, , longresp);
 if (s->arglen <= 0) {
 s->arglen = 1;
 s->response[0] = 4;
@@ -177,7 +177,7 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
 DPRINTF("Response 0x%02x\n", s->response[s->response_pos]);
 return s->response[s->response_pos++];
 }
-if (sd_data_ready(s->sd)) {
+if (sdbus_data_ready(>sdbus)) {
 DPRINTF("Data read\n");
 s->mode = SSI_SD_DATA_START;
 } else {
@@ -190,8 +190,8 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
 s->mode = SSI_SD_DATA_READ;
 return 0xfe;
 case SSI_SD_DATA_READ:
-val = sd_read_data(s->sd);
-if (!sd_data_ready(s->sd)) {
+val = sdbus_read_data(>sdbus);
+if (!sdbus_data_ready(>sdbus)) {
 DPRINTF("Data read end\n");
 s->mode = SSI_SD_CMD;
 }
@@ -242,13 +242,24 @@ static const VMStateDescription vmstate_ssi_sd = {
 static void ssi_sd_realize(SSISlave *d, Error **errp)
 {
 ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
+DeviceState *carddev;
 DriveInfo *dinfo;
+Error *err = NULL;
 
+qbus_create_inplace(>sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
+DEVICE(d), "sd-bus");
+
+/* Create and plug in the sd card */
 /* FIXME use a qdev drive property instead of drive_get_next() */
 dinfo = drive_get_next(IF_SD);
-s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true);
-if (s->sd == NULL) {
-error_setg(errp, "Device initialization failed.");
+carddev = qdev_create(>sdbus.qbus, TYPE_SD_CARD);
+if (dinfo) {
+qdev_prop_set_drive(carddev, "drive", blk_by_legacy_dinfo(dinfo), 
);
+}
+object_property_set_bool(OBJECT(carddev), true, "spi", );
+object_property_set_bool(OBJECT(carddev), true, "realized", );
+if (err) {
+error_setg(errp, "failed to init SD card: %s", error_get_pretty(err));
 return;
 }
 }
@@ -264,11 +275,6 @@ static void ssi_sd_reset(DeviceState *dev)
 s->arglen = 0;
 s->response_pos = 0;
 s->stopping = 0;
-
-/* Since we're still using the legacy SD API the card is not plugged
- * into any bus, and we must reset it manually.
- */
-device_reset(DEVICE(s->sd));
 }
 
 static void ssi_sd_class_init(ObjectClass *klass, void *data)
-- 
2.15.1




[Qemu-devel] [PATCH v2 4/6] hw/sd/pl181: expose a SDBus and connect the SDCard to it

2018-01-22 Thread Philippe Mathieu-Daudé
using the sdbus_*() API.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/pl181.c | 31 ---
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 3ba1f7dd23..ce696c5d7d 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -33,6 +33,7 @@ typedef struct PL181State {
 SysBusDevice parent_obj;
 
 MemoryRegion iomem;
+SDBus sdbus;
 SDState *card;
 uint32_t clock;
 uint32_t power;
@@ -179,7 +180,7 @@ static void pl181_send_command(PL181State *s)
 request.cmd = s->cmd & PL181_CMD_INDEX;
 request.arg = s->cmdarg;
 DPRINTF("Command %d %08x\n", request.cmd, request.arg);
-rlen = sd_do_command(s->card, , response);
+rlen = sdbus_do_command(>sdbus, , response);
 if (rlen < 0)
 goto error;
 if (s->cmd & PL181_CMD_RESPONSE) {
@@ -223,12 +224,12 @@ static void pl181_fifo_run(PL181State *s)
 int is_read;
 
 is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
-if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
+if (s->datacnt != 0 && (!is_read || sdbus_data_ready(>sdbus))
 && !s->linux_hack) {
 if (is_read) {
 n = 0;
 while (s->datacnt && s->fifo_len < PL181_FIFO_LEN) {
-value |= (uint32_t)sd_read_data(s->card) << (n * 8);
+value |= (uint32_t)sdbus_read_data(>sdbus) << (n * 8);
 s->datacnt--;
 n++;
 if (n == 4) {
@@ -249,7 +250,7 @@ static void pl181_fifo_run(PL181State *s)
 }
 n--;
 s->datacnt--;
-sd_write_data(s->card, value & 0xff);
+sdbus_write_data(>sdbus, value & 0xff);
 value >>= 8;
 }
 }
@@ -480,10 +481,6 @@ static void pl181_reset(DeviceState *d)
 
 /* We can assume our GPIO outputs have been wired up now */
 sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
-/* Since we're still using the legacy SD API the card is not plugged
- * into any bus, and we must reset it manually.
- */
-device_reset(DEVICE(s->card));
 }
 
 static void pl181_init(Object *obj)
@@ -502,14 +499,26 @@ static void pl181_init(Object *obj)
 static void pl181_realize(DeviceState *dev, Error **errp)
 {
 PL181State *s = PL181(dev);
+DeviceState *carddev;
 DriveInfo *dinfo;
+Error *err = NULL;
+
+qbus_create_inplace(>sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
+dev, "sd-bus");
 
+/* Create and plug in the sd card */
 /* FIXME use a qdev drive property instead of drive_get_next() */
 dinfo = drive_get_next(IF_SD);
-s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
-if (s->card == NULL) {
-error_setg(errp, "sd_init failed");
+carddev = qdev_create(>sdbus.qbus, TYPE_SD_CARD);
+if (dinfo) {
+qdev_prop_set_drive(carddev, "drive", blk_by_legacy_dinfo(dinfo), 
);
+}
+object_property_set_bool(OBJECT(carddev), true, "realized", );
+if (err) {
+error_setg(errp, "failed to init SD card: %s", error_get_pretty(err));
+return;
 }
+s->card = SD_CARD(carddev);
 }
 
 static void pl181_class_init(ObjectClass *klass, void *data)
-- 
2.15.1




[Qemu-devel] [PATCH v2 3/6] hw/sd/milkymist-memcard: expose a SDBus and connect the SDCard to it

2018-01-22 Thread Philippe Mathieu-Daudé
using the sdbus_*() API.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/milkymist-memcard.c | 38 +-
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index a8e65892c7..5570c1e9a0 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -69,7 +69,7 @@ struct MilkymistMemcardState {
 SysBusDevice parent_obj;
 
 MemoryRegion regs_region;
-SDState *card;
+SDBus sdbus;
 
 int command_write_ptr;
 int response_read_ptr;
@@ -105,7 +105,7 @@ static void memcard_sd_command(MilkymistMemcardState *s)
 req.crc = s->command[5];
 
 s->response[0] = req.cmd;
-s->response_len = sd_do_command(s->card, , s->response+1);
+s->response_len = sdbus_do_command(>sdbus, , s->response + 1);
 s->response_read_ptr = 0;
 
 if (s->response_len == 16) {
@@ -150,10 +150,10 @@ static uint64_t memcard_read(void *opaque, hwaddr addr,
 r = 0x;
 } else {
 r = 0;
-r |= sd_read_data(s->card) << 24;
-r |= sd_read_data(s->card) << 16;
-r |= sd_read_data(s->card) << 8;
-r |= sd_read_data(s->card);
+r |= sdbus_read_data(>sdbus) << 24;
+r |= sdbus_read_data(>sdbus) << 16;
+r |= sdbus_read_data(>sdbus) << 8;
+r |= sdbus_read_data(>sdbus);
 }
 break;
 case R_CLK2XDIV:
@@ -207,10 +207,10 @@ static void memcard_write(void *opaque, hwaddr addr, 
uint64_t value,
 if (!s->enabled) {
 break;
 }
-sd_write_data(s->card, (value >> 24) & 0xff);
-sd_write_data(s->card, (value >> 16) & 0xff);
-sd_write_data(s->card, (value >> 8) & 0xff);
-sd_write_data(s->card, value & 0xff);
+sdbus_write_data(>sdbus, (value >> 24) & 0xff);
+sdbus_write_data(>sdbus, (value >> 16) & 0xff);
+sdbus_write_data(>sdbus, (value >> 8) & 0xff);
+sdbus_write_data(>sdbus, value & 0xff);
 break;
 case R_ENABLE:
 s->regs[addr] = value;
@@ -251,10 +251,6 @@ static void milkymist_memcard_reset(DeviceState *d)
 for (i = 0; i < R_MAX; i++) {
 s->regs[i] = 0;
 }
-/* Since we're still using the legacy SD API the card is not plugged
- * into any bus, and we must reset it manually.
- */
-device_reset(DEVICE(s->card));
 }
 
 static void milkymist_memcard_init(Object *obj)
@@ -270,15 +266,23 @@ static void milkymist_memcard_init(Object *obj)
 static void milkymist_memcard_realize(DeviceState *dev, Error **errp)
 {
 MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
+DeviceState *carddev;
 BlockBackend *blk;
 DriveInfo *dinfo;
+Error *err = NULL;
 
+qbus_create_inplace(>sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
+dev, "sd-bus");
+
+/* Create and plug in the sd card */
 /* FIXME use a qdev drive property instead of drive_get_next() */
 dinfo = drive_get_next(IF_SD);
 blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
-s->card = sd_init(blk, false);
-if (s->card == NULL) {
-error_setg(errp, "failed to init SD card");
+carddev = qdev_create(>sdbus.qbus, TYPE_SD_CARD);
+qdev_prop_set_drive(carddev, "drive", blk, );
+object_property_set_bool(OBJECT(carddev), true, "realized", );
+if (err) {
+error_setg(errp, "failed to init SD card: %s", error_get_pretty(err));
 return;
 }
 s->enabled = blk && blk_is_inserted(blk);
-- 
2.15.1




[Qemu-devel] [PATCH v2 2/6] hw/sd/milkymist-memcard: split realize() out of SysBusDevice init()

2018-01-22 Thread Philippe Mathieu-Daudé
Create the SDCard in the realize() function.

Suggested-by: Michael Walle 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/milkymist-memcard.c | 28 
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 1292c0c099..a8e65892c7 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -257,27 +257,31 @@ static void milkymist_memcard_reset(DeviceState *d)
 device_reset(DEVICE(s->card));
 }
 
-static int milkymist_memcard_init(SysBusDevice *dev)
+static void milkymist_memcard_init(Object *obj)
+{
+MilkymistMemcardState *s = MILKYMIST_MEMCARD(obj);
+SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>regs_region, OBJECT(s), _mmio_ops, s,
+"milkymist-memcard", R_MAX * 4);
+sysbus_init_mmio(dev, >regs_region);
+}
+
+static void milkymist_memcard_realize(DeviceState *dev, Error **errp)
 {
 MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
-DriveInfo *dinfo;
 BlockBackend *blk;
+DriveInfo *dinfo;
 
 /* FIXME use a qdev drive property instead of drive_get_next() */
 dinfo = drive_get_next(IF_SD);
 blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
 s->card = sd_init(blk, false);
 if (s->card == NULL) {
-return -1;
+error_setg(errp, "failed to init SD card");
+return;
 }
-
 s->enabled = blk && blk_is_inserted(blk);
-
-memory_region_init_io(>regs_region, OBJECT(s), _mmio_ops, s,
-"milkymist-memcard", R_MAX * 4);
-sysbus_init_mmio(dev, >regs_region);
-
-return 0;
 }
 
 static const VMStateDescription vmstate_milkymist_memcard = {
@@ -300,9 +304,8 @@ static const VMStateDescription vmstate_milkymist_memcard = 
{
 static void milkymist_memcard_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
-SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-k->init = milkymist_memcard_init;
+dc->realize = milkymist_memcard_realize;
 dc->reset = milkymist_memcard_reset;
 dc->vmsd = _milkymist_memcard;
 /* Reason: init() method uses drive_get_next() */
@@ -313,6 +316,7 @@ static const TypeInfo milkymist_memcard_info = {
 .name  = TYPE_MILKYMIST_MEMCARD,
 .parent= TYPE_SYS_BUS_DEVICE,
 .instance_size = sizeof(MilkymistMemcardState),
+.instance_init = milkymist_memcard_init,
 .class_init= milkymist_memcard_class_init,
 };
 
-- 
2.15.1




[Qemu-devel] [PATCH v2 1/6] hw/sd/milkymist-memcard: use qemu_log_mask()

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/milkymist-memcard.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 341da88552..1292c0c099 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -22,11 +22,12 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "hw/hw.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
-#include "qemu/error-report.h"
+#include "include/qapi/error.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/sd/sd.h"
@@ -138,8 +139,8 @@ static uint64_t memcard_read(void *opaque, hwaddr addr,
 } else {
 r = s->response[s->response_read_ptr++];
 if (s->response_read_ptr > s->response_len) {
-error_report("milkymist_memcard: "
-"read more cmd bytes than available. Clipping.");
+qemu_log_mask(LOG_GUEST_ERROR, "milkymist_memcard: "
+  "read more cmd bytes than available. Clipping.");
 s->response_read_ptr = 0;
 }
 }
@@ -163,8 +164,9 @@ static uint64_t memcard_read(void *opaque, hwaddr addr,
 break;
 
 default:
-error_report("milkymist_memcard: read access to unknown register 0x"
-TARGET_FMT_plx, addr << 2);
+qemu_log_mask(LOG_UNIMP, "milkymist_memcard: "
+  "read access to unknown register 0x%" HWADDR_PRIx "\n",
+  addr << 2);
 break;
 }
 
@@ -220,8 +222,9 @@ static void memcard_write(void *opaque, hwaddr addr, 
uint64_t value,
 break;
 
 default:
-error_report("milkymist_memcard: write access to unknown register 0x"
-TARGET_FMT_plx, addr << 2);
+qemu_log_mask(LOG_UNIMP, "milkymist_memcard: "
+  "write access to unknown register 0x%" HWADDR_PRIx " "
+  "(value 0x%" PRIx64 ")\n", addr << 2, value);
 break;
 }
 }
-- 
2.15.1




[Qemu-devel] [PATCH v2 0/6] SDHCI: convert legacy devices to the SDBus API (part 6)

2018-01-22 Thread Philippe Mathieu-Daudé
Hi,

Since v1:
- rebased on /master (Peter sdcard reset() patches)
- fix milkymist-mmc from previous seris using instance_init (Michael Walle)

This series convert 3 devices using the legacy SDCard API to the SDBus API:
- milkymist-mmc
- pl181
- ssi-sd

Then move the legacy API to a separate header "sdcard_legacy.h".

Now the OMAP MMC is the last device using the legacy API, but need to get
QOM'ified first.

Having a common sdbus interface simplify qtesting (next series)

Regards,

Phil.

$ git backport-diff
001/6:[] [--] 'hw/sd/milkymist-memcard: use qemu_log_mask()'
002/6:[0014] [FC] 'hw/sd/milkymist-memcard: split realize() out of SysBusDevice 
init()'
003/6:[0004] [FC] 'hw/sd/milkymist-memcard: expose a SDBus and connect the 
SDCard to it'
004/6:[0006] [FC] 'hw/sd/pl181: expose a SDBus and connect the SDCard to it'
005/6:[down] 'hw/sd/ssi-sd: use the SDBus API, connect the SDCard to the bus'
006/6:[] [-C] 'hw/sd: move sdcard legacy API to "hw/sd/sdcard_legacy.h"'

Based-on: 20180123033034.29493-19-f4...@amsat.org
  (or /master)

Philippe Mathieu-Daudé (6):
  hw/sd/milkymist-memcard: use qemu_log_mask()
  hw/sd/milkymist-memcard: split realize() out of SysBusDevice init()
  hw/sd/milkymist-memcard: expose a SDBus and connect the SDCard to it
  hw/sd/pl181: expose a SDBus and connect the SDCard to it
  hw/sd/ssi-sd: use the SDBus API, connect the SDCard to the bus
  hw/sd: move sdcard legacy API to "hw/sd/sdcard_legacy.h"

 include/hw/sd/sd.h| 17 -
 include/hw/sd/sdcard_legacy.h | 51 +++
 hw/sd/milkymist-memcard.c | 81 ---
 hw/sd/omap_mmc.c  |  2 +-
 hw/sd/pl181.c | 32 +++--
 hw/sd/sd.c|  1 +
 hw/sd/ssi-sd.c| 32 ++---
 7 files changed, 139 insertions(+), 77 deletions(-)
 create mode 100644 include/hw/sd/sdcard_legacy.h

-- 
2.15.1




[Qemu-devel] [PATCH v3 3/5] target/arm: Add SVE to migration state

2018-01-22 Thread Richard Henderson
Save the high parts of the Zregs and all of the Pregs.
The ZCR_ELx registers are migrated via the CP mechanism.

Signed-off-by: Richard Henderson 
---
 target/arm/machine.c | 53 
 1 file changed, 53 insertions(+)

diff --git a/target/arm/machine.c b/target/arm/machine.c
index cb0e1c92bb..2c8b43062f 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -122,6 +122,56 @@ static const VMStateDescription vmstate_iwmmxt = {
 }
 };
 
+#ifdef TARGET_AARCH64
+/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
+ * and ARMPredicateReg is actively empty.  This triggers errors
+ * in the expansion of the VMSTATE macros.
+ */
+
+static bool sve_needed(void *opaque)
+{
+ARMCPU *cpu = opaque;
+CPUARMState *env = >env;
+
+return arm_feature(env, ARM_FEATURE_SVE);
+}
+
+/* The first two words of each Zreg is stored in VFP state.  */
+static const VMStateDescription vmstate_zreg_hi_reg = {
+.name = "cpu/sve/zreg_hi",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static const VMStateDescription vmstate_preg_reg = {
+.name = "cpu/sve/preg",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static const VMStateDescription vmstate_sve = {
+.name = "cpu/sve",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = sve_needed,
+.fields = (VMStateField[]) {
+VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
+ vmstate_zreg_hi_reg, ARMVectorReg),
+VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
+ vmstate_preg_reg, ARMPredicateReg),
+VMSTATE_END_OF_LIST()
+}
+};
+#endif /* AARCH64 */
+
 static bool m_needed(void *opaque)
 {
 ARMCPU *cpu = opaque;
@@ -586,6 +636,9 @@ const VMStateDescription vmstate_arm_cpu = {
 _pmsav7,
 _pmsav8,
 _m_security,
+#ifdef TARGET_AARCH64
+_sve,
+#endif
 NULL
 }
 };
-- 
2.14.3




[Qemu-devel] [PATCH v3 5/5] target/arm: Add SVE state to TB->FLAGS

2018-01-22 Thread Richard Henderson
Add both SVE exception state and vector length.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h   |  8 
 target/arm/translate.h |  2 ++
 target/arm/helper.c| 25 -
 target/arm/translate-a64.c |  2 ++
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 17955ad3ef..a311d4e327 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2648,6 +2648,10 @@ static inline bool 
arm_cpu_data_is_big_endian(CPUARMState *env)
 #define ARM_TBFLAG_TBI0_MASK (0x1ull << ARM_TBFLAG_TBI0_SHIFT)
 #define ARM_TBFLAG_TBI1_SHIFT 1/* TBI1 for EL0/1  */
 #define ARM_TBFLAG_TBI1_MASK (0x1ull << ARM_TBFLAG_TBI1_SHIFT)
+#define ARM_TBFLAG_SVEEXC_EL_SHIFT  2
+#define ARM_TBFLAG_SVEEXC_EL_MASK   (0x3 << ARM_TBFLAG_SVEEXC_EL_SHIFT)
+#define ARM_TBFLAG_ZCR_LEN_SHIFT4
+#define ARM_TBFLAG_ZCR_LEN_MASK (0xf << ARM_TBFLAG_ZCR_LEN_SHIFT)
 
 /* some convenience accessor macros */
 #define ARM_TBFLAG_AARCH64_STATE(F) \
@@ -2684,6 +2688,10 @@ static inline bool 
arm_cpu_data_is_big_endian(CPUARMState *env)
 (((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
 #define ARM_TBFLAG_TBI1(F) \
 (((F) & ARM_TBFLAG_TBI1_MASK) >> ARM_TBFLAG_TBI1_SHIFT)
+#define ARM_TBFLAG_SVEEXC_EL(F) \
+(((F) & ARM_TBFLAG_SVEEXC_EL_MASK) >> ARM_TBFLAG_SVEEXC_EL_SHIFT)
+#define ARM_TBFLAG_ZCR_LEN(F) \
+(((F) & ARM_TBFLAG_ZCR_LEN_MASK) >> ARM_TBFLAG_ZCR_LEN_SHIFT)
 
 static inline bool bswap_code(bool sctlr_b)
 {
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 3f4df91e5e..c47febf99d 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -29,6 +29,8 @@ typedef struct DisasContext {
 bool tbi1; /* TBI1 for EL0/1, not used for EL2/3 */
 bool ns;/* Use non-secure CPREG bank on access */
 int fp_excp_el; /* FP exception EL or 0 if enabled */
+int sve_excp_el; /* SVE exception EL or 0 if enabled */
+int sve_len; /* SVE vector length in bytes */
 /* Flag indicating that exceptions from secure mode are routed to EL3. */
 bool secure_routed_to_el3;
 bool vfp_enabled; /* FP enabled via FPSCR.EN */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index db67e8ac72..d46d3622fc 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11823,14 +11823,37 @@ void cpu_get_tb_cpu_state(CPUARMState *env, 
target_ulong *pc,
   target_ulong *cs_base, uint32_t *pflags)
 {
 ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
+int fp_el = fp_exception_el(env);
 uint32_t flags;
 
 if (is_a64(env)) {
+int sve_el = sve_exception_el(env);
+uint32_t zcr_len;
+
 *pc = env->pc;
 flags = ARM_TBFLAG_AARCH64_STATE_MASK;
 /* Get control bits for tagged addresses */
 flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
 flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
+flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
+
+/* If SVE is disabled, but FP is enabled,
+   then the effective len is 0.  */
+if (sve_el != 0 && fp_el == 0) {
+zcr_len = 0;
+} else {
+int current_el = arm_current_el(env);
+
+zcr_len = env->vfp.zcr_el[current_el <= 1 ? 1 : current_el];
+zcr_len &= 0xf;
+if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
+zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
+}
+if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
+zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
+}
+}
+flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
 } else {
 *pc = env->regs[15];
 flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
@@ -11873,7 +11896,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env, 
target_ulong *pc,
 if (arm_cpu_data_is_big_endian(env)) {
 flags |= ARM_TBFLAG_BE_DATA_MASK;
 }
-flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
+flags |= fp_el << ARM_TBFLAG_FPEXC_EL_SHIFT;
 
 if (arm_v7m_is_handler_mode(env)) {
 flags |= ARM_TBFLAG_HANDLER_MASK;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 10eef870fe..4c1eca7062 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11263,6 +11263,8 @@ static int 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->user = (dc->current_el == 0);
 #endif
 dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
+dc->sve_excp_el = ARM_TBFLAG_SVEEXC_EL(dc->base.tb->flags);
+dc->sve_len = (ARM_TBFLAG_ZCR_LEN(dc->base.tb->flags) + 1) * 16;
 dc->vec_len = 0;
 dc->vec_stride = 0;
 dc->cp_regs = arm_cpu->cp_regs;
-- 
2.14.3




[Qemu-devel] [PATCH v3 2/5] target/arm: Add predicate registers for SVE

2018-01-22 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 1854fe51a8..3f4f6b6144 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -188,6 +188,13 @@ typedef struct ARMVectorReg {
 uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
 } ARMVectorReg;
 
+/* In AArch32 mode, predicate registers do not exist at all.  */
+#ifdef TARGET_AARCH64
+typedef struct ARMPredicateReg {
+uint64_t p[2 * ARM_MAX_VQ / 8] QEMU_ALIGNED(16);
+} ARMPredicateReg;
+#endif
+
 
 typedef struct CPUARMState {
 /* Regs for current mode.  */
@@ -515,6 +522,11 @@ typedef struct CPUARMState {
 struct {
 ARMVectorReg zregs[32];
 
+#ifdef TARGET_AARCH64
+/* Store FFR as pregs[16] to make it easier to treat as any other.  */
+ARMPredicateReg pregs[17];
+#endif
+
 uint32_t xregs[16];
 /* We store these fpcsr fields separately for convenience.  */
 int vec_len;
-- 
2.14.3




[Qemu-devel] [PATCH v3 4/5] target/arm: Add ZCR_ELx

2018-01-22 Thread Richard Henderson
Define ZCR_EL[1-3].

Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h|   5 ++
 target/arm/helper.c | 131 
 2 files changed, 136 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 3f4f6b6144..17955ad3ef 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -549,6 +549,9 @@ typedef struct CPUARMState {
  */
 float_status fp_status;
 float_status standard_fp_status;
+
+/* ZCR_EL[1-3] */
+uint64_t zcr_el[4];
 } vfp;
 uint64_t exclusive_addr;
 uint64_t exclusive_val;
@@ -923,6 +926,8 @@ void pmccntr_sync(CPUARMState *env);
 #define CPTR_TCPAC(1U << 31)
 #define CPTR_TTA  (1U << 20)
 #define CPTR_TFP  (1U << 10)
+#define CPTR_TZ   (1U << 8)   /* CPTR_EL2 */
+#define CPTR_EZ   (1U << 8)   /* CPTR_EL3 */
 
 #define MDCR_EPMAD(1U << 21)
 #define MDCR_EDAD (1U << 20)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index bfce09643b..db67e8ac72 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4266,6 +4266,125 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
 REGINFO_SENTINEL
 };
 
+/* Return the exception level to which SVE-disabled exceptions should
+ * be taken, or 0 if SVE is enabled.
+ */
+static int sve_exception_el(CPUARMState *env)
+{
+#ifndef CONFIG_USER_ONLY
+unsigned current_el = arm_current_el(env);
+
+/* The CPACR.ZEN controls traps to EL1:
+ * 0, 2 : trap EL0 and EL1 accesses
+ * 1: trap only EL0 accesses
+ * 3: trap no accesses
+ */
+switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
+default:
+if (current_el <= 1) {
+/* Trap to PL1, which might be EL1 or EL3 */
+if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
+return 3;
+}
+return 1;
+}
+break;
+case 1:
+if (current_el == 0) {
+return 1;
+}
+break;
+case 3:
+break;
+}
+
+/* Similarly for CPACR.FPEN, after having checked ZEN.  */
+switch (extract32(env->cp15.cpacr_el1, 20, 2)) {
+default:
+if (current_el <= 1) {
+if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
+return 3;
+}
+return 1;
+}
+break;
+case 1:
+if (current_el == 0) {
+return 1;
+}
+break;
+case 3:
+break;
+}
+
+/* CPTR_EL2.  Check both TZ and TFP.  */
+if (current_el <= 2
+&& (env->cp15.cptr_el[2] & (CPTR_TFP | CPTR_TZ))
+&& !arm_is_secure_below_el3(env)) {
+return 2;
+}
+
+/* CPTR_EL3.  Check both EZ and TFP.  */
+if (!(env->cp15.cptr_el[3] & CPTR_EZ)
+|| (env->cp15.cptr_el[3] & CPTR_TFP)) {
+return 3;
+}
+#endif
+return 0;
+}
+
+static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+switch (sve_exception_el(env)) {
+case 3:
+return CP_ACCESS_TRAP_EL3;
+case 2:
+return CP_ACCESS_TRAP_EL2;
+case 1:
+return CP_ACCESS_TRAP;
+}
+return CP_ACCESS_OK;
+}
+
+static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+  uint64_t value)
+{
+/* Bits other than [3:0] are RAZ/WI.  */
+raw_write(env, ri, value & 0xf);
+}
+
+static const ARMCPRegInfo zcr_el1_reginfo = {
+.name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
+.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
+.access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
+.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
+.writefn = zcr_write, .raw_writefn = raw_write
+};
+
+static const ARMCPRegInfo zcr_el2_reginfo = {
+.name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
+.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
+.access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
+.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
+.writefn = zcr_write, .raw_writefn = raw_write
+};
+
+static const ARMCPRegInfo zcr_no_el2_reginfo = {
+.name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
+.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
+.access = PL2_RW, .type = ARM_CP_64BIT,
+.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore
+};
+
+static const ARMCPRegInfo zcr_el3_reginfo = {
+.name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
+.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
+.access = PL3_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
+.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
+.writefn = zcr_write, .raw_writefn = raw_write
+};
+
 void hw_watchpoint_update(ARMCPU *cpu, int n)
 {
 CPUARMState *env = >env;
@@ -5332,6 +5451,18 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 }
 define_one_arm_cp_reg(cpu, );
 }
+
+if (arm_feature(env, 

[Qemu-devel] [PATCH v3 1/5] target/arm: Expand vector registers for SVE

2018-01-22 Thread Richard Henderson
Change vfp.regs as a uint64_t to vfp.zregs as an ARMVectorReg.
The previous patches have made the change in representation
relatively painless.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h   | 59 +++---
 target/arm/machine.c   | 35 ++-
 target/arm/translate-a64.c |  8 +++
 target/arm/translate.c |  7 +++---
 4 files changed, 81 insertions(+), 28 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index d2bb59eded..1854fe51a8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -153,6 +153,42 @@ typedef struct {
 uint32_t base_mask;
 } TCR;
 
+/* Define a maximum sized vector register.
+ * For 32-bit, this is a 128-bit NEON/AdvSIMD register.
+ * For 64-bit, this is a 2048-bit SVE register.
+ *
+ * Note that the mapping between S, D, and Q views of the register bank
+ * differs between AArch64 and AArch32.
+ * In AArch32:
+ *  Qn = regs[n].d[1]:regs[n].d[0]
+ *  Dn = regs[n / 2].d[n & 1]
+ *  Sn = regs[n / 4].d[n % 4 / 2],
+ *   bits 31..0 for even n, and bits 63..32 for odd n
+ *   (and regs[16] to regs[31] are inaccessible)
+ * In AArch64:
+ *  Zn = regs[n].d[*]
+ *  Qn = regs[n].d[1]:regs[n].d[0]
+ *  Dn = regs[n].d[0]
+ *  Sn = regs[n].d[0] bits 31..0
+ *
+ * This corresponds to the architecturally defined mapping between
+ * the two execution states, and means we do not need to explicitly
+ * map these registers when changing states.
+ *
+ * Align the data for use with TCG host vector operations.
+ */
+
+#ifdef TARGET_AARCH64
+# define ARM_MAX_VQ16
+#else
+# define ARM_MAX_VQ1
+#endif
+
+typedef struct ARMVectorReg {
+uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
+} ARMVectorReg;
+
+
 typedef struct CPUARMState {
 /* Regs for current mode.  */
 uint32_t regs[16];
@@ -477,22 +513,7 @@ typedef struct CPUARMState {
 
 /* VFP coprocessor state.  */
 struct {
-/* VFP/Neon register state. Note that the mapping between S, D and Q
- * views of the register bank differs between AArch64 and AArch32:
- * In AArch32:
- *  Qn = regs[2n+1]:regs[2n]
- *  Dn = regs[n]
- *  Sn = regs[n/2] bits 31..0 for even n, and bits 63..32 for odd n
- * (and regs[32] to regs[63] are inaccessible)
- * In AArch64:
- *  Qn = regs[2n+1]:regs[2n]
- *  Dn = regs[2n]
- *  Sn = regs[2n] bits 31..0
- * This corresponds to the architecturally defined mapping between
- * the two execution states, and means we do not need to explicitly
- * map these registers when changing states.
- */
-uint64_t regs[64];
+ARMVectorReg zregs[32];
 
 uint32_t xregs[16];
 /* We store these fpcsr fields separately for convenience.  */
@@ -2769,7 +2790,7 @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU 
*cpu)
  */
 static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
 {
-return >vfp.regs[regno];
+return >vfp.zregs[regno >> 1].d[regno & 1];
 }
 
 /**
@@ -2778,7 +2799,7 @@ static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, 
unsigned regno)
  */
 static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
 {
-return >vfp.regs[2 * regno];
+return >vfp.zregs[regno].d[0];
 }
 
 /**
@@ -2787,7 +2808,7 @@ static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, 
unsigned regno)
  */
 static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
 {
-return >vfp.regs[2 * regno];
+return >vfp.zregs[regno].d[0];
 }
 
 #endif
diff --git a/target/arm/machine.c b/target/arm/machine.c
index a85c2430d3..cb0e1c92bb 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -50,7 +50,40 @@ static const VMStateDescription vmstate_vfp = {
 .minimum_version_id = 3,
 .needed = vfp_needed,
 .fields = (VMStateField[]) {
-VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64),
+/* For compatibility, store Qn out of Zn here.  */
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[0].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[1].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[2].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[3].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[4].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[5].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[6].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[7].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[8].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[9].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[10].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[11].d, ARMCPU, 0, 2),
+VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[12].d, ARMCPU, 0, 2),
+  

[Qemu-devel] [PATCH v3 0/5] target/arm: Preparatory work for SVE

2018-01-22 Thread Richard Henderson
Based on PMM's target-arm.next branch, which now has most of v2.

While looking again at ZCR_ELx, I think that there's an existing
bug in the FPCR/FPSR system registers, wherein we do not have an
access function for when the FPU is disabled.


r~


Richard Henderson (5):
  target/arm: Expand vector registers for SVE
  target/arm: Add predicate registers for SVE
  target/arm: Add SVE to migration state
  target/arm: Add ZCR_ELx
  target/arm: Add SVE state to TB->FLAGS

 target/arm/cpu.h   |  84 ++--
 target/arm/translate.h |   2 +
 target/arm/helper.c| 156 -
 target/arm/machine.c   |  88 -
 target/arm/translate-a64.c |  10 +--
 target/arm/translate.c |   7 +-
 6 files changed, 318 insertions(+), 29 deletions(-)

-- 
2.14.3




[Qemu-devel] [PATCH v3 17/18] sdcard: implement the UHS-I SWITCH_FUNCTION entries (Spec v3)

2018-01-22 Thread Philippe Mathieu-Daudé
[based on a patch from Alistair Francis 
 from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 148 +
 hw/sd/trace-events |   1 +
 2 files changed, 127 insertions(+), 22 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index b3b6859bc4..1f6c4ce2a4 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -125,6 +125,7 @@ struct SDState {
 bool enable;
 uint8_t dat_lines;
 bool cmd_line;
+bool uhs_enabled;
 };
 
 static const char *sd_state_name(enum SDCardStates state)
@@ -569,6 +570,7 @@ static void sd_reset(DeviceState *dev)
 sd->expecting_acmd = false;
 sd->dat_lines = 0xf;
 sd->cmd_line = true;
+sd->uhs_enabled = false;
 sd->multi_blk_cnt = 0;
 }
 
@@ -767,30 +769,132 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
 return ret;
 }
 
+/* Function Group */
+enum {
+SD_FG_MIN   = 1,
+SD_FG_ACCESS_MODE   = 1,
+SD_FG_COMMAND_SYSTEM= 2,
+SD_FG_DRIVER_STRENGTH   = 3,
+SD_FG_CURRENT_LIMIT = 4,
+SD_FG_RSVD_5= 5,
+SD_FG_RSVD_6= 6,
+SD_FG_COUNT
+};
+
+/* Function name */
+#define SD_FN_COUNT 16
+
+static const char *sd_fn_grp_name[SD_FG_COUNT] = {
+[SD_FG_ACCESS_MODE] = "ACCESS_MODE",
+[SD_FG_COMMAND_SYSTEM]  = "COMMAND_SYSTEM",
+[SD_FG_DRIVER_STRENGTH] = "DRIVER_STRENGTH",
+[SD_FG_CURRENT_LIMIT]   = "CURRENT_LIMIT",
+[SD_FG_RSVD_5]  = "RSVD5",
+[SD_FG_RSVD_6]  = "RSVD6",
+};
+
+typedef struct sd_fn_support {
+const char *name;
+bool uhs_only;
+bool unimp;
+} sd_fn_support;
+
+static const sd_fn_support *sd_fn_support_defs[SD_FG_COUNT] = {
+[SD_FG_ACCESS_MODE] = (sd_fn_support [SD_FN_COUNT]) {
+[0] = { .name = "default/SDR12" },
+[1] = { .name = "high-speed/SDR25" },
+[2] = { .name = "SDR50",.uhs_only = true },
+[3] = { .name = "SDR104",   .uhs_only = true },
+[4] = { .name = "DDR50",.uhs_only = true },
+},
+[SD_FG_COMMAND_SYSTEM] = (sd_fn_support [SD_FN_COUNT]) {
+[0] = { .name = "default" },
+[1] = { .name = "For eC" },
+[3] = { .name = "OTP",  .unimp = true },
+[4] = { .name = "ASSD", .unimp = true },
+},
+[SD_FG_DRIVER_STRENGTH] = (sd_fn_support [SD_FN_COUNT]) {
+[0] = { .name = "default/Type B" },
+[1] = { .name = "Type A",   .uhs_only = true },
+[2] = { .name = "Type C",   .uhs_only = true },
+[3] = { .name = "Type D",   .uhs_only = true },
+},
+[SD_FG_CURRENT_LIMIT] = (sd_fn_support [SD_FN_COUNT]) {
+[0] = { .name = "default/200mA" },
+[1] = { .name = "400mA",.uhs_only = true },
+[2] = { .name = "600mA",.uhs_only = true },
+[3] = { .name = "800mA",.uhs_only = true },
+},
+[SD_FG_RSVD_5] = (sd_fn_support [SD_FN_COUNT]) {
+[0] = { .name = "default" },
+},
+[SD_FG_RSVD_6] = (sd_fn_support [SD_FN_COUNT]) {
+[0] = { .name = "default" },
+},
+};
+
+#define SD_FN_NO_INFLUENCE  (1 << 15)
+
 static void sd_function_switch(SDState *sd, uint32_t arg)
 {
-int i, mode, new_func;
-mode = !!(arg & 0x8000);
-
-sd->data[0] = 0x00;/* Maximum current consumption */
-sd->data[1] = 0x01;
-sd->data[2] = 0x80;/* Supported group 6 functions */
-sd->data[3] = 0x01;
-sd->data[4] = 0x80;/* Supported group 5 functions */
-sd->data[5] = 0x01;
-sd->data[6] = 0x80;/* Supported group 4 functions */
-sd->data[7] = 0x01;
-sd->data[8] = 0x80;/* Supported group 3 functions */
-sd->data[9] = 0x01;
-sd->data[10] = 0x80;   /* Supported group 2 functions */
-sd->data[11] = 0x43;
-sd->data[12] = 0x80;   /* Supported group 1 functions */
-sd->data[13] = 0x03;
-for (i = 0; i < 6; i ++) {
-new_func = (arg >> (i * 4)) & 0x0f;
-if (mode && new_func != 0x0f)
-sd->function_group[i] = new_func;
-sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4);
+int fn_grp, new_func, i;
+uint8_t *data_p;
+bool mode = extract32(arg, 31, 1);  /* 0: check only, 1: do switch */
+
+stw_be_p(sd->data + 0, 0x0001); /* Maximum current consumption */
+
+data_p = >data[2];
+for (fn_grp = SD_FG_COUNT - 1; fn_grp >= SD_FG_MIN; fn_grp--) {
+uint16_t supported_fns = SD_FN_NO_INFLUENCE;
+for (i = 0; i < SD_FN_COUNT; ++i) {
+const sd_fn_support *def = _fn_support_defs[fn_grp][i];
+
+if (def->name && !def->unimp &&
+!(def->uhs_only && !sd->uhs_enabled)) {
+supported_fns |= 1 << i;
+}
+}
+stw_be_p(data_p, supported_fns);
+data_p += 2;
+}
+
+assert(data_p == >data[14]);
+for (fn_grp = SD_FG_COUNT - 

[Qemu-devel] [PATCH v3 13/18] sdcard: simplify SEND_IF_COND (CMD8)

2018-01-22 Thread Philippe Mathieu-Daudé
replace switch(single case) -> if()

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index b5c947df62..707c294169 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1015,23 +1015,19 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 case 8:/* CMD8:   SEND_IF_COND */
 /* Physical Layer Specification Version 2.00 command */
-switch (sd->state) {
-case sd_idle_state:
-sd->vhs = 0;
-
-/* No response if not exactly one VHS bit is set.  */
-if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) {
-return sd->spi ? sd_r7 : sd_r0;
-}
-
-/* Accept.  */
-sd->vhs = req.arg;
-return sd_r7;
-
-default:
+if (sd->state != sd_idle_state) {
 break;
 }
-break;
+sd->vhs = 0;
+
+/* No response if not exactly one VHS bit is set.  */
+if (!(req.arg >> 8) || (req.arg >> (ctz32(req.arg & ~0xff) + 1))) {
+return sd->spi ? sd_r7 : sd_r0;
+}
+
+/* Accept.  */
+sd->vhs = req.arg;
+return sd_r7;
 
 case 9:/* CMD9:   SEND_CSD */
 switch (sd->state) {
-- 
2.15.1




[Qemu-devel] [PATCH v3 15/18] sdcard: add SD SEND_TUNING_BLOCK (CMD19)

2018-01-22 Thread Philippe Mathieu-Daudé
[based on a patch from Alistair Francis 
 from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 6efcacb942..27176ba33e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1169,6 +1169,14 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 break;
 
+case 19:/* CMD19: SEND_TUNING_BLOCK (SD) */
+if (sd->state == sd_transfer_state) {
+sd->state = sd_sendingdata_state;
+sd->data_offset = 0;
+return sd_r1;
+}
+break;
+
 case 23:/* CMD23: SET_BLOCK_COUNT */
 switch (sd->state) {
 case sd_transfer_state:
@@ -1911,6 +1919,15 @@ void sd_write_data(SDState *sd, uint8_t value)
 }
 }
 
+#define SD_TUNING_BLOCK_SIZE64
+
+static const uint32_t sd_tunning_data[SD_TUNING_BLOCK_SIZE / 4] = {
+0xFF0FFF00, 0x0FFCC3CC, 0xC33CCCFF, 0xFEFFFEEF,
+0xFFDFFFDD, 0xFFFBFFFB, 0XBFFF7FFF, 0X77F7BDEF,
+0XFFF0FFF0, 0X0FFCCC3C, 0XCC33CCCF, 0XFFEFFFEE,
+0XFFFDFFFD, 0XDFFFBFFF, 0XBBFFF7FF, 0XF77F7BDE,
+};
+
 uint8_t sd_read_data(SDState *sd)
 {
 /* TODO: Append CRCs */
@@ -1990,6 +2007,13 @@ uint8_t sd_read_data(SDState *sd)
 }
 break;
 
+case 19:/* CMD19:  SEND_TUNING_BLOCK (SD) */
+if (sd->data_offset >= SD_TUNING_BLOCK_SIZE - 1) {
+sd->state = sd_transfer_state;
+}
+ret = ((uint8_t *)(_tunning_data))[sd->data_offset++];
+break;
+
 case 22:   /* ACMD22: SEND_NUM_WR_BLOCKS */
 ret = sd->data[sd->data_offset ++];
 
-- 
2.15.1




[Qemu-devel] [PATCH v3 12/18] sdcard: warn if host uses an incorrect address for APP CMD (CMD55)

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 434d1fbc47..b5c947df62 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1394,6 +1394,11 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 case sd_identification_state:
 case sd_inactive_state:
 return sd_illegal;
+case sd_idle_state:
+if (rca) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "SD: illegal RCA 0x%04x for APP_CMD\n", req.cmd);
+}
 default:
 break;
 }
-- 
2.15.1




[Qemu-devel] [PATCH v3 16/18] sdcard: add a 'uhs' property, update the OCR register ACCEPT_SWITCH_1V8 bit

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 27176ba33e..b3b6859bc4 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -93,6 +93,7 @@ struct SDState {
 /* Configurable properties */
 BlockBackend *blk;
 bool spi;
+uint8_t uhs_supported;
 
 uint32_t mode;/* current card mode, one of SDCardModes */
 int32_t state;/* current card state, one of SDCardStates */
@@ -289,6 +290,8 @@ static void sd_reset_ocr(SDState *sd)
 {
 /* All voltages OK */
 sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK;
+
+sd->ocr = FIELD_DP32(sd->ocr, OCR, ACCEPT_SWITCH_1V8, !!sd->uhs_supported);
 }
 
 static void sd_ocr_powerup(void *opaque)
@@ -2107,6 +2110,7 @@ static Property sd_properties[] = {
  * board to ensure that ssi transfers only occur when the chip select
  * is asserted.  */
 DEFINE_PROP_BOOL("spi", SDState, spi, false),
+DEFINE_PROP_UINT8("uhs", SDState, uhs_supported, UHS_NOT_SUPPORTED),
 DEFINE_PROP_END_OF_LIST()
 };
 
-- 
2.15.1




[Qemu-devel] [PATCH v3 10/18] sdcard: handle CMD54 (SDIO)

2018-01-22 Thread Philippe Mathieu-Daudé
Linux uses it to poll the bus before polling for a card.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 07424aa56e..bbf9496e8a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1378,9 +1378,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 break;
 
-case 52:
-case 53:
-/* CMD52, CMD53: reserved for SDIO cards
+case 52 ... 54:
+/* CMD52, CMD53, CMD54: reserved for SDIO cards
  * (see the SDIO Simplified Specification V2.0)
  * Handle as illegal command but do not complain
  * on stderr, as some OSes may use these in their
-- 
2.15.1




[Qemu-devel] [PATCH v3 14/18] sdcard: simplify SD_SEND_OP_COND (ACMD41)

2018-01-22 Thread Philippe Mathieu-Daudé
replace switch(single case) -> if()

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 56 ++--
 1 file changed, 26 insertions(+), 30 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 707c294169..6efcacb942 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1535,45 +1535,41 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 sd->state = sd_transfer_state;
 return sd_r1;
 }
-switch (sd->state) {
-case sd_idle_state:
-/* If it's the first ACMD41 since reset, we need to decide
- * whether to power up. If this is not an enquiry ACMD41,
- * we immediately report power on and proceed below to the
- * ready state, but if it is, we set a timer to model a
- * delay for power up. This works around a bug in EDK2
- * UEFI, which sends an initial enquiry ACMD41, but
- * assumes that the card is in ready state as soon as it
- * sees the power up bit set. */
-if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) {
-if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) {
-timer_del(sd->ocr_power_timer);
-sd_ocr_powerup(sd);
-} else {
-trace_sdcard_inquiry_cmd41();
-if (!timer_pending(sd->ocr_power_timer)) {
-timer_mod_ns(sd->ocr_power_timer,
- (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
-  + OCR_POWER_DELAY_NS));
-}
+if (sd->state != sd_idle_state) {
+break;
+}
+/* If it's the first ACMD41 since reset, we need to decide
+ * whether to power up. If this is not an enquiry ACMD41,
+ * we immediately report power on and proceed below to the
+ * ready state, but if it is, we set a timer to model a
+ * delay for power up. This works around a bug in EDK2
+ * UEFI, which sends an initial enquiry ACMD41, but
+ * assumes that the card is in ready state as soon as it
+ * sees the power up bit set. */
+if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) {
+if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) {
+timer_del(sd->ocr_power_timer);
+sd_ocr_powerup(sd);
+} else {
+trace_sdcard_inquiry_cmd41();
+if (!timer_pending(sd->ocr_power_timer)) {
+timer_mod_ns(sd->ocr_power_timer,
+ (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
+  + OCR_POWER_DELAY_NS));
 }
 }
+}
 
+if (FIELD_EX32(sd->ocr & req.arg, OCR, VDD_VOLTAGE_WINDOW)) {
 /* We accept any voltage.  1 V is nothing.
  *
  * Once we're powered up, we advance straight to ready state
  * unless it's an enquiry ACMD41 (bits 23:0 == 0).
  */
-if (req.arg & ACMD41_ENQUIRY_MASK) {
-sd->state = sd_ready_state;
-}
-
-return sd_r3;
-
-default:
-break;
+sd->state = sd_ready_state;
 }
-break;
+
+return sd_r3;
 
 case 42:   /* ACMD42: SET_CLR_CARD_DETECT */
 switch (sd->state) {
-- 
2.15.1




[Qemu-devel] [PATCH v3 18/18] sdcard: add an enum for the SD PHY Spec version

2018-01-22 Thread Philippe Mathieu-Daudé
So far this device intends to model the Spec v1.10

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1f6c4ce2a4..9880a5d090 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -47,6 +47,11 @@
 
 //#define DEBUG_SD 1
 
+typedef enum {
+SD_PHY_SPEC_VER_1_10 = 110,
+SD_PHY_SPEC_VER_2_00 = 200, /* not yet supported */
+} sd_phy_spec_ver_t;
+
 typedef enum {
 sd_r0 = 0,/* no response */
 sd_r1,/* normal response command */
@@ -122,6 +127,7 @@ struct SDState {
 qemu_irq inserted_cb;
 QEMUTimer *ocr_power_timer;
 const char *proto_name;
+int spec_version;
 bool enable;
 uint8_t dat_lines;
 bool cmd_line;
@@ -2191,6 +2197,7 @@ static void sd_realize(DeviceState *dev, Error **errp)
 int ret;
 
 sd->proto_name = sd->spi ? "SPI" : "SD";
+sd->spec_version = SD_PHY_SPEC_VER_1_10;
 
 if (sd->blk && blk_is_read_only(sd->blk)) {
 error_setg(errp, "Cannot use read-only drive as SD card");
-- 
2.15.1




[Qemu-devel] [PATCH v3 02/18] sdcard: update the CSD CRC register regardless the CSD structure version

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 20764451f2..f6318c6fdb 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -377,7 +377,6 @@ static void sd_reset_csd(SDState *sd, uint64_t size)
 sd->csd[13] = 0x20 |   /* Max. write data block length */
 ((HWBLOCK_SHIFT << 6) & 0xc0);
 sd->csd[14] = 0x00;/* File format group */
-sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
 } else {   /* SDHC */
 size /= 512 * 1024;
 size -= 1;
@@ -396,8 +395,8 @@ static void sd_reset_csd(SDState *sd, uint64_t size)
 sd->csd[12] = 0x0a;
 sd->csd[13] = 0x40;
 sd->csd[14] = 0x00;
-sd->csd[15] = 0x00;
 }
+sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
 }
 
 static void sd_reset_rca(SDState *sd)
-- 
2.15.1




[Qemu-devel] [PATCH v3 05/18] sdcard: remove commands from unsupported old MMC specification

2018-01-22 Thread Philippe Mathieu-Daudé
This device does not model MMCA Specification previous to v4.2

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 33 -
 1 file changed, 33 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 5d50d48097..3c66521862 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1044,24 +1044,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 break;
 
-case 11:   /* CMD11:  READ_DAT_UNTIL_STOP */
-if (sd->spi)
-goto bad_cmd;
-switch (sd->state) {
-case sd_transfer_state:
-sd->state = sd_sendingdata_state;
-sd->data_start = req.arg;
-sd->data_offset = 0;
-
-if (sd->data_start + sd->blk_len > sd->size)
-sd->card_status |= ADDRESS_ERROR;
-return sd_r0;
-
-default:
-break;
-}
-break;
-
 case 12:   /* CMD12:  STOP_TRANSMISSION */
 switch (sd->state) {
 case sd_sendingdata_state:
@@ -1874,21 +1856,6 @@ uint8_t sd_read_data(SDState *sd)
 sd->state = sd_transfer_state;
 break;
 
-case 11:   /* CMD11:  READ_DAT_UNTIL_STOP */
-if (sd->data_offset == 0)
-BLK_READ_BLOCK(sd->data_start, io_len);
-ret = sd->data[sd->data_offset ++];
-
-if (sd->data_offset >= io_len) {
-sd->data_start += io_len;
-sd->data_offset = 0;
-if (sd->data_start + io_len > sd->size) {
-sd->card_status |= ADDRESS_ERROR;
-break;
-}
-}
-break;
-
 case 13:   /* ACMD13: SD_STATUS */
 ret = sd->sd_status[sd->data_offset ++];
 
-- 
2.15.1




[Qemu-devel] [PATCH v3 11/18] sdcard: check the card is in correct state for APP CMD (CMD55)

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index bbf9496e8a..434d1fbc47 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1389,6 +1389,14 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 /* Application specific commands (Class 8) */
 case 55:   /* CMD55:  APP_CMD */
+switch (sd->state) {
+case sd_ready_state:
+case sd_identification_state:
+case sd_inactive_state:
+return sd_illegal;
+default:
+break;
+}
 if (!sd->spi) {
 if (sd->rca != rca) {
 return sd_r0;
-- 
2.15.1




[Qemu-devel] [PATCH v3 08/18] sdcard: use the registerfields API for the CARD_STATUS register masks

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 48 +---
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ee381540aa..2eca999bc3 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -423,14 +423,56 @@ static void sd_set_rca(SDState *sd)
 sd->rca += 0x4567;
 }
 
+FIELD(CSR, AKE_SEQ_ERROR,   3,  1)
+FIELD(CSR, APP_CMD, 5,  1)
+FIELD(CSR, FX_EVENT,6,  1)
+FIELD(CSR, READY_FOR_DATA,  8,  1)
+FIELD(CSR, CURRENT_STATE,   9,  4)
+FIELD(CSR, ERASE_RESET,13,  1)
+FIELD(CSR, CARD_ECC_DISABLED,  14,  1)
+FIELD(CSR, WP_ERASE_SKIP,  15,  1)
+FIELD(CSR, CSD_OVERWRITE,  16,  1)
+FIELD(CSR, DEFERRED_RESPONSE,  17,  1)
+FIELD(CSR, ERROR,  19,  1)
+FIELD(CSR, CC_ERROR,   20,  1)
+FIELD(CSR, CARD_ECC_FAILED,21,  1)
+FIELD(CSR, ILLEGAL_COMMAND,22,  1)
+FIELD(CSR, COM_CRC_ERROR,  23,  1)
+FIELD(CSR, LOCK_UNLOCK_FAILED, 24,  1)
+FIELD(CSR, CARD_IS_LOCKED, 25,  1)
+FIELD(CSR, WP_VIOLATION,   26,  1)
+FIELD(CSR, ERASE_PARAM,27,  1)
+FIELD(CSR, ERASE_SEQ_ERROR,28,  1)
+FIELD(CSR, BLOCK_LEN_ERROR,29,  1)
+FIELD(CSR, ADDRESS_ERROR,  30,  1)
+FIELD(CSR, OUT_OF_RANGE,   31,  1)
+
 /* Card status bits, split by clear condition:
  * A : According to the card current state
  * B : Always related to the previous command
  * C : Cleared by read
  */
-#define CARD_STATUS_A  0x02004100
-#define CARD_STATUS_B  0x00c01e00
-#define CARD_STATUS_C  0xfd39a028
+#define CARD_STATUS_A   (R_CSR_READY_FOR_DATA_MASK \
+   | R_CSR_CARD_ECC_DISABLED_MASK \
+   | R_CSR_CARD_IS_LOCKED_MASK)
+#define CARD_STATUS_B   (R_CSR_CURRENT_STATE_MASK \
+   | R_CSR_ILLEGAL_COMMAND_MASK \
+   | R_CSR_COM_CRC_ERROR_MASK)
+#define CARD_STATUS_C   (R_CSR_AKE_SEQ_ERROR_MASK \
+   | R_CSR_APP_CMD_MASK \
+   | R_CSR_ERASE_RESET_MASK \
+   | R_CSR_WP_ERASE_SKIP_MASK \
+   | R_CSR_CSD_OVERWRITE_MASK \
+   | R_CSR_ERROR_MASK \
+   | R_CSR_CC_ERROR_MASK \
+   | R_CSR_CARD_ECC_FAILED_MASK \
+   | R_CSR_LOCK_UNLOCK_FAILED_MASK \
+   | R_CSR_WP_VIOLATION_MASK \
+   | R_CSR_ERASE_PARAM_MASK \
+   | R_CSR_ERASE_SEQ_ERROR_MASK \
+   | R_CSR_BLOCK_LEN_ERROR_MASK \
+   | R_CSR_ADDRESS_ERROR_MASK \
+   | R_CSR_OUT_OF_RANGE_MASK)
 
 static void sd_reset_cardstatus(SDState *sd)
 {
-- 
2.15.1




[Qemu-devel] [PATCH v3 01/18] sdcard: Don't always set the high capacity bit

2018-01-22 Thread Philippe Mathieu-Daudé
Don't set the high capacity bit by default as it will be set if required
in the sd_set_csd() function.

[based on a patch from Alistair Francis 
 and Peter Ogden  from qemu/xilinx tag xilinx-v2015.4]
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 437ce25f79..20764451f2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -289,6 +289,10 @@ static void sd_ocr_powerup(void *opaque)
 
 /* card power-up OK */
 sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1);
+
+if (sd->size > 1 * G_BYTE) {
+sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_CAPACITY, 1);
+}
 }
 
 static void sd_reset_scr(SDState *sd)
@@ -393,7 +397,6 @@ static void sd_reset_csd(SDState *sd, uint64_t size)
 sd->csd[13] = 0x40;
 sd->csd[14] = 0x00;
 sd->csd[15] = 0x00;
-sd->ocr |= 1 << 30; /* High Capacity SD Memory Card */
 }
 }
 
-- 
2.15.1




[Qemu-devel] [PATCH v3 09/18] sdcard: handles more commands in SPI mode

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 57 ++---
 1 file changed, 54 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 2eca999bc3..07424aa56e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1390,9 +1390,11 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 
 /* Application specific commands (Class 8) */
 case 55:   /* CMD55:  APP_CMD */
-if (sd->rca != rca)
-return sd_r0;
-
+if (!sd->spi) {
+if (sd->rca != rca) {
+return sd_r0;
+}
+}
 sd->expecting_acmd = true;
 sd->card_status |= APP_CMD;
 return sd_r1;
@@ -1412,6 +1414,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 }
 break;
 
+case 58:/* CMD58:   READ_OCR (SPI) */
+if (!sd->spi) {
+goto bad_cmd;
+}
+return sd_r3;
+
+case 59:/* CMD59:   CRC_ON_OFF (SPI) */
+if (!sd->spi) {
+goto bad_cmd;
+}
+goto unimplemented_cmd;
+
 default:
 bad_cmd:
 qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd);
@@ -1436,6 +1450,9 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 sd->card_status |= APP_CMD;
 switch (req.cmd) {
 case 6:/* ACMD6:  SET_BUS_WIDTH */
+if (sd->spi) {
+goto unimplemented_cmd;
+}
 switch (sd->state) {
 case sd_transfer_state:
 sd->sd_status[0] &= 0x3f;
@@ -1460,6 +1477,12 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 break;
 
+case 18:
+if (sd->spi) {
+goto unimplemented_cmd;
+}
+break;
+
 case 22:   /* ACMD22: SEND_NUM_WR_BLOCKS */
 switch (sd->state) {
 case sd_transfer_state:
@@ -1485,6 +1508,19 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 break;
 
+case 25:
+case 26:
+if (sd->spi) {
+goto unimplemented_cmd;
+}
+break;
+
+case 38:
+if (sd->spi) {
+goto unimplemented_cmd;
+}
+break;
+
 case 41:   /* ACMD41: SD_APP_OP_COND */
 if (sd->spi) {
 /* SEND_OP_CMD */
@@ -1542,6 +1578,12 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 break;
 
+case 43 ... 49:
+if (sd->spi) {
+goto unimplemented_cmd;
+}
+break;
+
 case 51:   /* ACMD51: SEND_SCR */
 switch (sd->state) {
 case sd_transfer_state:
@@ -1555,9 +1597,18 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 }
 break;
 
+case 55:/* Not exist */
+break;
+
 default:
 /* Fall back to standard commands.  */
 return sd_normal_command(sd, req);
+
+unimplemented_cmd:
+/* Commands that are recognised but not yet implemented in SPI mode.  
*/
+qemu_log_mask(LOG_UNIMP, "SD: CMD%i not implemented in SPI mode\n",
+  req.cmd);
+return sd_illegal;
 }
 
 qemu_log_mask(LOG_GUEST_ERROR, "SD: ACMD%i in a wrong state\n", req.cmd);
-- 
2.15.1




[Qemu-devel] [PATCH v3 04/18] sdcard: clean the SCR register and add few comments

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 56df5b660a..5d50d48097 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -297,10 +297,13 @@ static void sd_ocr_powerup(void *opaque)
 
 static void sd_reset_scr(SDState *sd)
 {
-sd->scr[0] = 0x00; /* SCR Structure */
-sd->scr[1] = 0x2f; /* SD Security Support */
-sd->scr[2] = 0x00;
+sd->scr[0] = (0 << 4)   /* SCR version 1.0 */
+ | 0;   /* Spec Versions 1.0 and 1.01 */
+sd->scr[1] = (2 << 4)   /* SDSC Card (Security Version 1.01) */
+ | 0b0101;  /* 1-bit or 4-bit width bus modes */
+sd->scr[2] = 0x00;  /* Extended Security is not supported. */
 sd->scr[3] = 0x00;
+/* reserved for manufacturer usage */
 sd->scr[4] = 0x00;
 sd->scr[5] = 0x00;
 sd->scr[6] = 0x00;
-- 
2.15.1




[Qemu-devel] [PATCH v3 06/18] sdcard: simplify using the ldst API

2018-01-22 Thread Philippe Mathieu-Daudé
the code is easier to review/refactor.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 38 +-
 1 file changed, 9 insertions(+), 29 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 3c66521862..23f5d47782 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -435,57 +435,39 @@ static int sd_req_crc_validate(SDRequest *req)
 {
 uint8_t buffer[5];
 buffer[0] = 0x40 | req->cmd;
-buffer[1] = (req->arg >> 24) & 0xff;
-buffer[2] = (req->arg >> 16) & 0xff;
-buffer[3] = (req->arg >> 8) & 0xff;
-buffer[4] = (req->arg >> 0) & 0xff;
+stl_be_p([1], req->arg);
 return 0;
 return sd_crc7(buffer, 5) != req->crc; /* TODO */
 }
 
 static void sd_response_r1_make(SDState *sd, uint8_t *response)
 {
-uint32_t status = sd->card_status;
+stl_be_p(response, sd->card_status);
+
 /* Clear the "clear on read" status bits */
 sd->card_status &= ~CARD_STATUS_C;
-
-response[0] = (status >> 24) & 0xff;
-response[1] = (status >> 16) & 0xff;
-response[2] = (status >> 8) & 0xff;
-response[3] = (status >> 0) & 0xff;
 }
 
 static void sd_response_r3_make(SDState *sd, uint8_t *response)
 {
-response[0] = (sd->ocr >> 24) & 0xff;
-response[1] = (sd->ocr >> 16) & 0xff;
-response[2] = (sd->ocr >> 8) & 0xff;
-response[3] = (sd->ocr >> 0) & 0xff;
+stl_be_p(response, sd->ocr);
 }
 
 static void sd_response_r6_make(SDState *sd, uint8_t *response)
 {
-uint16_t arg;
 uint16_t status;
 
-arg = sd->rca;
 status = ((sd->card_status >> 8) & 0xc000) |
  ((sd->card_status >> 6) & 0x2000) |
   (sd->card_status & 0x1fff);
 sd->card_status &= ~(CARD_STATUS_C & 0xc81fff);
-
-response[0] = (arg >> 8) & 0xff;
-response[1] = arg & 0xff;
-response[2] = (status >> 8) & 0xff;
-response[3] = status & 0xff;
+stw_be_p(response + 0, sd->rca);
+stw_be_p(response + 2, status);
 }
 
 static void sd_response_r7_make(SDState *sd, uint8_t *response)
 {
-response[0] = (sd->vhs >> 24) & 0xff;
-response[1] = (sd->vhs >> 16) & 0xff;
-response[2] = (sd->vhs >>  8) & 0xff;
-response[3] = (sd->vhs >>  0) & 0xff;
+stl_be_p(response, sd->vhs);
 }
 
 static inline uint64_t sd_addr_to_wpnum(uint64_t addr)
@@ -731,7 +713,7 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
 
 static void sd_function_switch(SDState *sd, uint32_t arg)
 {
-int i, mode, new_func, crc;
+int i, mode, new_func;
 mode = !!(arg & 0x8000);
 
 sd->data[0] = 0x00;/* Maximum current consumption */
@@ -755,9 +737,7 @@ static void sd_function_switch(SDState *sd, uint32_t arg)
 sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4);
 }
 memset(>data[17], 0, 47);
-crc = sd_crc16(sd->data, 64);
-sd->data[65] = crc >> 8;
-sd->data[66] = crc & 0xff;
+stw_be_p(sd->data + 65, sd_crc16(sd->data, 64));
 }
 
 static inline bool sd_wp_addr(SDState *sd, uint64_t addr)
-- 
2.15.1




[Qemu-devel] [PATCH v3 07/18] sdcard: use the correct masked OCR in the R3 reply

2018-01-22 Thread Philippe Mathieu-Daudé
use the registerfields API to access the OCR register

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 29 +++--
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 23f5d47782..ee381540aa 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -47,8 +47,6 @@
 
 //#define DEBUG_SD 1
 
-#define ACMD41_ENQUIRY_MASK 0x00ff
-
 typedef enum {
 sd_r0 = 0,/* no response */
 sd_r1,/* normal response command */
@@ -271,13 +269,26 @@ static uint16_t sd_crc16(void *message, size_t width)
 
 #define OCR_POWER_DELAY_NS  50 /* 0.5ms */
 
+FIELD(OCR, VDD_VOLTAGE_WINDOW,  0, 24)
+FIELD(OCR, VDD_VOLTAGE_WIN_LO,  0,  8)
+FIELD(OCR, DUAL_VOLTAGE_CARD,   7,  1)
+FIELD(OCR, VDD_VOLTAGE_WIN_HI,  8, 16)
+FIELD(OCR, ACCEPT_SWITCH_1V8,  24,  1) /* Only UHS-I */
+FIELD(OCR, UHS_II_CARD,29,  1) /* Only UHS-II */
 FIELD(OCR, CARD_CAPACITY,  30,  1) /* 0:SDSC, 1:SDHC/SDXC */
 FIELD(OCR, CARD_POWER_UP,  31,  1)
 
+#define ACMD41_ENQUIRY_MASK 0x00ff
+#define ACMD41_R3_MASK  (R_OCR_VDD_VOLTAGE_WIN_HI_MASK \
+   | R_OCR_ACCEPT_SWITCH_1V8_MASK \
+   | R_OCR_UHS_II_CARD_MASK \
+   | R_OCR_CARD_CAPACITY_MASK \
+   | R_OCR_CARD_POWER_UP_MASK)
+
 static void sd_reset_ocr(SDState *sd)
 {
-/* All voltages OK, Standard Capacity SD Memory Card, not yet powered up */
-sd->ocr = 0x0000;
+/* All voltages OK */
+sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK;
 }
 
 static void sd_ocr_powerup(void *opaque)
@@ -450,7 +461,7 @@ static void sd_response_r1_make(SDState *sd, uint8_t 
*response)
 
 static void sd_response_r3_make(SDState *sd, uint8_t *response)
 {
-stl_be_p(response, sd->ocr);
+stl_be_p(response, sd->ocr & ACMD41_R3_MASK);
 }
 
 static void sd_response_r6_make(SDState *sd, uint8_t *response)
@@ -1634,7 +1645,13 @@ send_response:
 }
 
 #ifdef DEBUG_SD
-qemu_hexdump((const char *)response, stderr, "Response", rsplen);
+if (rsplen) {
+int i;
+DPRINTF("Response:");
+for (i = 0; i < rsplen; i++)
+fprintf(stderr, " %02x", response[i]);
+fputc('\n', stderr);
+}
 #endif
 
 return rsplen;
-- 
2.15.1




[Qemu-devel] [PATCH v3 03/18] sdcard: fix the 'maximum data transfer rate' to 25MHz

2018-01-22 Thread Philippe Mathieu-Daudé
To comply with Spec v1.10 (and 2.00, 3.01):

. TRAN_SPEED

for current SD Memory Cards that field must be always 0_0110_010b (032h) which 
is
equal to 25MHz - the mandatory maximum operating frequency of SD Memory Card.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index f6318c6fdb..56df5b660a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -356,7 +356,7 @@ static void sd_reset_csd(SDState *sd, uint64_t size)
 sd->csd[0] = 0x00; /* CSD structure */
 sd->csd[1] = 0x26; /* Data read access-time-1 */
 sd->csd[2] = 0x00; /* Data read access-time-2 */
-sd->csd[3] = 0x5a; /* Max. data transfer rate */
+sd->csd[3] = 0x32;  /* Max. data transfer rate: 25 MHz */
 sd->csd[4] = 0x5f; /* Card Command Classes */
 sd->csd[5] = 0x50 |/* Max. read data block length */
 HWBLOCK_SHIFT;
-- 
2.15.1




[Qemu-devel] [PATCH v3 00/18] SDCard: bugfixes, support UHS-I (part 5)

2018-01-22 Thread Philippe Mathieu-Daudé
Some refactors, few bugfixes, better SD/SPI support.

With this series apply, machines can use cards in UHS-I mode.
(mostly imported from Alistair Francis work)

MMC mode split out for another series.

Since v2:
- split again in 2... other part is cleanup/tracing

Since v1:
- rewrote mostly all patches to keep it simpler.

$ git backport-diff
001/18:[0003] [FC] 'sdcard: Don't always set the high capacity bit'
002/18:[down] 'sdcard: update the CSD CRC register regardless the CSD structure 
version'
003/18:[down] 'sdcard: fix the 'maximum data transfer rate' to 25MHz'
004/18:[down] 'sdcard: clean the SCR register and add few comments'
005/18:[down] 'sdcard: remove commands from unsupported old MMC specification'
006/18:[down] 'sdcard: simplify using the ldst API'
007/18:[down] 'sdcard: use the correct masked OCR in the R3 reply'
008/18:[down] 'sdcard: use the registerfields API for the CARD_STATUS register 
masks'
009/18:[down] 'sdcard: handles more commands in SPI mode'
010/18:[down] 'sdcard: handle CMD54 (SDIO)'
011/18:[down] 'sdcard: check the card is in correct state for APP CMD (CMD55)'
012/18:[down] 'sdcard: warn if host uses an incorrect address for APP CMD 
(CMD55)'
013/18:[down] 'sdcard: simplify SEND_IF_COND (CMD8)'
014/18:[down] 'sdcard: simplify SD_SEND_OP_COND (ACMD41)'
015/18:[down] 'sdcard: add SD SEND_TUNING_BLOCK (CMD19)'
016/18:[down] 'sdcard: add a 'uhs' property, update the OCR register 
ACCEPT_SWITCH_1V8 bit'
017/18:[down] 'sdcard: implement the UHS-I SWITCH_FUNCTION entries (Spec v3)'
018/18:[0006] [FC] 'sdcard: add an enum for the SD PHY Spec version'

Based-on: 20180123032135.28863-13-f4...@amsat.org

Philippe Mathieu-Daudé (18):
  sdcard: Don't always set the high capacity bit
  sdcard: update the CSD CRC register regardless the CSD structure version
  sdcard: fix the 'maximum data transfer rate' to 25MHz
  sdcard: clean the SCR register and add few comments
  sdcard: remove commands from unsupported old MMC specification
  sdcard: simplify using the ldst API
  sdcard: use the correct masked OCR in the R3 reply
  sdcard: use the registerfields API for the CARD_STATUS register masks
  sdcard: handles more commands in SPI mode
  sdcard: handle CMD54 (SDIO)
  sdcard: check the card is in correct state for APP CMD (CMD55)
  sdcard: warn if host uses an incorrect address for APP CMD (CMD55)
  sdcard: simplify SEND_IF_COND (CMD8)
  sdcard: simplify SD_SEND_OP_COND (ACMD41)
  sdcard: add SD SEND_TUNING_BLOCK (CMD19)
  sdcard: add a 'uhs' property, update the OCR register ACCEPT_SWITCH_1V8 bit
  sdcard: implement the UHS-I SWITCH_FUNCTION entries (Spec v3)
  sdcard: add an enum for the SD PHY Spec version

 hw/sd/sd.c | 501 +
 hw/sd/trace-events |   1 +
 2 files changed, 354 insertions(+), 148 deletions(-)

-- 
2.15.1




[Qemu-devel] [PATCH v3 08/12] sdcard: display command name when tracing CMD/ACMD

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdmmc-internal.h | 20 ++
 hw/sd/sd.c | 16 ++-
 hw/sd/sdmmc-common.c   | 72 ++
 hw/sd/Makefile.objs|  2 +-
 hw/sd/trace-events |  8 +++---
 5 files changed, 106 insertions(+), 12 deletions(-)
 create mode 100644 hw/sd/sdmmc-internal.h
 create mode 100644 hw/sd/sdmmc-common.c

diff --git a/hw/sd/sdmmc-internal.h b/hw/sd/sdmmc-internal.h
new file mode 100644
index 00..7db6c63ee7
--- /dev/null
+++ b/hw/sd/sdmmc-internal.h
@@ -0,0 +1,20 @@
+/*
+ * SD/MMC cards common
+ *
+ * Copyright (c) 2018  Philippe Mathieu-Daudé 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef SD_INTERNAL_H
+#define SD_INTERNAL_H
+
+#include "hw/sd/sd.h"
+
+#define SDMMC_CMD_MAX 64
+
+const char *sd_cmd_name(uint8_t cmd);
+const char *sd_acmd_name(uint8_t cmd);
+
+#endif
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 7b1cbc0a2e..e2c4d96d76 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -40,6 +40,7 @@
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
 #include "qemu/log.h"
+#include "sdmmc-internal.h"
 #include "trace.h"
 
 //#define DEBUG_SD 1
@@ -126,8 +127,6 @@ struct SDState {
 bool cmd_line;
 };
 
-#define SDMMC_CMD_MAX 64
-
 static const char *sd_state_name(enum SDCardStates state)
 {
 static const char *state_name[] = {
@@ -827,8 +826,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
 
 if (req.cmd != 55 || sd->expecting_acmd) {
-trace_sdcard_normal_command(req.cmd, req.arg,
-sd_state_name(sd->state));
+trace_sdcard_normal_command(sd_cmd_name(req.cmd), req.cmd,
+req.arg, sd_state_name(sd->state));
 }
 
 /* Not interpreting this as an app command */
@@ -1399,7 +1398,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 static sd_rsp_type_t sd_app_command(SDState *sd,
 SDRequest req)
 {
-trace_sdcard_app_command(req.cmd, req.arg);
+trace_sdcard_app_command(sd_acmd_name(req.cmd),
+ req.cmd, req.arg, sd_state_name(sd->state));
 sd->card_status |= APP_CMD;
 switch (req.cmd) {
 case 6:/* ACMD6:  SET_BUS_WIDTH */
@@ -1697,7 +1697,8 @@ void sd_write_data(SDState *sd, uint8_t value)
 if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
 return;
 
-trace_sdcard_write_data(sd->current_cmd, value);
+trace_sdcard_write_data(sd_acmd_name(sd->current_cmd),
+sd->current_cmd, value);
 switch (sd->current_cmd) {
 case 24:   /* CMD24:  WRITE_SINGLE_BLOCK */
 sd->data[sd->data_offset ++] = value;
@@ -1835,7 +1836,8 @@ uint8_t sd_read_data(SDState *sd)
 
 io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
 
-trace_sdcard_read_data(sd->current_cmd, io_len);
+trace_sdcard_read_data(sd_acmd_name(sd->current_cmd),
+   sd->current_cmd, io_len);
 switch (sd->current_cmd) {
 case 6:/* CMD6:   SWITCH_FUNCTION */
 ret = sd->data[sd->data_offset ++];
diff --git a/hw/sd/sdmmc-common.c b/hw/sd/sdmmc-common.c
new file mode 100644
index 00..1d0198b1ad
--- /dev/null
+++ b/hw/sd/sdmmc-common.c
@@ -0,0 +1,72 @@
+/*
+ * SD/MMC cards common helpers
+ *
+ * Copyright (c) 2018  Philippe Mathieu-Daudé 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "sdmmc-internal.h"
+
+const char *sd_cmd_name(uint8_t cmd)
+{
+static const char *cmd_abbrev[SDMMC_CMD_MAX] = {
+ [0]= "GO_IDLE_STATE",
+ [2]= "ALL_SEND_CID",[3]= "SEND_RELATIVE_ADDR",
+ [4]= "SET_DSR", [5]= "IO_SEND_OP_COND",
+ [6]= "SWITCH_FUNC", [7]= "SELECT/DESELECT_CARD",
+ [8]= "SEND_IF_COND",[9]= "SEND_CSD",
+[10]= "SEND_CID",   [11]= "VOLTAGE_SWITCH",
+[12]= "STOP_TRANSMISSION",  [13]= "SEND_STATUS",
+[15]= "GO_INACTIVE_STATE",
+[16]= "SET_BLOCKLEN",   [17]= "READ_SINGLE_BLOCK",
+[18]= "READ_MULTIPLE_BLOCK",[19]= "SEND_TUNING_BLOCK",
+[20]= "SPEED_CLASS_CONTROL",[21]= "DPS_spec",
+[23]= "SET_BLOCK_COUNT",
+[24]= "WRITE_BLOCK",[25]= "WRITE_MULTIPLE_BLOCK",
+[26]= "MANUF_RSVD", [27]= 

[Qemu-devel] [PATCH v3 11/12] sdcard: use G_BYTE from cutils

2018-01-22 Thread Philippe Mathieu-Daudé
code is now easier to read.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
---
 hw/sd/sd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 8b5022a7db..f87e543f8f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -36,6 +36,7 @@
 #include "hw/sd/sd.h"
 #include "qapi/error.h"
 #include "qemu/bitmap.h"
+#include "qemu/cutils.h"
 #include "hw/qdev-properties.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
@@ -342,7 +343,7 @@ static void sd_reset_csd(SDState *sd, uint64_t size)
 uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1;
 uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1;
 
-if (size <= 0x4000) {  /* Standard Capacity SD */
+if (size <= 1 * G_BYTE) { /* Standard Capacity SD */
 sd->csd[0] = 0x00; /* CSD structure */
 sd->csd[1] = 0x26; /* Data read access-time-1 */
 sd->csd[2] = 0x00; /* Data read access-time-2 */
-- 
2.15.1




[Qemu-devel] [PATCH v3 05/12] sdcard: add more trace events

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 32 ++--
 hw/sd/trace-events | 13 +
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 03263e08ae..dc4b2329e4 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -177,6 +177,8 @@ static bool sd_get_cmd_line(SDState *sd)
 
 static void sd_set_voltage(SDState *sd, uint16_t millivolts)
 {
+trace_sdcard_set_voltage(millivolts);
+
 switch (millivolts) {
 case 3001 ... 3600: /* SD_VOLTAGE_3_3V */
 case 2001 ... 3000: /* SD_VOLTAGE_3_0V */
@@ -272,6 +274,7 @@ static void sd_ocr_powerup(void *opaque)
 {
 SDState *sd = opaque;
 
+trace_sdcard_powerup();
 /* Set powered up bit in OCR */
 assert(!(sd->ocr & OCR_POWER_UP));
 sd->ocr |= OCR_POWER_UP;
@@ -475,6 +478,7 @@ static void sd_reset(DeviceState *dev)
 uint64_t size;
 uint64_t sect;
 
+trace_sdcard_reset();
 if (sd->blk) {
 blk_get_geometry(sd->blk, );
 } else {
@@ -528,7 +532,10 @@ static void sd_cardchange(void *opaque, bool load, Error 
**errp)
 bool readonly = sd_get_readonly(sd);
 
 if (inserted) {
+trace_sdcard_inserted(readonly);
 sd_reset(dev);
+} else {
+trace_sdcard_ejected();
 }
 
 /* The IRQ notification is for legacy non-QOM SD controller devices;
@@ -660,6 +667,7 @@ static void sd_erase(SDState *sd)
 uint64_t erase_start = sd->erase_start;
 uint64_t erase_end = sd->erase_end;
 
+trace_sdcard_erase();
 if (!sd->erase_start || !sd->erase_end) {
 sd->card_status |= ERASE_SEQ_ERROR;
 return;
@@ -749,6 +757,11 @@ static void sd_lock_command(SDState *sd)
 else
 pwd_len = 0;
 
+if (lock) {
+trace_sdcard_lock();
+} else {
+trace_sdcard_unlock();
+}
 if (erase) {
 if (!(sd->card_status & CARD_IS_LOCKED) || sd->blk_len > 1 ||
 set_pwd || clr_pwd || lock || sd->wp_switch ||
@@ -1075,10 +1088,12 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 case 16:   /* CMD16:  SET_BLOCKLEN */
 switch (sd->state) {
 case sd_transfer_state:
-if (req.arg > (1 << HWBLOCK_SHIFT))
+if (req.arg > (1 << HWBLOCK_SHIFT)) {
 sd->card_status |= BLOCK_LEN_ERROR;
-else
+} else {
+trace_sdcard_set_blocklen(req.arg);
 sd->blk_len = req.arg;
+}
 
 return sd_r1;
 
@@ -1450,10 +1465,13 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
 if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) {
 timer_del(sd->ocr_power_timer);
 sd_ocr_powerup(sd);
-} else if (!timer_pending(sd->ocr_power_timer)) {
-timer_mod_ns(sd->ocr_power_timer,
- (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
-  + OCR_POWER_DELAY_NS));
+} else {
+trace_sdcard_inquiry_cmd41();
+if (!timer_pending(sd->ocr_power_timer)) {
+timer_mod_ns(sd->ocr_power_timer,
+ (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
+  + OCR_POWER_DELAY_NS));
+}
 }
 }
 
@@ -1666,6 +1684,7 @@ void sd_write_data(SDState *sd, uint8_t value)
 if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
 return;
 
+trace_sdcard_write_data(sd->current_cmd, value);
 switch (sd->current_cmd) {
 case 24:   /* CMD24:  WRITE_SINGLE_BLOCK */
 sd->data[sd->data_offset ++] = value;
@@ -1803,6 +1822,7 @@ uint8_t sd_read_data(SDState *sd)
 
 io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
 
+trace_sdcard_read_data(sd->current_cmd, io_len);
 switch (sd->current_cmd) {
 case 6:/* CMD6:   SWITCH_FUNCTION */
 ret = sd->data[sd->data_offset ++];
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index b2aa19ec0d..3040d32560 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -27,8 +27,21 @@ sdhci_capareg(const char *desc, uint16_t val) "%s: %u"
 sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d arg 
0x%08x (state %s)"
 sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x"
 sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
+sdcard_powerup(void) ""
+sdcard_inquiry_cmd41(void) ""
+sdcard_set_enable(bool current_state, bool new_state) "%u -> %u"
+sdcard_reset(void) ""
+sdcard_set_blocklen(uint16_t length) "0x%04x"
+sdcard_inserted(bool readonly) "read_only: %u"
+sdcard_ejected(void) ""
+sdcard_erase(void) ""
+sdcard_lock(void) ""
+sdcard_unlock(void) ""
 sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"

[Qemu-devel] [PATCH v3 09/12] sdcard: display protocol used when tracing

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 14 ++
 hw/sd/trace-events |  8 
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index e2c4d96d76..c46e9c2818 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -122,6 +122,7 @@ struct SDState {
 qemu_irq readonly_cb;
 qemu_irq inserted_cb;
 QEMUTimer *ocr_power_timer;
+const char *proto_name;
 bool enable;
 uint8_t dat_lines;
 bool cmd_line;
@@ -826,7 +827,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
 
 if (req.cmd != 55 || sd->expecting_acmd) {
-trace_sdcard_normal_command(sd_cmd_name(req.cmd), req.cmd,
+trace_sdcard_normal_command(sd->proto_name,
+sd_cmd_name(req.cmd), req.cmd,
 req.arg, sd_state_name(sd->state));
 }
 
@@ -1398,7 +1400,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 static sd_rsp_type_t sd_app_command(SDState *sd,
 SDRequest req)
 {
-trace_sdcard_app_command(sd_acmd_name(req.cmd),
+trace_sdcard_app_command(sd->proto_name, sd_acmd_name(req.cmd),
  req.cmd, req.arg, sd_state_name(sd->state));
 sd->card_status |= APP_CMD;
 switch (req.cmd) {
@@ -1697,7 +1699,8 @@ void sd_write_data(SDState *sd, uint8_t value)
 if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
 return;
 
-trace_sdcard_write_data(sd_acmd_name(sd->current_cmd),
+trace_sdcard_write_data(sd->proto_name,
+sd_acmd_name(sd->current_cmd),
 sd->current_cmd, value);
 switch (sd->current_cmd) {
 case 24:   /* CMD24:  WRITE_SINGLE_BLOCK */
@@ -1836,7 +1839,8 @@ uint8_t sd_read_data(SDState *sd)
 
 io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
 
-trace_sdcard_read_data(sd_acmd_name(sd->current_cmd),
+trace_sdcard_read_data(sd->proto_name,
+   sd_acmd_name(sd->current_cmd),
sd->current_cmd, io_len);
 switch (sd->current_cmd) {
 case 6:/* CMD6:   SWITCH_FUNCTION */
@@ -1978,6 +1982,8 @@ static void sd_realize(DeviceState *dev, Error **errp)
 SDState *sd = SD_CARD(dev);
 int ret;
 
+sd->proto_name = sd->spi ? "SPI" : "SD";
+
 if (sd->blk && blk_is_read_only(sd->blk)) {
 error_setg(errp, "Cannot use read-only drive as SD card");
 return;
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index cdddca3dbf..2059ace61f 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -24,8 +24,8 @@ sdhci_write_dataport(uint16_t data_count) "write buffer 
filled with %u bytes of
 sdhci_capareg(const char *desc, uint16_t val) "%s: %u"
 
 # hw/sd/sd.c
-sdcard_normal_command(const char *cmd_desc, uint8_t cmd, uint32_t arg, const 
char *state) "%20s/ CMD%02d arg 0x%08x (state %s)"
-sdcard_app_command(const char *acmd_desc, uint8_t acmd, uint32_t arg, const 
char *state) "%23s/ACMD%02d arg 0x%08x (state %s)"
+sdcard_normal_command(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint32_t arg, const char *state) "%s %20s/ CMD%02d arg 0x%08x (state %s)"
+sdcard_app_command(const char *proto, const char *acmd_desc, uint8_t acmd, 
uint32_t arg, const char *state) "%s %23s/ACMD%02d arg 0x%08x (state %s)"
 sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
 sdcard_powerup(void) ""
 sdcard_inquiry_cmd41(void) ""
@@ -39,8 +39,8 @@ sdcard_lock(void) ""
 sdcard_unlock(void) ""
 sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
-sdcard_write_data(const char *cmd_desc, uint8_t cmd, uint8_t value) "%20s/ 
CMD%02d value 0x%02x"
-sdcard_read_data(const char *cmd_desc, uint8_t cmd, int length) "%20s/ CMD%02d 
len %d"
+sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, 
uint8_t value) "%s %20s/ CMD%02d value 0x%02x"
+sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, int 
length) "%s %20s/ CMD%02d len %d"
 sdcard_set_voltage(uint16_t millivolts) "%u mV"
 
 # hw/sd/milkymist-memcard.c
-- 
2.15.1




[Qemu-devel] [PATCH v3 12/12] sdcard: use the registerfields API to access the OCR register

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h |  1 -
 hw/sd/sd.c | 21 +
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index bf1eb0713c..9bdb3c9285 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -53,7 +53,6 @@
 #define READY_FOR_DATA (1 << 8)
 #define APP_CMD(1 << 5)
 #define AKE_SEQ_ERROR  (1 << 3)
-#define OCR_CCS_BITN30
 
 typedef enum {
 SD_VOLTAGE_0_4V = 400,  /* currently not supported */
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index f87e543f8f..437ce25f79 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -32,6 +32,7 @@
 #include "qemu/osdep.h"
 #include "hw/qdev.h"
 #include "hw/hw.h"
+#include "hw/registerfields.h"
 #include "sysemu/block-backend.h"
 #include "hw/sd/sd.h"
 #include "qapi/error.h"
@@ -47,8 +48,6 @@
 //#define DEBUG_SD 1
 
 #define ACMD41_ENQUIRY_MASK 0x00ff
-#define OCR_POWER_UP0x8000
-#define OCR_POWER_DELAY_NS  50 /* 0.5ms */
 
 typedef enum {
 sd_r0 = 0,/* no response */
@@ -270,6 +269,11 @@ static uint16_t sd_crc16(void *message, size_t width)
 return shift_reg;
 }
 
+#define OCR_POWER_DELAY_NS  50 /* 0.5ms */
+
+FIELD(OCR, CARD_CAPACITY,  30,  1) /* 0:SDSC, 1:SDHC/SDXC */
+FIELD(OCR, CARD_POWER_UP,  31,  1)
+
 static void sd_reset_ocr(SDState *sd)
 {
 /* All voltages OK, Standard Capacity SD Memory Card, not yet powered up */
@@ -281,9 +285,10 @@ static void sd_ocr_powerup(void *opaque)
 SDState *sd = opaque;
 
 trace_sdcard_powerup();
-/* Set powered up bit in OCR */
-assert(!(sd->ocr & OCR_POWER_UP));
-sd->ocr |= OCR_POWER_UP;
+assert(!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP));
+
+/* card power-up OK */
+sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1);
 }
 
 static void sd_reset_scr(SDState *sd)
@@ -574,7 +579,7 @@ static bool sd_ocr_vmstate_needed(void *opaque)
 SDState *sd = opaque;
 
 /* Include the OCR state (and timer) if it is not yet powered up */
-return !(sd->ocr & OCR_POWER_UP);
+return !FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP);
 }
 
 static const VMStateDescription sd_ocr_vmstate = {
@@ -684,7 +689,7 @@ static void sd_erase(SDState *sd)
 return;
 }
 
-if (extract32(sd->ocr, OCR_CCS_BITN, 1)) {
+if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) {
 /* High capacity memory card: erase units are 512 byte blocks */
 erase_start *= 512;
 erase_end *= 512;
@@ -1476,7 +1481,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
  * UEFI, which sends an initial enquiry ACMD41, but
  * assumes that the card is in ready state as soon as it
  * sees the power up bit set. */
-if (!(sd->ocr & OCR_POWER_UP)) {
+if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) {
 if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) {
 timer_del(sd->ocr_power_timer);
 sd_ocr_powerup(sd);
-- 
2.15.1




[Qemu-devel] [PATCH v3 04/12] sdcard: replace fprintf() by qemu_hexdump()

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 3590099ce8..03263e08ae 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -44,13 +44,6 @@
 
 //#define DEBUG_SD 1
 
-#ifdef DEBUG_SD
-#define DPRINTF(fmt, ...) \
-do { fprintf(stderr, "SD: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
-
 #define ACMD41_ENQUIRY_MASK 0x00ff
 #define OCR_POWER_UP0x8000
 #define OCR_POWER_DELAY_NS  50 /* 0.5ms */
@@ -1630,13 +1623,7 @@ send_response:
 }
 
 #ifdef DEBUG_SD
-if (rsplen) {
-int i;
-DPRINTF("Response:");
-for (i = 0; i < rsplen; i++)
-fprintf(stderr, " %02x", response[i]);
-fputc('\n', stderr);
-}
+qemu_hexdump((const char *)response, stderr, "Response", rsplen);
 #endif
 
 return rsplen;
-- 
2.15.1




[Qemu-devel] [PATCH v3 07/12] sdcard: define SDMMC_CMD_MAX instead of using the magic '64'

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
---
 hw/sd/sd.c | 23 +--
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 27c08aa894..7b1cbc0a2e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -126,6 +126,8 @@ struct SDState {
 bool cmd_line;
 };
 
+#define SDMMC_CMD_MAX 64
+
 static const char *sd_state_name(enum SDCardStates state)
 {
 static const char *state_name[] = {
@@ -213,18 +215,21 @@ static void sd_set_mode(SDState *sd)
 }
 }
 
-static const sd_cmd_type_t sd_cmd_type[64] = {
+static const sd_cmd_type_t sd_cmd_type[SDMMC_CMD_MAX] = {
 sd_bc,   sd_none, sd_bcr,  sd_bcr,  sd_none, sd_none, sd_none, sd_ac,
 sd_bcr,  sd_ac,   sd_ac,   sd_adtc, sd_ac,   sd_ac,   sd_none, sd_ac,
+/* 16 */
 sd_ac,   sd_adtc, sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none,
 sd_adtc, sd_adtc, sd_adtc, sd_adtc, sd_ac,   sd_ac,   sd_adtc, sd_none,
+/* 32 */
 sd_ac,   sd_ac,   sd_none, sd_none, sd_none, sd_none, sd_ac,   sd_none,
 sd_none, sd_none, sd_bc,   sd_none, sd_none, sd_none, sd_none, sd_none,
+/* 48 */
 sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac,
 sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
 };
 
-static const int sd_cmd_class[64] = {
+static const int sd_cmd_class[SDMMC_CMD_MAX] = {
 0,  0,  0,  0,  0,  9, 10,  0,  0,  0,  0,  1,  0,  0,  0,  0,
 2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,
 5,  5, 10, 10, 10, 10,  5,  9,  9,  9,  7,  7,  7,  7,  7,  7,
@@ -829,8 +834,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, 
SDRequest req)
 /* Not interpreting this as an app command */
 sd->card_status &= ~APP_CMD;
 
-if (sd_cmd_type[req.cmd & 0x3F] == sd_ac
-|| sd_cmd_type[req.cmd & 0x3F] == sd_adtc) {
+if (sd_cmd_type[req.cmd] == sd_ac
+|| sd_cmd_type[req.cmd] == sd_adtc) {
 rca = req.arg >> 16;
 }
 
@@ -1542,8 +1547,8 @@ static int cmd_valid_while_locked(SDState *sd, SDRequest 
*req)
 if (req->cmd == 16 || req->cmd == 55) {
 return 1;
 }
-return sd_cmd_class[req->cmd & 0x3F] == 0
-|| sd_cmd_class[req->cmd & 0x3F] == 7;
+return sd_cmd_class[req->cmd] == 0
+|| sd_cmd_class[req->cmd] == 7;
 }
 
 int sd_do_command(SDState *sd, SDRequest *req,
@@ -1562,6 +1567,12 @@ int sd_do_command(SDState *sd, SDRequest *req,
 goto send_response;
 }
 
+if (req->cmd >= SDMMC_CMD_MAX) {
+qemu_log_mask(LOG_GUEST_ERROR, "SD: incorrect command 0x%02x\n",
+  req->cmd);
+req->cmd &= 0x3f;
+}
+
 if (sd->card_status & CARD_IS_LOCKED) {
 if (!cmd_valid_while_locked(sd, req)) {
 sd->card_status |= ILLEGAL_COMMAND;
-- 
2.15.1




[Qemu-devel] [PATCH v3 10/12] sdcard: rename sd_set_$REG() functions called once as sd_reset_$REG()

2018-01-22 Thread Philippe Mathieu-Daudé
All are only called once at reset.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 31 ++-
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index c46e9c2818..8b5022a7db 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -269,7 +269,7 @@ static uint16_t sd_crc16(void *message, size_t width)
 return shift_reg;
 }
 
-static void sd_set_ocr(SDState *sd)
+static void sd_reset_ocr(SDState *sd)
 {
 /* All voltages OK, Standard Capacity SD Memory Card, not yet powered up */
 sd->ocr = 0x0000;
@@ -285,7 +285,7 @@ static void sd_ocr_powerup(void *opaque)
 sd->ocr |= OCR_POWER_UP;
 }
 
-static void sd_set_scr(SDState *sd)
+static void sd_reset_scr(SDState *sd)
 {
 sd->scr[0] = 0x00; /* SCR Structure */
 sd->scr[1] = 0x2f; /* SD Security Support */
@@ -304,7 +304,7 @@ static void sd_set_scr(SDState *sd)
 #define MDT_YR 2006
 #define MDT_MON2
 
-static void sd_set_cid(SDState *sd)
+static void sd_reset_cid(SDState *sd)
 {
 sd->cid[0] = MID;  /* Fake card manufacturer ID (MID) */
 sd->cid[1] = OID[0];   /* OEM/Application ID (OID) */
@@ -336,7 +336,7 @@ static const uint8_t sd_csd_rw_mask[16] = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe,
 };
 
-static void sd_set_csd(SDState *sd, uint64_t size)
+static void sd_reset_csd(SDState *sd, uint64_t size)
 {
 uint32_t csize = (size >> (CMULT_SHIFT + HWBLOCK_SHIFT)) - 1;
 uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1;
@@ -391,6 +391,11 @@ static void sd_set_csd(SDState *sd, uint64_t size)
 }
 }
 
+static void sd_reset_rca(SDState *sd)
+{
+sd->rca = 0;
+}
+
 static void sd_set_rca(SDState *sd)
 {
 sd->rca += 0x4567;
@@ -405,12 +410,12 @@ static void sd_set_rca(SDState *sd)
 #define CARD_STATUS_B  0x00c01e00
 #define CARD_STATUS_C  0xfd39a028
 
-static void sd_set_cardstatus(SDState *sd)
+static void sd_reset_cardstatus(SDState *sd)
 {
 sd->card_status = 0x0100;
 }
 
-static void sd_set_sdstatus(SDState *sd)
+static void sd_reset_sdstatus(SDState *sd)
 {
 memset(sd->sd_status, 0, 64);
 }
@@ -494,13 +499,13 @@ static void sd_reset(DeviceState *dev)
 sect = sd_addr_to_wpnum(size) + 1;
 
 sd->state = sd_idle_state;
-sd->rca = 0x;
-sd_set_ocr(sd);
-sd_set_scr(sd);
-sd_set_cid(sd);
-sd_set_csd(sd, size);
-sd_set_cardstatus(sd);
-sd_set_sdstatus(sd);
+sd_reset_rca(sd);
+sd_reset_ocr(sd);
+sd_reset_scr(sd);
+sd_reset_cid(sd);
+sd_reset_csd(sd, size);
+sd_reset_cardstatus(sd);
+sd_reset_sdstatus(sd);
 
 g_free(sd->wp_groups);
 sd->wp_switch = sd->blk ? blk_is_read_only(sd->blk) : false;
-- 
2.15.1




[Qemu-devel] [PATCH v3 03/12] sdcard: add a trace event for command responses

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 26 +++---
 hw/sd/trace-events |  1 +
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index f876973a2b..3590099ce8 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -152,6 +152,26 @@ static const char *sd_state_name(enum SDCardStates state)
 return state_name[state];
 }
 
+static const char *sd_response_name(sd_rsp_type_t rsp)
+{
+static const char *response_name[] = {
+[sd_r0] = "RESP#0 (no response)",
+[sd_r1] = "RESP#1 (normal cmd)",
+[sd_r2_i]   = "RESP#2 (CID reg)",
+[sd_r2_s]   = "RESP#2 (CSD reg)",
+[sd_r3] = "RESP#3 (OCR reg)",
+[sd_r6] = "RESP#6 (RCA)",
+[sd_r7] = "RESP#7 (operating voltage)",
+};
+if (rsp == sd_illegal) {
+return "ILLEGAL RESP";
+}
+if (rsp == sd_r1b) {
+rsp = sd_r1;
+}
+return response_name[rsp];
+}
+
 static uint8_t sd_get_dat_lines(SDState *sd)
 {
 return sd->enable ? sd->dat_lines : 0;
@@ -1595,10 +1615,12 @@ send_response:
 
 case sd_r0:
 case sd_illegal:
-default:
 rsplen = 0;
 break;
+default:
+g_assert_not_reached();
 }
+trace_sdcard_response(sd_response_name(rtype), rsplen);
 
 if (rtype != sd_illegal) {
 /* Clear the "clear on valid command" status bits now we've
@@ -1614,8 +1636,6 @@ send_response:
 for (i = 0; i < rsplen; i++)
 fprintf(stderr, " %02x", response[i]);
 fputc('\n', stderr);
-} else {
-DPRINTF("No response %d\n", sd->state);
 }
 #endif
 
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 75dac5a2cd..b2aa19ec0d 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -26,6 +26,7 @@ sdhci_capareg(const char *desc, uint16_t val) "%s: %u"
 # hw/sd/sd.c
 sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d arg 
0x%08x (state %s)"
 sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x"
+sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
 sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
 
-- 
2.15.1




[Qemu-devel] [PATCH v3 01/12] sdcard: reorder SDState struct members

2018-01-22 Thread Philippe Mathieu-Daudé
place card registers first, this will ease further code movements.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
---
 hw/sd/sd.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ab9be561d2..55d2ba2dd7 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -88,16 +88,21 @@ enum SDCardStates {
 struct SDState {
 DeviceState parent_obj;
 
-uint32_t mode;/* current card mode, one of SDCardModes */
-int32_t state;/* current card state, one of SDCardStates */
+/* SD Memory Card Registers */
 uint32_t ocr;
-QEMUTimer *ocr_power_timer;
 uint8_t scr[8];
 uint8_t cid[16];
 uint8_t csd[16];
 uint16_t rca;
 uint32_t card_status;
 uint8_t sd_status[64];
+
+/* Configurable properties */
+BlockBackend *blk;
+bool spi;
+
+uint32_t mode;/* current card mode, one of SDCardModes */
+int32_t state;/* current card state, one of SDCardStates */
 uint32_t vhs;
 bool wp_switch;
 unsigned long *wp_groups;
@@ -110,8 +115,6 @@ struct SDState {
 uint8_t pwd[16];
 uint32_t pwd_len;
 uint8_t function_group[6];
-
-bool spi;
 uint8_t current_cmd;
 /* True if we will handle the next command as an ACMD. Note that this does
  * *not* track the APP_CMD status bit!
@@ -123,8 +126,7 @@ struct SDState {
 uint8_t data[512];
 qemu_irq readonly_cb;
 qemu_irq inserted_cb;
-BlockBackend *blk;
-
+QEMUTimer *ocr_power_timer;
 bool enable;
 uint8_t dat_lines;
 bool cmd_line;
-- 
2.15.1




[Qemu-devel] [PATCH v3 00/12] SDCard: housekeeping, add tracing (part 4)

2018-01-22 Thread Philippe Mathieu-Daudé
Since v2:
- split again in 2... this part is cleanup/tracing
- add more tracepoints
- move some code reusable by sdbus in sdmmc-internal.h

Since v1:
- rewrote mostly all patches to keep it simpler.

$ git backport-diff
001/12:[0007] [FC] 'sdcard: reorder SDState struct members'
002/12:[0002] [FC] 'sdcard: replace DPRINTF() by trace events'
003/12:[down] 'sdcard: add a trace event for command responses'
004/12:[down] 'sdcard: replace fprintf() by qemu_hexdump()'
005/12:[0035] [FC] 'sdcard: add more trace events'
006/12:[down] 'sdcard: do not trace CMD55 when expecting ACMD'
007/12:[down] 'sdcard: define SDMMC_CMD_MAX instead of using the magic '64''
008/12:[0083] [FC] 'sdcard: display command name when tracing CMD/ACMD'
009/12:[down] 'sdcard: display protocol used when tracing'
010/12:[] [--] 'sdcard: rename sd_set_$REG() functions called once as 
sd_reset_$REG()'
011/12:[0002] [FC] 'sdcard: use G_BYTE from cutils'
012/12:[0008] [FC] 'sdcard: use the registerfields API to access the OCR 
register'

Based-on: 20180123030630.26613-15-f4...@amsat.org

Philippe Mathieu-Daudé (12):
  sdcard: reorder SDState struct members
  sdcard: replace DPRINTF() by trace events
  sdcard: add a trace event for command responses
  sdcard: replace fprintf() by qemu_hexdump()
  sdcard: add more trace events
  sdcard: do not trace CMD55 when expecting ACMD
  sdcard: define SDMMC_CMD_MAX instead of using the magic '64'
  sdcard: display command name when tracing CMD/ACMD
  sdcard: display protocol used when tracing
  sdcard: rename sd_set_$REG() functions called once as sd_reset_$REG()
  sdcard: use G_BYTE from cutils
  sdcard: use the registerfields API to access the OCR register

 include/hw/sd/sd.h |   1 -
 hw/sd/sdmmc-internal.h |  20 +
 hw/sd/sd.c | 212 ++---
 hw/sd/sdmmc-common.c   |  72 +
 hw/sd/Makefile.objs|   2 +-
 hw/sd/trace-events |  20 +
 6 files changed, 259 insertions(+), 68 deletions(-)
 create mode 100644 hw/sd/sdmmc-internal.h
 create mode 100644 hw/sd/sdmmc-common.c

-- 
2.15.1




[Qemu-devel] [PATCH v3 06/12] sdcard: do not trace CMD55 when expecting ACMD

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index dc4b2329e4..27c08aa894 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -816,13 +816,15 @@ static void sd_lock_command(SDState *sd)
 sd->card_status &= ~CARD_IS_LOCKED;
 }
 
-static sd_rsp_type_t sd_normal_command(SDState *sd,
-   SDRequest req)
+static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
 {
 uint32_t rca = 0x;
 uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
 
-trace_sdcard_normal_command(req.cmd, req.arg, sd_state_name(sd->state));
+if (req.cmd != 55 || sd->expecting_acmd) {
+trace_sdcard_normal_command(req.cmd, req.arg,
+sd_state_name(sd->state));
+}
 
 /* Not interpreting this as an app command */
 sd->card_status &= ~APP_CMD;
-- 
2.15.1




[Qemu-devel] [PATCH v3 02/12] sdcard: replace DPRINTF() by trace events

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 33 ++---
 hw/sd/trace-events |  6 ++
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 55d2ba2dd7..f876973a2b 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -40,6 +40,7 @@
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
 #include "qemu/log.h"
+#include "trace.h"
 
 //#define DEBUG_SD 1
 
@@ -132,6 +133,25 @@ struct SDState {
 bool cmd_line;
 };
 
+static const char *sd_state_name(enum SDCardStates state)
+{
+static const char *state_name[] = {
+[sd_idle_state] = "idle",
+[sd_ready_state]= "ready",
+[sd_identification_state]   = "identification",
+[sd_standby_state]  = "standby",
+[sd_transfer_state] = "transfer",
+[sd_sendingdata_state]  = "sendingdata",
+[sd_receivingdata_state]= "receivingdata",
+[sd_programming_state]  = "programming",
+[sd_disconnect_state]   = "disconnect",
+};
+if (state == sd_inactive_state) {
+return "inactive";
+}
+return state_name[state];
+}
+
 static uint8_t sd_get_dat_lines(SDState *sd)
 {
 return sd->enable ? sd->dat_lines : 0;
@@ -776,6 +796,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 uint32_t rca = 0x;
 uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg;
 
+trace_sdcard_normal_command(req.cmd, req.arg, sd_state_name(sd->state));
+
 /* Not interpreting this as an app command */
 sd->card_status &= ~APP_CMD;
 
@@ -790,7 +812,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 sd->multi_blk_cnt = 0;
 }
 
-DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state);
 switch (req.cmd) {
 /* Basic commands (Class 0 and Class 1) */
 case 0:/* CMD0:   GO_IDLE_STATE */
@@ -1310,8 +1331,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 return sd_r1;
 
 case 56:   /* CMD56:  GEN_CMD */
-fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg);
-
 switch (sd->state) {
 case sd_transfer_state:
 sd->data_offset = 0;
@@ -1345,7 +1364,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 static sd_rsp_type_t sd_app_command(SDState *sd,
 SDRequest req)
 {
-DPRINTF("ACMD%d 0x%08x\n", req.cmd, req.arg);
+trace_sdcard_app_command(req.cmd, req.arg);
 sd->card_status |= APP_CMD;
 switch (req.cmd) {
 case 6:/* ACMD6:  SET_BUS_WIDTH */
@@ -1594,7 +1613,7 @@ send_response:
 DPRINTF("Response:");
 for (i = 0; i < rsplen; i++)
 fprintf(stderr, " %02x", response[i]);
-fprintf(stderr, " state %d\n", sd->state);
+fputc('\n', stderr);
 } else {
 DPRINTF("No response %d\n", sd->state);
 }
@@ -1605,8 +1624,7 @@ send_response:
 
 static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
 {
-DPRINTF("sd_blk_read: addr = 0x%08llx, len = %d\n",
-(unsigned long long) addr, len);
+trace_sdcard_read_block(addr, len);
 if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) {
 fprintf(stderr, "sd_blk_read: read error on host side\n");
 }
@@ -1614,6 +1632,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, 
uint32_t len)
 
 static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
 {
+trace_sdcard_write_block(addr, len);
 if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) {
 fprintf(stderr, "sd_blk_write: write error on host side\n");
 }
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 0f8536db32..75dac5a2cd 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -23,6 +23,12 @@ sdhci_read_dataport(uint16_t data_count) "all %u bytes of 
data have been read fr
 sdhci_write_dataport(uint16_t data_count) "write buffer filled with %u bytes 
of data"
 sdhci_capareg(const char *desc, uint16_t val) "%s: %u"
 
+# hw/sd/sd.c
+sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d arg 
0x%08x (state %s)"
+sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x"
+sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
+sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
+
 # hw/sd/milkymist-memcard.c
 milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x 
value 0x%08x"
 milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x 
value 0x%08x"
-- 
2.15.1




[Qemu-devel] [PATCH v8 13/14] sdhci: add a check_capab_v3() qtest

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Stefan Hajnoczi 
---
 tests/sdhci-test.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
index 56eefdafd8..a8970da71a 100644
--- a/tests/sdhci-test.c
+++ b/tests/sdhci-test.c
@@ -16,6 +16,8 @@
 #define SDHC_CAPAB  0x40
 FIELD(SDHC_CAPAB, BASECLKFREQ,   8, 8); /* since v2 */
 FIELD(SDHC_CAPAB, SDMA, 22, 1);
+FIELD(SDHC_CAPAB, SDR,  32, 3); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER,   36, 3); /* since v3 */
 #define SDHC_HCVER  0xFE
 
 static const struct sdhci_t {
@@ -160,6 +162,20 @@ static void check_capab_sdma(uintptr_t addr, bool 
supported)
 g_assert_cmpuint(capab_sdma, ==, supported);
 }
 
+static void check_capab_v3(uintptr_t addr, uint8_t version)
+{
+uint64_t capab, capab_v3;
+
+if (version < 3) {
+/* before v3 those fields are RESERVED */
+capab = sdhci_readq(addr, SDHC_CAPAB);
+capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, SDR);
+g_assert_cmpuint(capab_v3, ==, 0);
+capab_v3 = FIELD_EX64(capab, SDHC_CAPAB, DRIVER);
+g_assert_cmpuint(capab_v3, ==, 0);
+}
+}
+
 static void machine_start(const struct sdhci_t *test)
 {
 if (test->pci.vendor_id) {
@@ -202,6 +218,7 @@ static void test_machine(const void *data)
 check_specs_version(test->sdhci.addr, test->sdhci.version);
 check_capab_capareg(test->sdhci.addr, test->sdhci.capab.reg);
 check_capab_readonly(test->sdhci.addr);
+check_capab_v3(test->sdhci.addr, test->sdhci.version);
 check_capab_sdma(test->sdhci.addr, test->sdhci.capab.sdma);
 check_capab_baseclock(test->sdhci.addr, test->sdhci.baseclock);
 
-- 
2.15.1




[Qemu-devel] [PATCH v8 09/14] hw/arm/fsl-imx6: implement SDHCI Spec. v3

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
various FreeBSD console output from google search show this register having
a value of 0x0377c800.

 hw/arm/fsl-imx6.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index b0d4088290..1f4607f206 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -27,6 +27,8 @@
 #include "chardev/char.h"
 #include "qemu/error-report.h"
 
+#define IMX6_ESDHC_CAPABILITIES 0x057834b4
+
 #define NAME_SIZE 20
 
 static void fsl_imx6_init(Object *obj)
@@ -348,6 +350,11 @@ static void fsl_imx6_realize(DeviceState *dev, Error 
**errp)
 { FSL_IMX6_uSDHC4_ADDR, FSL_IMX6_uSDHC4_IRQ },
 };
 
+/* UHS-I SDIO3.0 SDR104 1.8V ADMA */
+object_property_set_uint(OBJECT(>esdhc[i]), 3, "sd-spec-version",
+ );
+object_property_set_uint(OBJECT(>esdhc[i]), IMX6_ESDHC_CAPABILITIES,
+ "capareg", );
 object_property_set_bool(OBJECT(>esdhc[i]), true, "realized", );
 if (err) {
 error_propagate(errp, err);
-- 
2.15.1




[Qemu-devel] [PATCH v8 08/14] hw/arm/bcm2835_peripherals: change maximum block size to 1kB

2018-01-22 Thread Philippe Mathieu-Daudé
following the datasheet.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/bcm2835_peripherals.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 0570cc4ad3..6b86a99b14 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -19,7 +19,7 @@
 #define BCM2835_VC_PERI_BASE 0x7e00
 
 /* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
-#define BCM2835_SDHC_CAPAREG 0x52034b4
+#define BCM2835_SDHC_CAPAREG 0x52134b4
 
 static void bcm2835_peripherals_init(Object *obj)
 {
-- 
2.15.1




[Qemu-devel] [PATCH v8 12/14] sdhci: check Spec v3 capabilities qtest

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 tests/sdhci-test.c | 12 
 tests/Makefile.include |  1 +
 2 files changed, 13 insertions(+)

diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
index aae2cfc1b5..56eefdafd8 100644
--- a/tests/sdhci-test.c
+++ b/tests/sdhci-test.c
@@ -42,10 +42,22 @@ static const struct sdhci_t {
 { "arm","smdkc210",
 {0x1251, 2, 0,  {1, 0x5e80080} } },
 
+/* i.MX 6 */
+{ "arm","sabrelite",
+{0x0219, 3, 0,  {1, 0x057834b4} } },
+
+/* BCM2835 */
+{ "arm","raspi2",
+{0x3f30, 3, 52, {0, 0x052134b4} } },
+
 /* Zynq-7000 */
 { "arm","xilinx-zynq-a9",   /* Datasheet: UG585 (v1.12.1) */
 {0xe010, 2, 0,  {1, 0x69ec0080} } },
 
+/* ZynqMP */
+{ "aarch64", "xlnx-zcu102", /* Datasheet: UG1085 (v1.7) */
+{0xff16, 3, 0,  {1, 0x280737ec6481} } },
+
 };
 
 static struct {
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 756725b0f9..74cae947cb 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -367,6 +367,7 @@ check-qtest-arm-y += tests/boot-serial-test$(EXESUF)
 check-qtest-arm-y += tests/sdhci-test$(EXESUF)
 
 check-qtest-aarch64-y = tests/numa-test$(EXESUF)
+check-qtest-aarch64-y += tests/sdhci-test$(EXESUF)
 
 check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
 
-- 
2.15.1




[Qemu-devel] [PATCH v8 07/14] hw/arm/bcm2835_peripherals: implement SDHCI Spec. v3

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/bcm2835_peripherals.c | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 12e0dd11af..0570cc4ad3 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -254,14 +254,19 @@ static void bcm2835_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(>peri_mr, RNG_OFFSET,
 sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng), 0));
 
-/* Extended Mass Media Controller */
-object_property_set_int(OBJECT(>sdhci), BCM2835_SDHC_CAPAREG, "capareg",
-);
-if (err) {
-error_propagate(errp, err);
-return;
-}
-
+/* Extended Mass Media Controller
+ *
+ * Compatible with:
+ * - SD Host Controller Specification Version 3.0 Draft 1.0
+ * - SDIO Specification Version 3.0
+ * - MMC Specification Version 4.4
+ *
+ * For the exact details please refer to the Arasan documentation:
+ *   SD3.0_Host_AHB_eMMC4.4_Usersguide_ver5.9_jan11_10.pdf   ¯\_(ツ)_/¯
+ */
+object_property_set_uint(OBJECT(>sdhci), 3, "sd-spec-version", );
+object_property_set_uint(OBJECT(>sdhci), BCM2835_SDHC_CAPAREG, 
"capareg",
+ );
 object_property_set_bool(OBJECT(>sdhci), true, "pending-insert-quirk",
  );
 if (err) {
-- 
2.15.1




[Qemu-devel] [PATCH v8 06/14] sdhci: implement CMD/DAT[] fields in the Present State register

2018-01-22 Thread Philippe Mathieu-Daudé
[based on a patch from Alistair Francis 
 from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdhci-internal.h |  2 ++
 include/hw/sd/sd.h |  4 
 hw/sd/core.c   | 34 ++
 hw/sd/sd.c | 16 
 hw/sd/sdhci.c  |  4 
 hw/sd/trace-events |  2 ++
 6 files changed, 62 insertions(+)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index e7cbea297f..514ecd4841 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -82,6 +82,8 @@
 #define SDHC_CARD_PRESENT  0x0001
 #define SDHC_CARD_DETECT   0x0004
 #define SDHC_WRITE_PROTECT 0x0008
+FIELD(SDHC_PRNSTS, DAT_LVL,20, 4);
+FIELD(SDHC_PRNSTS, CMD_LVL,24, 1);
 #define TRANSFERRING_DATA(x)   \
 ((x) & (SDHC_DOING_READ | SDHC_DOING_WRITE))
 
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index f086679493..bf1eb0713c 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -103,6 +103,8 @@ typedef struct {
 uint8_t (*read_data)(SDState *sd);
 bool (*data_ready)(SDState *sd);
 void (*set_voltage)(SDState *sd, uint16_t millivolts);
+uint8_t (*get_dat_lines)(SDState *sd);
+bool (*get_cmd_line)(SDState *sd);
 void (*enable)(SDState *sd, bool enable);
 bool (*get_inserted)(SDState *sd);
 bool (*get_readonly)(SDState *sd);
@@ -150,6 +152,8 @@ void sd_enable(SDState *sd, bool enable);
  * an SDBus rather than directly with SDState)
  */
 void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
+uint8_t sdbus_get_dat_lines(SDBus *sdbus);
+bool sdbus_get_cmd_line(SDBus *sdbus);
 int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
 void sdbus_write_data(SDBus *sd, uint8_t value);
 uint8_t sdbus_read_data(SDBus *sd);
diff --git a/hw/sd/core.c b/hw/sd/core.c
index 6d198ea775..3c6eae6c88 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -41,6 +41,40 @@ static SDState *get_card(SDBus *sdbus)
 return SD_CARD(kid->child);
 }
 
+uint8_t sdbus_get_dat_lines(SDBus *sdbus)
+{
+SDState *slave = get_card(sdbus);
+uint8_t dat_lines = 0b; /* 4 bit bus width */
+
+if (slave) {
+SDCardClass *sc = SD_CARD_GET_CLASS(slave);
+
+if (sc->get_dat_lines) {
+dat_lines = sc->get_dat_lines(slave);
+}
+}
+trace_sdbus_get_dat_lines(sdbus_name(sdbus), dat_lines);
+
+return dat_lines;
+}
+
+bool sdbus_get_cmd_line(SDBus *sdbus)
+{
+SDState *slave = get_card(sdbus);
+bool cmd_line = true;
+
+if (slave) {
+SDCardClass *sc = SD_CARD_GET_CLASS(slave);
+
+if (sc->get_cmd_line) {
+cmd_line = sc->get_cmd_line(slave);
+}
+}
+trace_sdbus_get_cmd_line(sdbus_name(sdbus), cmd_line);
+
+return cmd_line;
+}
+
 void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
 {
 SDState *card = get_card(sdbus);
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 609b2da14f..ab9be561d2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -126,8 +126,20 @@ struct SDState {
 BlockBackend *blk;
 
 bool enable;
+uint8_t dat_lines;
+bool cmd_line;
 };
 
+static uint8_t sd_get_dat_lines(SDState *sd)
+{
+return sd->enable ? sd->dat_lines : 0;
+}
+
+static bool sd_get_cmd_line(SDState *sd)
+{
+return sd->enable ? sd->cmd_line : false;
+}
+
 static void sd_set_voltage(SDState *sd, uint16_t millivolts)
 {
 switch (millivolts) {
@@ -457,6 +469,8 @@ static void sd_reset(DeviceState *dev)
 sd->blk_len = 0x200;
 sd->pwd_len = 0;
 sd->expecting_acmd = false;
+sd->dat_lines = 0xf;
+sd->cmd_line = true;
 sd->multi_blk_cnt = 0;
 }
 
@@ -1938,6 +1952,8 @@ static void sd_class_init(ObjectClass *klass, void *data)
 dc->bus_type = TYPE_SD_BUS;
 
 sc->set_voltage = sd_set_voltage;
+sc->get_dat_lines = sd_get_dat_lines;
+sc->get_cmd_line = sd_get_cmd_line;
 sc->do_command = sd_do_command;
 sc->write_data = sd_write_data;
 sc->read_data = sd_read_data;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index aec6ca4d14..b7fb262750 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1003,6 +1003,10 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, 
unsigned size)
 break;
 case SDHC_PRNSTS:
 ret = s->prnsts;
+ret = FIELD_DP32(ret, SDHC_PRNSTS, DAT_LVL,
+ sdbus_get_dat_lines(>sdbus));
+ret = FIELD_DP32(ret, SDHC_PRNSTS, CMD_LVL,
+ sdbus_get_cmd_line(>sdbus));
 break;
 case SDHC_HOSTCTL:
 ret = s->hostctl1 | (s->pwrcon << 8) | (s->blkgap << 16) |
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 84d2f398b1..0f8536db32 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -5,6 +5,8 @@ sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, 
uint8_t crc) "@%s
 sdbus_read(const char *bus_name, uint8_t value) "@%s value 

[Qemu-devel] [PATCH v8 11/14] hw/arm/xilinx_zynqmp: enable the UHS-I mode

2018-01-22 Thread Philippe Mathieu-Daudé
see the Xilinx datasheet "UG1085" (v1.7)

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/xlnx-zynqmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 33d5fe53d8..bb4265a4ce 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -394,6 +394,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
  */
 object_property_set_uint(sdhci, 3, "sd-spec-version", );
 object_property_set_uint(sdhci, SDHCI_CAPABILITIES, "capareg", );
+object_property_set_uint(sdhci, UHS_I, "uhs", );
 object_property_set_bool(sdhci, true, "realized", );
 if (err) {
 error_propagate(errp, err);
-- 
2.15.1




[Qemu-devel] [PATCH v8 02/14] sdhci: rename the hostctl1 register

2018-01-22 Thread Philippe Mathieu-Daudé
As per the Spec v3.00

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
---
 include/hw/sd/sdhci.h |  2 +-
 hw/sd/sdhci.c | 12 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 96e07de2a2..5af9e0dc5a 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -57,7 +57,7 @@ typedef struct SDHCIState {
 uint16_t cmdreg;   /* Command Register */
 uint32_t rspreg[4];/* Response Registers 0-3 */
 uint32_t prnsts;   /* Present State Register */
-uint8_t  hostctl;  /* Host Control Register */
+uint8_t  hostctl1; /* Host Control Register */
 uint8_t  pwrcon;   /* Power control Register */
 uint8_t  blkgap;   /* Block Gap Control Register */
 uint8_t  wakcon;   /* WakeUp Control Register */
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index c32adc0f24..013c35e585 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -691,7 +691,7 @@ static void get_adma_description(SDHCIState *s, ADMADescr 
*dscr)
 uint32_t adma1 = 0;
 uint64_t adma2 = 0;
 hwaddr entry_addr = (hwaddr)s->admasysaddr;
-switch (SDHC_DMA_TYPE(s->hostctl)) {
+switch (SDHC_DMA_TYPE(s->hostctl1)) {
 case SDHC_CTRL_ADMA2_32:
 dma_memory_read(s->dma_as, entry_addr, (uint8_t *),
 sizeof(adma2));
@@ -880,7 +880,7 @@ static void sdhci_data_transfer(void *opaque)
 SDHCIState *s = (SDHCIState *)opaque;
 
 if (s->trnmod & SDHC_TRNS_DMA) {
-switch (SDHC_DMA_TYPE(s->hostctl)) {
+switch (SDHC_DMA_TYPE(s->hostctl1)) {
 case SDHC_CTRL_SDMA:
 if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
 sdhci_sdma_transfer_single_block(s);
@@ -989,7 +989,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, 
unsigned size)
 ret = s->prnsts;
 break;
 case SDHC_HOSTCTL:
-ret = s->hostctl | (s->pwrcon << 8) | (s->blkgap << 16) |
+ret = s->hostctl1 | (s->pwrcon << 8) | (s->blkgap << 16) |
   (s->wakcon << 24);
 break;
 case SDHC_CLKCON:
@@ -1107,7 +1107,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
unsigned size)
 MASKED_WRITE(s->sdmasysad, mask, value);
 /* Writing to last byte of sdmasysad might trigger transfer */
 if (!(mask & 0xFF00) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt 
&&
-s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
+s->blksize && SDHC_DMA_TYPE(s->hostctl1) == SDHC_CTRL_SDMA) {
 if (s->trnmod & SDHC_TRNS_MULTI) {
 sdhci_sdma_transfer_multi_blocks(s);
 } else {
@@ -1159,7 +1159,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
unsigned size)
 if (!(mask & 0xFF)) {
 sdhci_blkgap_write(s, value >> 16);
 }
-MASKED_WRITE(s->hostctl, mask, value);
+MASKED_WRITE(s->hostctl1, mask, value);
 MASKED_WRITE(s->pwrcon, mask >> 8, value >> 8);
 MASKED_WRITE(s->wakcon, mask >> 24, value >> 24);
 if (!(s->prnsts & SDHC_CARD_PRESENT) || ((s->pwrcon >> 1) & 0x7) < 5 ||
@@ -1378,7 +1378,7 @@ const VMStateDescription sdhci_vmstate = {
 VMSTATE_UINT16(cmdreg, SDHCIState),
 VMSTATE_UINT32_ARRAY(rspreg, SDHCIState, 4),
 VMSTATE_UINT32(prnsts, SDHCIState),
-VMSTATE_UINT8(hostctl, SDHCIState),
+VMSTATE_UINT8(hostctl1, SDHCIState),
 VMSTATE_UINT8(pwrcon, SDHCIState),
 VMSTATE_UINT8(blkgap, SDHCIState),
 VMSTATE_UINT8(wakcon, SDHCIState),
-- 
2.15.1




[Qemu-devel] [PATCH v8 05/14] sdhci: implement UHS-I voltage switch

2018-01-22 Thread Philippe Mathieu-Daudé
[based on a patch from Alistair Francis 
 from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h| 16 
 include/hw/sd/sdhci.h |  1 +
 hw/sd/core.c  | 13 +
 hw/sd/sd.c| 13 +
 hw/sd/sdhci.c | 12 +++-
 hw/sd/trace-events|  1 +
 6 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index 96caefe373..f086679493 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -55,6 +55,20 @@
 #define AKE_SEQ_ERROR  (1 << 3)
 #define OCR_CCS_BITN30
 
+typedef enum {
+SD_VOLTAGE_0_4V = 400,  /* currently not supported */
+SD_VOLTAGE_1_8V = 1800,
+SD_VOLTAGE_3_0V = 3000,
+SD_VOLTAGE_3_3V = 3300,
+} sd_voltage_mv_t;
+
+typedef enum  {
+UHS_NOT_SUPPORTED   = 0,
+UHS_I   = 1,
+UHS_II  = 2,/* currently not supported */
+UHS_III = 3,/* currently not supported */
+} sd_uhs_mode_t;
+
 typedef enum {
 sd_none = -1,
 sd_bc = 0, /* broadcast -- no response */
@@ -88,6 +102,7 @@ typedef struct {
 void (*write_data)(SDState *sd, uint8_t value);
 uint8_t (*read_data)(SDState *sd);
 bool (*data_ready)(SDState *sd);
+void (*set_voltage)(SDState *sd, uint16_t millivolts);
 void (*enable)(SDState *sd, bool enable);
 bool (*get_inserted)(SDState *sd);
 bool (*get_readonly)(SDState *sd);
@@ -134,6 +149,7 @@ void sd_enable(SDState *sd, bool enable);
 /* Functions to be used by qdevified callers (working via
  * an SDBus rather than directly with SDState)
  */
+void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
 int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
 void sdbus_write_data(SDBus *sd, uint8_t value);
 uint8_t sdbus_read_data(SDBus *sd);
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 0fff941a98..06e3784e54 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -93,6 +93,7 @@ typedef struct SDHCIState {
 /* Configurable properties */
 bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
 uint8_t sd_spec_version;
+uint8_t uhs_mode;
 } SDHCIState;
 
 #define TYPE_PCI_SDHCI "sdhci-pci"
diff --git a/hw/sd/core.c b/hw/sd/core.c
index 498284f109..6d198ea775 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -41,6 +41,19 @@ static SDState *get_card(SDBus *sdbus)
 return SD_CARD(kid->child);
 }
 
+void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
+{
+SDState *card = get_card(sdbus);
+
+trace_sdbus_set_voltage(sdbus_name(sdbus), millivolts);
+if (card) {
+SDCardClass *sc = SD_CARD_GET_CLASS(card);
+
+assert(sc->set_voltage);
+sc->set_voltage(card, millivolts);
+}
+}
+
 int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
 {
 SDState *card = get_card(sdbus);
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 35347a5bbc..609b2da14f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -128,6 +128,18 @@ struct SDState {
 bool enable;
 };
 
+static void sd_set_voltage(SDState *sd, uint16_t millivolts)
+{
+switch (millivolts) {
+case 3001 ... 3600: /* SD_VOLTAGE_3_3V */
+case 2001 ... 3000: /* SD_VOLTAGE_3_0V */
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "SD card voltage not supported: %.3fV",
+  millivolts / 1000.f);
+}
+}
+
 static void sd_set_mode(SDState *sd)
 {
 switch (sd->state) {
@@ -1925,6 +1937,7 @@ static void sd_class_init(ObjectClass *klass, void *data)
 dc->reset = sd_reset;
 dc->bus_type = TYPE_SD_BUS;
 
+sc->set_voltage = sd_set_voltage;
 sc->do_command = sd_do_command;
 sc->write_data = sd_write_data;
 sc->read_data = sd_read_data;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index b7e69fbc22..aec6ca4d14 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1255,7 +1255,16 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
unsigned size)
 sdhci_update_irq(s);
 break;
 case SDHC_ACMD12ERRSTS:
-MASKED_WRITE(s->acmd12errsts, mask, value);
+MASKED_WRITE(s->acmd12errsts, mask, value & UINT16_MAX);
+if (s->uhs_mode >= UHS_I) {
+MASKED_WRITE(s->hostctl2, mask >> 16, value >> 16);
+
+if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, V18_ENA)) {
+sdbus_set_voltage(>sdbus, SD_VOLTAGE_1_8V);
+} else {
+sdbus_set_voltage(>sdbus, SD_VOLTAGE_3_3V);
+}
+}
 break;
 
 case SDHC_CAPAB:
@@ -1310,6 +1319,7 @@ static void sdhci_init_readonly_registers(SDHCIState *s, 
Error **errp)
 
 #define DEFINE_SDHCI_COMMON_PROPERTIES(_state) \
 DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \
+DEFINE_PROP_UINT8("uhs", _state, uhs_mode, UHS_NOT_SUPPORTED), \
 \
 /* Capabilities registers provide 

[Qemu-devel] [PATCH v8 04/14] sdbus: add trace events

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/core.c   | 14 --
 hw/sd/trace-events |  5 +
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/hw/sd/core.c b/hw/sd/core.c
index 295dc44ab7..498284f109 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -23,6 +23,12 @@
 #include "hw/qdev-core.h"
 #include "sysemu/block-backend.h"
 #include "hw/sd/sd.h"
+#include "trace.h"
+
+static inline const char *sdbus_name(SDBus *sdbus)
+{
+return sdbus->qbus.name;
+}
 
 static SDState *get_card(SDBus *sdbus)
 {
@@ -39,6 +45,7 @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t 
*response)
 {
 SDState *card = get_card(sdbus);
 
+trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg, req->crc);
 if (card) {
 SDCardClass *sc = SD_CARD_GET_CLASS(card);
 
@@ -52,6 +59,7 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
 {
 SDState *card = get_card(sdbus);
 
+trace_sdbus_write(sdbus_name(sdbus), value);
 if (card) {
 SDCardClass *sc = SD_CARD_GET_CLASS(card);
 
@@ -62,14 +70,16 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
 uint8_t sdbus_read_data(SDBus *sdbus)
 {
 SDState *card = get_card(sdbus);
+uint8_t value = 0;
 
 if (card) {
 SDCardClass *sc = SD_CARD_GET_CLASS(card);
 
-return sc->read_data(card);
+value = sc->read_data(card);
 }
+trace_sdbus_read(sdbus_name(sdbus), value);
 
-return 0;
+return value;
 }
 
 bool sdbus_data_ready(SDBus *sdbus)
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 78d8707669..ea2746c8b7 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -1,5 +1,10 @@
 # See docs/devel/tracing.txt for syntax documentation.
 
+# hw/sd/core.c
+sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) 
"@%s CMD%02d arg 0x%08x crc 0x%02x"
+sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
+sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
+
 # hw/sd/sdhci.c
 sdhci_set_inserted(const char *level) "card state changed: %s"
 sdhci_send_command(uint8_t cmd, uint32_t arg) "CMD%02u ARG[0x%08x]"
-- 
2.15.1




[Qemu-devel] [PATCH v8 10/14] hw/arm/xilinx_zynqmp: fix the capabilities/spec version to match the datasheet

2018-01-22 Thread Philippe Mathieu-Daudé
checking Xilinx datasheet "UG1085" (v1.7)

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/xlnx-zynqmp.c | 29 ++---
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 325642058b..33d5fe53d8 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -50,6 +50,8 @@
 #define DPDMA_ADDR  0xfd4c
 #define DPDMA_IRQ   116
 
+#define SDHCI_CAPABILITIES  0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
+
 static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E,
 };
@@ -381,22 +383,27 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(>sata), 0, gic_spi[SATA_INTR]);
 
 for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
-char *bus_name;
-
-object_property_set_bool(OBJECT(>sdhci[i]), true,
- "realized", );
+char *bus_name = g_strdup_printf("sd-bus%d", i);
+SysBusDevice *sbd = SYS_BUS_DEVICE(>sdhci[i]);
+Object *sdhci = OBJECT(>sdhci[i]);
+
+/* Compatible with:
+ * - SD Host Controller Specification Version 3.00
+ * - SDIO Specification Version 3.0
+ * - eMMC Specification Version 4.51
+ */
+object_property_set_uint(sdhci, 3, "sd-spec-version", );
+object_property_set_uint(sdhci, SDHCI_CAPABILITIES, "capareg", );
+object_property_set_bool(sdhci, true, "realized", );
 if (err) {
 error_propagate(errp, err);
 return;
 }
-sysbus_mmio_map(SYS_BUS_DEVICE(>sdhci[i]), 0,
-sdhci_addr[i]);
-sysbus_connect_irq(SYS_BUS_DEVICE(>sdhci[i]), 0,
-   gic_spi[sdhci_intr[i]]);
+sysbus_mmio_map(sbd, 0, sdhci_addr[i]);
+sysbus_connect_irq(sbd, 0, gic_spi[sdhci_intr[i]]);
+
 /* Alias controller SD bus to the SoC itself */
-bus_name = g_strdup_printf("sd-bus%d", i);
-object_property_add_alias(OBJECT(s), bus_name,
-  OBJECT(>sdhci[i]), "sd-bus",
+object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus",
   _abort);
 g_free(bus_name);
 }
-- 
2.15.1




[Qemu-devel] [PATCH v8 00/14] SDHCI: add tuning sequence for UHS-I cards (part 3)

2018-01-22 Thread Philippe Mathieu-Daudé
This series add minimum features required by Spec v3 to support UHS-I cards.

Since v7:
- we keep the 'capareg' property, this simplify a lot the series
- the ZynqMP uses the datasheet CAPAREG
- reset R-b/A-b

Note: https://www.google.com.ar/search?q=sdhci_imx0+caps show various console
  output with i.MX6 capareg value of 0x0377c800 

Since v6:
- rebased on upstream
- included spec v3 qtest back

Since v5:
- addressed Alistair reviews
- dropped "abstract generic-sdhci"
- dropped Linux Device Tree names
- split qtests in another series
- change the bcm2835 minimum blocksize to 1KB (Andrew Baumann)
- added Alistair R-b
- based on Alistair work:
  - add SD tunning sequence via Host Control 2 to use UHS-I cards
  - add CMD/DAT[] fields in the Present State (used in next series
to switch card voltage)

based on Alistair work:
- add SD tunning sequence via Host Control 2 to use UHS-I cards
- add CMD/DAT[] fields in the Present State (used in next series
  to switch card voltage)

Since v4 ("SDHCI: add qtests and fix few issues"):
- spec_version default to v2 (current behaviour)
- addressed Alistair review (no v1, tell user about valid version)

Since v3:
- no change, but split back in 2 series, 1st part is "SDHCI: housekeeping v5",

Since v2:
- more detailed 'capabilities', all boards converted to use these properties
- since all qtests pass, removed the previous 'capareg' property
- added Stefan/Alistair R-b
- corrected 'access' LED behavior (Alistair's review)
- more uses of the registerfields API
- remove some dead code
- cosmetix:
  - added more comments
  - renamed a pair of registers
  - reordered few struct members

Since v1:
- addressed Alistair Francis review comments, added some R-b
- only move register defines to "sd-internal.h"
- fixed deposit64() arguments
- dropped unuseful s->fifo_buffer = NULL
- use a qemu_irq for the LED, restrict the logging to ON/OFF
- fixed a trace format string error
- included Andrey Smirnov ACMD12ERRSTS write patch
- dropped few unuseful patches, and separate the Python polemical ones for later

>From the "SDHCI housekeeping" series:
- 1: we restrict part of "sd/sd.h" into local "sd-internal.h",
- 2,3: we somehow beautiful the code, no logical changes,
- 4-7: we refactor the common sysbus/pci qdev code,
- 8-10: we add plenty of trace events which will result useful later,
- 11: we finally expose a "dma-memory" property.
>From the "SDHCI: add a qtest and fix few issues" series:
- 12,13: fix registers
- 14,15: boards can specify which SDHCI Spec to use (v2 and v3 so far)
- 15-20: HCI qtest

Regards,

Phil.

$ git backport-diff
001/14:[down] 'sdhci: add support for v3 capabilities'
002/14:[] [--] 'sdhci: rename the hostctl1 register'
003/14:[] [--] 'sdhci: implement the Host Control 2 register (tuning 
sequence)'
004/14:[] [--] 'sdbus: add trace events'
005/14:[0006] [FC] 'sdhci: implement UHS-I voltage switch'
006/14:[] [--] 'sdhci: implement CMD/DAT[] fields in the Present State 
register'
007/14:[0015] [FC] 'hw/arm/bcm2835_peripherals: implement SDHCI Spec. v3'
008/14:[0003] [FC] 'hw/arm/bcm2835_peripherals: change maximum block size to 
1kB'
009/14:[0014] [FC] 'hw/arm/fsl-imx6: implement SDHCI Spec. v3'
010/14:[0017] [FC] 'hw/arm/xilinx_zynqmp: fix the capabilities/spec version to 
match the datasheet'
011/14:[down] 'hw/arm/xilinx_zynqmp: enable the UHS-I mode'
012/14:[0010] [FC] 'sdhci: check Spec v3 capabilities qtest'
013/14:[] [--] 'sdhci: add a check_capab_v3() qtest'
014/14:[0019] [FC] 'sdhci: add Spec v4.2 register definitions'

Based-on: 20180123020820.1288-17-f4...@amsat.org

Philippe Mathieu-Daudé (14):
  sdhci: add support for v3 capabilities
  sdhci: rename the hostctl1 register
  sdhci: implement the Host Control 2 register (tuning sequence)
  sdbus: add trace events
  sdhci: implement UHS-I voltage switch
  sdhci: implement CMD/DAT[] fields in the Present State register
  hw/arm/bcm2835_peripherals: implement SDHCI Spec v3
  hw/arm/bcm2835_peripherals: change maximum block size to 1kB
  hw/arm/fsl-imx6: implement SDHCI Spec. v3
  hw/arm/xilinx_zynqmp: fix the capabilities/spec version to match the datasheet
  hw/arm/xilinx_zynqmp: enable the UHS-I mode
  sdhci: check Spec v3 capabilities qtest
  sdhci: add a check_capab_v3() qtest
  sdhci: add Spec v4.2 register definitions

 include/hw/sd/sd.h   |  20 
 include/hw/sd/sdhci.h|   4 +-
 hw/sd/sdhci-internal.h   |  34 
 hw/arm/bcm2835_peripherals.c |  23 +
 hw/arm/fsl-imx6.c|   7 +++
 hw/arm/xlnx-zynqmp.c |  30 +++
 hw/sd/core.c |  61 +-
 hw/sd/sd.c   |  29 +++
 hw/sd/sdhci.c| 120 ++-
 hw/sd/trace-events   |   8 +++
 tests/sdhci-test.c   |  29 +++
 tests/Makefile.include   |   1 +
 12 files changed, 330 insertions(+), 36 deletions(-)

-- 
2.15.1




[Qemu-devel] [PATCH v8 03/14] sdhci: implement the Host Control 2 register (tuning sequence)

2018-01-22 Thread Philippe Mathieu-Daudé
[based on a patch from Alistair Francis 
 from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdhci-internal.h | 10 ++
 include/hw/sd/sdhci.h  |  1 +
 hw/sd/sdhci.c  | 22 +++---
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 9111f6856a..e7cbea297f 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -184,6 +184,16 @@ FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
 FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,  2, 1);
 FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,4, 1);
 
+/* Host Control Register 2 (since v3) */
+#define SDHC_HOSTCTL2  0x3E
+FIELD(SDHC_HOSTCTL2, UHS_MODE_SEL, 0, 3);
+FIELD(SDHC_HOSTCTL2, V18_ENA,  3, 1); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, DRIVER_STRENGTH,  4, 2); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, EXECUTE_TUNING,   6, 1); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, SAMPLING_CLKSEL,  7, 1); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, ASYNC_INT,   14, 1);
+FIELD(SDHC_HOSTCTL2, PRESET_ENA,  15, 1);
+
 /* HWInit Capabilities Register 0x05E80080 */
 #define SDHC_CAPAB 0x40
 FIELD(SDHC_CAPAB, TOCLKFREQ,   0, 6);
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 5af9e0dc5a..0fff941a98 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -71,6 +71,7 @@ typedef struct SDHCIState {
 uint16_t norintsigen;  /* Normal Interrupt Signal Enable Register */
 uint16_t errintsigen;  /* Error Interrupt Signal Enable Register */
 uint16_t acmd12errsts; /* Auto CMD12 error status register */
+uint16_t hostctl2; /* Host Control 2 */
 uint64_t admasysaddr;  /* ADMA System Address Register */
 
 /* Read-only registers */
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 013c35e585..b7e69fbc22 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -408,14 +408,29 @@ static void sdhci_end_transfer(SDHCIState *s)
 static void sdhci_read_block_from_card(SDHCIState *s)
 {
 int index = 0;
+uint8_t data;
+const uint16_t blk_size = s->blksize & BLOCK_SIZE_MASK;
 
 if ((s->trnmod & SDHC_TRNS_MULTI) &&
 (s->trnmod & SDHC_TRNS_BLK_CNT_EN) && (s->blkcnt == 0)) {
 return;
 }
 
-for (index = 0; index < (s->blksize & BLOCK_SIZE_MASK); index++) {
-s->fifo_buffer[index] = sdbus_read_data(>sdbus);
+for (index = 0; index < blk_size; index++) {
+data = sdbus_read_data(>sdbus);
+if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
+/* Device is not in tunning */
+s->fifo_buffer[index] = data;
+}
+}
+
+if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
+/* Device is in tunning */
+s->hostctl2 &= ~R_SDHC_HOSTCTL2_EXECUTE_TUNING_MASK;
+s->hostctl2 |= R_SDHC_HOSTCTL2_SAMPLING_CLKSEL_MASK;
+s->prnsts &= ~(SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ |
+   SDHC_DATA_INHIBIT);
+goto read_done;
 }
 
 /* New data now available for READ through Buffer Port Register */
@@ -440,6 +455,7 @@ static void sdhci_read_block_from_card(SDHCIState *s)
 }
 }
 
+read_done:
 sdhci_update_irq(s);
 }
 
@@ -1005,7 +1021,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, 
unsigned size)
 ret = s->norintsigen | (s->errintsigen << 16);
 break;
 case SDHC_ACMD12ERRSTS:
-ret = s->acmd12errsts;
+ret = s->acmd12errsts | (s->hostctl2 << 16);
 break;
 case SDHC_CAPAB:
 ret = (uint32_t)s->capareg;
-- 
2.15.1




[Qemu-devel] [PATCH v8 01/14] sdhci: add support for v3 capabilities

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdhci-internal.h | 13 
 hw/sd/sdhci.c  | 54 --
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 4ed9727ec3..9111f6856a 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -43,6 +43,7 @@
 #define SDHC_TRNS_DMA  0x0001
 #define SDHC_TRNS_BLK_CNT_EN   0x0002
 #define SDHC_TRNS_ACMD12   0x0004
+#define SDHC_TRNS_ACMD23   0x0008 /* since v3 */
 #define SDHC_TRNS_READ 0x0010
 #define SDHC_TRNS_MULTI0x0020
 #define SDHC_TRNMOD_MASK   0x0037
@@ -189,6 +190,7 @@ FIELD(SDHC_CAPAB, TOCLKFREQ,   0, 6);
 FIELD(SDHC_CAPAB, TOUNIT,  7, 1);
 FIELD(SDHC_CAPAB, BASECLKFREQ, 8, 8);
 FIELD(SDHC_CAPAB, MAXBLOCKLENGTH, 16, 2);
+FIELD(SDHC_CAPAB, EMBEDDED_8BIT,  18, 1); /* since v3 */
 FIELD(SDHC_CAPAB, ADMA2,  19, 1); /* since v2 */
 FIELD(SDHC_CAPAB, ADMA1,  20, 1); /* v1 only? */
 FIELD(SDHC_CAPAB, HIGHSPEED,  21, 1);
@@ -198,6 +200,17 @@ FIELD(SDHC_CAPAB, V33,24, 1);
 FIELD(SDHC_CAPAB, V30,25, 1);
 FIELD(SDHC_CAPAB, V18,26, 1);
 FIELD(SDHC_CAPAB, BUS64BIT,   28, 1); /* since v2 */
+FIELD(SDHC_CAPAB, ASYNC_INT,  29, 1); /* since v3 */
+FIELD(SDHC_CAPAB, SLOT_TYPE,  30, 2); /* since v3 */
+FIELD(SDHC_CAPAB, BUS_SPEED,  32, 3); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER_STRENGTH,36, 3); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER_TYPE_A,  36, 1); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER_TYPE_C,  37, 1); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER_TYPE_D,  38, 1); /* since v3 */
+FIELD(SDHC_CAPAB, TIMER_RETUNING, 40, 4); /* since v3 */
+FIELD(SDHC_CAPAB, SDR50_TUNING,   45, 1); /* since v3 */
+FIELD(SDHC_CAPAB, RETUNING_MODE,  46, 2); /* since v3 */
+FIELD(SDHC_CAPAB, CLOCK_MULT, 48, 8); /* since v3 */
 
 /* HWInit Maximum Current Capabilities Register 0x0 */
 #define SDHC_MAXCURR   0x48
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index bc3a4f6e16..c32adc0f24 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -70,6 +70,9 @@ static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
 static bool sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
  uint8_t freq, Error **errp)
 {
+if (s->sd_spec_version >= 3) {
+return false;
+}
 switch (freq) {
 case 0:
 case 10 ... 63:
@@ -89,6 +92,50 @@ static void sdhci_check_capareg(SDHCIState *s, Error **errp)
 bool y;
 
 switch (s->sd_spec_version) {
+case 3:
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, ASYNC_INT);
+trace_sdhci_capareg("async interrupt", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, ASYNC_INT, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, SLOT_TYPE);
+if (val) {
+error_setg(errp, "slot-type not supported");
+return;
+}
+trace_sdhci_capareg("slot type", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, SLOT_TYPE, 0);
+
+if (val != 0b10) {
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, EMBEDDED_8BIT);
+trace_sdhci_capareg("8-bit bus", val);
+}
+msk = FIELD_DP64(msk, SDHC_CAPAB, EMBEDDED_8BIT, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, BUS_SPEED);
+trace_sdhci_capareg("bus speed mask", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, BUS_SPEED, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, DRIVER_STRENGTH);
+trace_sdhci_capareg("driver strength mask", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, DRIVER_STRENGTH, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, TIMER_RETUNING);
+trace_sdhci_capareg("timer re-tuning", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, TIMER_RETUNING, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, SDR50_TUNING);
+trace_sdhci_capareg("use SDR50 tuning", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, SDR50_TUNING, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, RETUNING_MODE);
+trace_sdhci_capareg("re-tuning mode", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, RETUNING_MODE, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, CLOCK_MULT);
+trace_sdhci_capareg("clock multiplier", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, CLOCK_MULT, 0);
+
+/* fallback */
 case 2: /* default version */
 val = FIELD_EX64(s->capareg, SDHC_CAPAB, ADMA2);
 trace_sdhci_capareg("ADMA2", val);
@@ -1227,8 +1274,11 @@ static void sdhci_init_readonly_registers(SDHCIState *s, 
Error **errp)
 {
 Error *local_err = NULL;
 
-if (s->sd_spec_version != 2) {
-error_setg(errp, "Only Spec v2 is supported");
+switch 

Re: [Qemu-devel] [PATCH] raw: Disable probing if image format is given by driver-specific options

2018-01-22 Thread Lin Ma


On 01/23/2018 12:45 AM, Max Reitz wrote:

On 2018-01-22 08:21, Lin Ma wrote:

If the user specifies image format through driver-specific options, The
format probing should be prohibited and the warning message should not
be printed.

e.g.:
$ qemu-system-x86_64 ... -drive file.file.filename=disk0.raw,file.driver=raw ...
WARNING: Image format was not specified for 'disk0.raw' and probing guessed raw.
  Automatically detecting the format is dangerous for raw images, ...

Signed-off-by: Lin Ma 
---
  blockdev.c | 2 ++
  1 file changed, 2 insertions(+)

But what has been proped is the driver for the root BDS, so the warning
is actually correct.

(That command line is creating a chain of three BDS:
raw (probed) -> raw (explicitly specified) -> file (default protocol))

Max


OK, Thanks
Lin



[Qemu-devel] virtio block device is not working

2018-01-22 Thread joserz
Hello people!

I'm not able to boot any guest that sets a virtio block device like:
(branch master)

[PPC64]
qemu-system-ppc64 -cpu POWER8 -nographic -vga none -m 4G -M 
pseries,accel=kvm,kvm-type=PR -drive file=disk.qcow2,if=virtio
QEMU Starting
 Build Date = Dec 18 2017 13:08:00
 FW Version = git-fa981320a1e0968d
 Press "s" to enter Open Firmware.

Populating /vdevice methods
Populating /vdevice/vty@7100
Populating /vdevice/nvram@7101
Populating /vdevice/v-scsi@7102
   SCSI: Looking for devices
  8200 CD-ROM   : "QEMU QEMU CD-ROM  2.5+"
Populating /pci@8002000
 00  (D) : 1af4 1000virtio [ net ]
Aborted

[x86]

qemu-system-x86_64 -m 4G -enable-kvm -drive file=util.qcow2,if=virtio
Running QEMU with GTK 2.x is deprecated, and will be removed
in a future release. Please switch to GTK 3.x instead
[1]5282 abort

[Cause]

The commit 4fe6d78b2e introduces the

...
kvm_mem_ioeventfd_del(...) {
...
r = kvm_set_ioeventfd_mmio(fd, ...
if (r < 0) {
abort();
}

+if (e->cleanup) {
+e->cleanup(e);
+}
}

For some reason, not yet clear to me, cleanup() calls the same
kvm_mem_ioeventfd_del again and again until kvm_set_ioeventfd_mmio
returns < 0 and abort().

I was going to send a patch to revert that 'if ()' but I think it could
cause a regression. What do you guys think?

Thanks,

Jose Ricardo Ziviani




[Qemu-devel] [PATCH v9 12/16] sdhci: Fix 64-bit ADMA2

2018-01-22 Thread Philippe Mathieu-Daudé
From: Sai Pavan Boddu 

The 64-bit ADMA address is not converted to the cpu endianes correctly.
This patch fixes the issue and uses a valid mask for the attribute data.

Signed-off-by: Sai Pavan Boddu 
[AF: Re-write commit message]
Reviewed-by: Alistair Francis 
---
 hw/sd/sdhci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 9f9d6835c0..a6bba1939f 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -667,8 +667,8 @@ static void get_adma_description(SDHCIState *s, ADMADescr 
*dscr)
 dscr->length = le16_to_cpu(dscr->length);
 dma_memory_read(s->dma_as, entry_addr + 4,
 (uint8_t *)(>addr), 8);
-dscr->attr = le64_to_cpu(dscr->attr);
-dscr->attr &= 0xfff8;
+dscr->addr = le64_to_cpu(dscr->addr);
+dscr->attr &= (uint8_t) ~0xC0;
 dscr->incr = 12;
 break;
 }
-- 
2.15.1




[Qemu-devel] [PATCH v9 15/16] hw/arm/exynos4210: add a comment about a very similar SDHCI (Spec. v2)

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/exynos4210.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index d89322c7ea..06f9d1ffa4 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -377,6 +377,18 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
 BlockBackend *blk;
 DriveInfo *di;
 
+/* Compatible with:
+ * - SD Host Controller Specification Version 2.0
+ * - SDIO Specification Version 2.0
+ * - MMC Specification Version 4.3
+ * - SDMA
+ * - ADMA2
+ *
+ * As this part of the Exynos4210 is not publically available,
+ * we used the "HS-MMC Controller S3C2416X RISC Microprocessor"
+ * public datasheet which is very similar (implementing
+ * MMC Specification Version 4.0 being the only difference noted)
+ */
 dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
 qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
 qdev_init_nofail(dev);
-- 
2.15.1




[Qemu-devel] [PATCH v9 07/16] sdhci: add a 'spec_version property' (default to v2)

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
---
 hw/sd/sdhci-internal.h |  4 ++--
 include/hw/sd/sdhci.h  |  2 ++
 hw/sd/sdhci.c  | 27 +++
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index fc807f08f3..b7751c815f 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -210,9 +210,9 @@
 /* Slot interrupt status */
 #define SDHC_SLOT_INT_STATUS0xFC
 
-/* HWInit Host Controller Version Register 0x0401 */
+/* HWInit Host Controller Version Register */
 #define SDHC_HCVER  0xFE
-#define SD_HOST_SPECv2_VERS 0x2401
+#define SDHC_HCVER_VENDOR   0x24
 
 #define SDHC_REGISTERS_MAP_SIZE 0x100
 #define SDHC_INSERTION_DELAY(NANOSECONDS_PER_SECOND)
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index cb37182536..96e07de2a2 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -76,6 +76,7 @@ typedef struct SDHCIState {
 /* Read-only registers */
 uint64_t capareg;  /* Capabilities Register */
 uint64_t maxcurr;  /* Maximum Current Capabilities Register */
+uint16_t version;  /* Host Controller Version Register */
 
 uint8_t  *fifo_buffer; /* SD host i/o FIFO buffer */
 uint32_t buf_maxsz;
@@ -90,6 +91,7 @@ typedef struct SDHCIState {
 
 /* Configurable properties */
 bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
+uint8_t sd_spec_version;
 } SDHCIState;
 
 #define TYPE_PCI_SDHCI "sdhci-pci"
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 8c9c0fbc2a..1331062306 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -174,7 +174,8 @@ static void sdhci_reset(SDHCIState *s)
 
 timer_del(s->insert_timer);
 timer_del(s->transfer_timer);
-/* Set all registers to 0. Capabilities registers are not cleared
+
+/* Set all registers to 0. Capabilities/Version registers are not cleared
  * and assumed to always preserve their value, given to them during
  * initialization */
 memset(>sdmasysad, 0, (uintptr_t)>capareg - 
(uintptr_t)>sdmasysad);
@@ -918,7 +919,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, 
unsigned size)
 ret = (uint32_t)(s->admasysaddr >> 32);
 break;
 case SDHC_SLOT_INT_STATUS:
-ret = (SD_HOST_SPECv2_VERS << 16) | sdhci_slotint(s);
+ret = (s->version << 16) | sdhci_slotint(s);
 break;
 default:
 qemu_log_mask(LOG_UNIMP, "SDHC rd_%ub @0x%02" HWADDR_PRIx " "
@@ -1174,11 +1175,22 @@ static inline unsigned int sdhci_get_fifolen(SDHCIState 
*s)
 }
 }
 
+static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
+{
+if (s->sd_spec_version != 2) {
+error_setg(errp, "Only Spec v2 is supported");
+return;
+}
+s->version = (SDHC_HCVER_VENDOR << 8) | (s->sd_spec_version - 1);
+}
+
 /* --- qdev common --- */
 
 #define DEFINE_SDHCI_COMMON_PROPERTIES(_state) \
-/* Capabilities registers provide information on supported features
- * of this specific host controller implementation */ \
+DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \
+\
+/* Capabilities registers provide information on supported
+ * features of this specific host controller implementation */ \
 DEFINE_PROP_UINT64("capareg", _state, capareg, SDHC_CAPAB_REG_DEFAULT), \
 DEFINE_PROP_UINT64("maxcurr", _state, maxcurr, 0)
 
@@ -1204,6 +1216,13 @@ static void sdhci_uninitfn(SDHCIState *s)
 
 static void sdhci_common_realize(SDHCIState *s, Error **errp)
 {
+Error *local_err = NULL;
+
+sdhci_init_readonly_registers(s, _err);
+if (local_err) {
+error_propagate(errp, local_err);
+return;
+}
 s->buf_maxsz = sdhci_get_fifolen(s);
 s->fifo_buffer = g_malloc0(s->buf_maxsz);
 
-- 
2.15.1




[Qemu-devel] [PATCH v9 09/16] sdhci: simplify sdhci_get_fifolen()

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdhci-internal.h |  4 +++-
 hw/sd/sdhci.c  | 20 +---
 2 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index b7751c815f..577ca9da54 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -24,6 +24,8 @@
 #ifndef SDHCI_INTERNAL_H
 #define SDHCI_INTERNAL_H
 
+#include "hw/registerfields.h"
+
 /* R/W SDMA System Address register 0x0 */
 #define SDHC_SYSAD 0x00
 
@@ -179,7 +181,7 @@
 #define SDHC_CAN_DO_ADMA2  0x0008
 #define SDHC_CAN_DO_ADMA1  0x0010
 #define SDHC_64_BIT_BUS_SUPPORT(1 << 28)
-#define SDHC_CAPAB_BLOCKSIZE(x)(((x) >> 16) & 0x3)
+FIELD(SDHC_CAPAB, MAXBLOCKLENGTH, 16, 2);
 
 /* HWInit Maximum Current Capabilities Register 0x0 */
 #define SDHC_MAXCURR   0x48
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 1c781c4ba5..dce1a49af1 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -59,6 +59,11 @@
  */
 #define SDHC_CAPAB_REG_DEFAULT 0x057834b4
 
+static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
+{
+return 1 << (9 + FIELD_EX32(s->capareg, SDHC_CAPAB, MAXBLOCKLENGTH));
+}
+
 static uint8_t sdhci_slotint(SDHCIState *s)
 {
 return (s->norintsts & s->norintsigen) || (s->errintsts & s->errintsigen) 
||
@@ -1118,21 +1123,6 @@ static const MemoryRegionOps sdhci_mmio_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
-{
-switch (SDHC_CAPAB_BLOCKSIZE(s->capareg)) {
-case 0:
-return 512;
-case 1:
-return 1024;
-case 2:
-return 2048;
-default:
-hw_error("SDHC: unsupported value for maximum block size\n");
-return 0;
-}
-}
-
 static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
 {
 if (s->sd_spec_version != 2) {
-- 
2.15.1




[Qemu-devel] [PATCH v9 14/16] hw/arm/exynos4210: access the 64-bit capareg with qdev_prop_set_uint64()

2018-01-22 Thread Philippe Mathieu-Daudé
We only set a 32-bit value, but this is a good practice in case this
code is used as reference.

(missed in 5efc9016e52)

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/exynos4210.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index e8e1d81e62..d89322c7ea 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -378,7 +378,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
 DriveInfo *di;
 
 dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
-qdev_prop_set_uint32(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
+qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
 qdev_init_nofail(dev);
 
 busdev = SYS_BUS_DEVICE(dev);
-- 
2.15.1




[Qemu-devel] [PATCH v9 03/16] sdhci: add check_capab_readonly() qtest

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Stefan Hajnoczi 
---
 tests/sdhci-test.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
index 517e2ed5a2..4833dd4204 100644
--- a/tests/sdhci-test.c
+++ b/tests/sdhci-test.c
@@ -62,6 +62,17 @@ static uint64_t sdhci_readq(uintptr_t base, uint32_t 
reg_addr)
 }
 }
 
+static void sdhci_writeq(uintptr_t base, uint32_t reg_addr, uint64_t value)
+{
+if (g.dev) {
+qpci_memwrite(g.dev, g.mem_bar, reg_addr, , sizeof(value));
+} else {
+QTestState *qtest = global_qtest;
+
+qtest_writeq(qtest, base + reg_addr, value);
+}
+}
+
 static void check_capab_capareg(uintptr_t addr, uint64_t expected_capab)
 {
 uint64_t capab;
@@ -70,6 +81,20 @@ static void check_capab_capareg(uintptr_t addr, uint64_t 
expected_capab)
 g_assert_cmphex(capab, ==, expected_capab);
 }
 
+static void check_capab_readonly(uintptr_t addr)
+{
+const uint64_t vrand = 0x123456789abcdef;
+uint64_t capab0, capab1;
+
+capab0 = sdhci_readq(addr, SDHC_CAPAB);
+g_assert_cmpuint(capab0, !=, vrand);
+
+sdhci_writeq(addr, SDHC_CAPAB, vrand);
+capab1 = sdhci_readq(addr, SDHC_CAPAB);
+g_assert_cmpuint(capab1, !=, vrand);
+g_assert_cmpuint(capab1, ==, capab0);
+}
+
 static void machine_start(const struct sdhci_t *test)
 {
 if (test->pci.vendor_id) {
@@ -110,6 +135,7 @@ static void test_machine(const void *data)
 machine_start(test);
 
 check_capab_capareg(test->sdhci.addr, test->sdhci.capab.reg);
+check_capab_readonly(test->sdhci.addr);
 
 machine_stop();
 }
-- 
2.15.1




[Qemu-devel] [PATCH v9 08/16] sdhci: use a numeric value for the default CAPAB register

2018-01-22 Thread Philippe Mathieu-Daudé
using many #defines is not portable when scaling to different HCI.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdhci.c | 74 +--
 1 file changed, 16 insertions(+), 58 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 1331062306..1c781c4ba5 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -39,67 +39,25 @@
 #define TYPE_SDHCI_BUS "sdhci-bus"
 #define SDHCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SDHCI_BUS)
 
+#define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
+
 /* Default SD/MMC host controller features information, which will be
  * presented in CAPABILITIES register of generic SD host controller at reset.
- * If not stated otherwise:
- * 0 - not supported, 1 - supported, other - prohibited.
+ *
+ * support:
+ * - 3.3v and 1.8v voltages
+ * - SDMA/ADMA1/ADMA2
+ * - high-speed
+ * max host controller R/W buffers size: 512B
+ * max clock frequency for SDclock: 52 MHz
+ * timeout clock frequency: 52 MHz
+ *
+ * does not support:
+ * - 3.0v voltage
+ * - 64-bit system bus
+ * - suspend/resume
  */
-#define SDHC_CAPAB_64BITBUS   0ul/* 64-bit System Bus Support */
-#define SDHC_CAPAB_18V1ul/* Voltage support 1.8v */
-#define SDHC_CAPAB_30V0ul/* Voltage support 3.0v */
-#define SDHC_CAPAB_33V1ul/* Voltage support 3.3v */
-#define SDHC_CAPAB_SUSPRESUME 0ul/* Suspend/resume support */
-#define SDHC_CAPAB_SDMA   1ul/* SDMA support */
-#define SDHC_CAPAB_HIGHSPEED  1ul/* High speed support */
-#define SDHC_CAPAB_ADMA1  1ul/* ADMA1 support */
-#define SDHC_CAPAB_ADMA2  1ul/* ADMA2 support */
-/* Maximum host controller R/W buffers size
- * Possible values: 512, 1024, 2048 bytes */
-#define SDHC_CAPAB_MAXBLOCKLENGTH 512ul
-/* Maximum clock frequency for SDclock in MHz
- * value in range 10-63 MHz, 0 - not defined */
-#define SDHC_CAPAB_BASECLKFREQ52ul
-#define SDHC_CAPAB_TOUNIT 1ul  /* Timeout clock unit 0 - kHz, 1 - MHz 
*/
-/* Timeout clock frequency 1-63, 0 - not defined */
-#define SDHC_CAPAB_TOCLKFREQ  52ul
-
-/* Now check all parameters and calculate CAPABILITIES REGISTER value */
-#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_18V > 1 || SDHC_CAPAB_30V > 1 || 
\
-SDHC_CAPAB_33V > 1 || SDHC_CAPAB_SUSPRESUME > 1 || SDHC_CAPAB_SDMA > 1 ||  
\
-SDHC_CAPAB_HIGHSPEED > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 
||\
-SDHC_CAPAB_TOUNIT > 1
-#error Capabilities features can have value 0 or 1 only!
-#endif
-
-#if SDHC_CAPAB_MAXBLOCKLENGTH == 512
-#define MAX_BLOCK_LENGTH 0ul
-#elif SDHC_CAPAB_MAXBLOCKLENGTH == 1024
-#define MAX_BLOCK_LENGTH 1ul
-#elif SDHC_CAPAB_MAXBLOCKLENGTH == 2048
-#define MAX_BLOCK_LENGTH 2ul
-#else
-#error Max host controller block size can have value 512, 1024 or 2048 only!
-#endif
-
-#if (SDHC_CAPAB_BASECLKFREQ > 0 && SDHC_CAPAB_BASECLKFREQ < 10) || \
-SDHC_CAPAB_BASECLKFREQ > 63
-#error SDclock frequency can have value in range 0, 10-63 only!
-#endif
-
-#if SDHC_CAPAB_TOCLKFREQ > 63
-#error Timeout clock frequency can have value in range 0-63 only!
-#endif
-
-#define SDHC_CAPAB_REG_DEFAULT \
-   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_18V << 26) | \
-(SDHC_CAPAB_30V << 25) | (SDHC_CAPAB_33V << 24) |  \
-(SDHC_CAPAB_SUSPRESUME << 23) | (SDHC_CAPAB_SDMA << 22) |  \
-(SDHC_CAPAB_HIGHSPEED << 21) | (SDHC_CAPAB_ADMA1 << 20) |  \
-(SDHC_CAPAB_ADMA2 << 19) | (MAX_BLOCK_LENGTH << 16) |  \
-(SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
-(SDHC_CAPAB_TOCLKFREQ))
-
-#define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
+#define SDHC_CAPAB_REG_DEFAULT 0x057834b4
 
 static uint8_t sdhci_slotint(SDHCIState *s)
 {
-- 
2.15.1




[Qemu-devel] [PATCH v9 13/16] sdhci: check Spec v2 capabilities (DMA and 64-bit bus)

2018-01-22 Thread Philippe Mathieu-Daudé
Incorrect value will throw an error.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdhci-internal.h | 14 +++---
 hw/sd/sdhci.c  | 19 +++
 2 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index c5e26bf8f3..4ed9727ec3 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -89,12 +89,12 @@
 FIELD(SDHC_HOSTCTL, LED_CTRL,  0, 1);
 FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
 FIELD(SDHC_HOSTCTL, HIGH_SPEED,2, 1);
-#define SDHC_CTRL_DMA_CHECK_MASK   0x18
+FIELD(SDHC_HOSTCTL, DMA,   3, 2);
 #define SDHC_CTRL_SDMA 0x00
-#define SDHC_CTRL_ADMA1_32 0x08
+#define SDHC_CTRL_ADMA1_32 0x08 /* NOT ALLOWED since v2 */
 #define SDHC_CTRL_ADMA2_32 0x10
-#define SDHC_CTRL_ADMA2_64 0x18
-#define SDHC_DMA_TYPE(x)   ((x) & SDHC_CTRL_DMA_CHECK_MASK)
+#define SDHC_CTRL_ADMA2_64 0x18 /* only v1 & v2 (v3 optional) */
+#define SDHC_DMA_TYPE(x)   ((x) & R_SDHC_HOSTCTL_DMA_MASK)
 
 /* R/W Power Control Register 0x0 */
 #define SDHC_PWRCON0x29
@@ -185,19 +185,19 @@ FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,4, 1);
 
 /* HWInit Capabilities Register 0x05E80080 */
 #define SDHC_CAPAB 0x40
-#define SDHC_CAN_DO_ADMA2  0x0008
-#define SDHC_CAN_DO_ADMA1  0x0010
-#define SDHC_64_BIT_BUS_SUPPORT(1 << 28)
 FIELD(SDHC_CAPAB, TOCLKFREQ,   0, 6);
 FIELD(SDHC_CAPAB, TOUNIT,  7, 1);
 FIELD(SDHC_CAPAB, BASECLKFREQ, 8, 8);
 FIELD(SDHC_CAPAB, MAXBLOCKLENGTH, 16, 2);
+FIELD(SDHC_CAPAB, ADMA2,  19, 1); /* since v2 */
+FIELD(SDHC_CAPAB, ADMA1,  20, 1); /* v1 only? */
 FIELD(SDHC_CAPAB, HIGHSPEED,  21, 1);
 FIELD(SDHC_CAPAB, SDMA,   22, 1);
 FIELD(SDHC_CAPAB, SUSPRESUME, 23, 1);
 FIELD(SDHC_CAPAB, V33,24, 1);
 FIELD(SDHC_CAPAB, V30,25, 1);
 FIELD(SDHC_CAPAB, V18,26, 1);
+FIELD(SDHC_CAPAB, BUS64BIT,   28, 1); /* since v2 */
 
 /* HWInit Maximum Current Capabilities Register 0x0 */
 #define SDHC_MAXCURR   0x48
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index a6bba1939f..bc3a4f6e16 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -90,6 +90,17 @@ static void sdhci_check_capareg(SDHCIState *s, Error **errp)
 
 switch (s->sd_spec_version) {
 case 2: /* default version */
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, ADMA2);
+trace_sdhci_capareg("ADMA2", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, ADMA2, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, ADMA1);
+trace_sdhci_capareg("ADMA1", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, ADMA1, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, BUS64BIT);
+trace_sdhci_capareg("64-bit system bus", val);
+msk = FIELD_DP64(msk, SDHC_CAPAB, BUS64BIT, 0);
 
 /* fallback */
 case 1:
@@ -832,7 +843,7 @@ static void sdhci_data_transfer(void *opaque)
 
 break;
 case SDHC_CTRL_ADMA1_32:
-if (!(s->capareg & SDHC_CAN_DO_ADMA1)) {
+if (!(s->capareg & R_SDHC_CAPAB_ADMA1_MASK)) {
 trace_sdhci_error("ADMA1 not supported");
 break;
 }
@@ -840,7 +851,7 @@ static void sdhci_data_transfer(void *opaque)
 sdhci_do_adma(s);
 break;
 case SDHC_CTRL_ADMA2_32:
-if (!(s->capareg & SDHC_CAN_DO_ADMA2)) {
+if (!(s->capareg & R_SDHC_CAPAB_ADMA2_MASK)) {
 trace_sdhci_error("ADMA2 not supported");
 break;
 }
@@ -848,8 +859,8 @@ static void sdhci_data_transfer(void *opaque)
 sdhci_do_adma(s);
 break;
 case SDHC_CTRL_ADMA2_64:
-if (!(s->capareg & SDHC_CAN_DO_ADMA2) ||
-!(s->capareg & SDHC_64_BIT_BUS_SUPPORT)) {
+if (!(s->capareg & R_SDHC_CAPAB_ADMA2_MASK) ||
+!(s->capareg & R_SDHC_CAPAB_BUS64BIT_MASK)) {
 trace_sdhci_error("64 bit ADMA not supported");
 break;
 }
-- 
2.15.1




[Qemu-devel] [PATCH v9 02/16] sdhci: add qtest to check the SD capabilities register

2018-01-22 Thread Philippe Mathieu-Daudé
The PCI model is tested with the pc/x86_64 machine,
the SysBus model with the smdkc210/arm machine.

Signed-off-by: Philippe Mathieu-Daudé 
---
 tests/sdhci-test.c | 134 +
 tests/Makefile.include |   3 ++
 2 files changed, 137 insertions(+)
 create mode 100644 tests/sdhci-test.c

diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
new file mode 100644
index 00..517e2ed5a2
--- /dev/null
+++ b/tests/sdhci-test.c
@@ -0,0 +1,134 @@
+/*
+ * QTest testcase for SDHCI controllers
+ *
+ * Written by Philippe Mathieu-Daudé 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "hw/registerfields.h"
+#include "libqtest.h"
+#include "libqos/pci-pc.h"
+#include "hw/pci/pci.h"
+
+#define SDHC_CAPAB  0x40
+#define SDHC_HCVER  0xFE
+
+static const struct sdhci_t {
+const char *arch, *machine;
+struct {
+uintptr_t addr;
+uint8_t version;
+uint8_t baseclock;
+struct {
+bool sdma;
+uint64_t reg;
+} capab;
+} sdhci;
+struct {
+uint16_t vendor_id, device_id;
+} pci;
+} models[] = {
+/* PC via PCI */
+{ "x86_64", "pc",
+{-1, 2, 0,  {1, 0x057834b4} },
+.pci = { PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_SDHCI } },
+
+/* Exynos4210 */
+{ "arm","smdkc210",
+{0x1251, 2, 0,  {1, 0x5e80080} } },
+};
+
+static struct {
+QPCIBus *pcibus;
+QPCIDevice *dev;
+QPCIBar mem_bar;
+} g = { };
+
+static uint64_t sdhci_readq(uintptr_t base, uint32_t reg_addr)
+{
+if (g.dev) {
+uint64_t value;
+
+qpci_memread(g.dev, g.mem_bar, reg_addr, , sizeof(value));
+
+return value;
+} else {
+QTestState *qtest = global_qtest;
+
+return qtest_readq(qtest, base + reg_addr);
+}
+}
+
+static void check_capab_capareg(uintptr_t addr, uint64_t expected_capab)
+{
+uint64_t capab;
+
+capab = sdhci_readq(addr, SDHC_CAPAB);
+g_assert_cmphex(capab, ==, expected_capab);
+}
+
+static void machine_start(const struct sdhci_t *test)
+{
+if (test->pci.vendor_id) {
+/* PCI */
+uint16_t vendor_id, device_id;
+uint64_t barsize;
+
+global_qtest = qtest_startf("-machine %s -d unimp -device sdhci-pci",
+test->machine);
+
+g.pcibus = qpci_init_pc(NULL);
+
+/* Find PCI device and verify it's the right one */
+g.dev = qpci_device_find(g.pcibus, QPCI_DEVFN(4, 0));
+g_assert_nonnull(g.dev);
+vendor_id = qpci_config_readw(g.dev, PCI_VENDOR_ID);
+device_id = qpci_config_readw(g.dev, PCI_DEVICE_ID);
+g_assert(vendor_id == test->pci.vendor_id);
+g_assert(device_id == test->pci.device_id);
+g.mem_bar = qpci_iomap(g.dev, 0, );
+qpci_device_enable(g.dev);
+} else {
+/* SysBus */
+global_qtest = qtest_startf("-machine %s -d unimp", test->machine);
+}
+}
+
+static void machine_stop(void)
+{
+g_free(g.dev);
+qtest_quit(global_qtest);
+}
+
+static void test_machine(const void *data)
+{
+const struct sdhci_t *test = data;
+
+machine_start(test);
+
+check_capab_capareg(test->sdhci.addr, test->sdhci.capab.reg);
+
+machine_stop();
+}
+
+int main(int argc, char *argv[])
+{
+const char *arch = qtest_get_arch();
+char *name;
+int i;
+
+g_test_init(, , NULL);
+for (i = 0; i < ARRAY_SIZE(models); i++) {
+if (strcmp(arch, models[i].arch)) {
+continue;
+}
+name = g_strdup_printf("sdhci/%s", models[i].machine);
+qtest_add_data_func(name, [i], test_machine);
+g_free(name);
+}
+
+return g_test_run();
+}
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 8883274ae1..756725b0f9 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -293,6 +293,7 @@ check-qtest-i386-y += tests/migration-test$(EXESUF)
 check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF)
 check-qtest-i386-y += tests/numa-test$(EXESUF)
 check-qtest-x86_64-y += $(check-qtest-i386-y)
+check-qtest-x86_64-y += tests/sdhci-test$(EXESUF)
 gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
 gcov-files-x86_64-y = $(subst 
i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
 
@@ -363,6 +364,7 @@ gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
 check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
 gcov-files-arm-y += hw/timer/arm_mptimer.c
 check-qtest-arm-y += tests/boot-serial-test$(EXESUF)
+check-qtest-arm-y += tests/sdhci-test$(EXESUF)
 
 check-qtest-aarch64-y = tests/numa-test$(EXESUF)
 
@@ -816,6 +818,7 @@ tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o
 tests/test-qapi-util$(EXESUF): 

[Qemu-devel] [PATCH v9 04/16] sdhci: add a check_capab_baseclock() qtest

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Stefan Hajnoczi 
---
 tests/sdhci-test.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
index 4833dd4204..5f036c8a75 100644
--- a/tests/sdhci-test.c
+++ b/tests/sdhci-test.c
@@ -14,6 +14,7 @@
 #include "hw/pci/pci.h"
 
 #define SDHC_CAPAB  0x40
+FIELD(SDHC_CAPAB, BASECLKFREQ,   8, 8); /* since v2 */
 #define SDHC_HCVER  0xFE
 
 static const struct sdhci_t {
@@ -95,6 +96,18 @@ static void check_capab_readonly(uintptr_t addr)
 g_assert_cmpuint(capab1, ==, capab0);
 }
 
+static void check_capab_baseclock(uintptr_t addr, uint8_t expected_freq)
+{
+uint64_t capab, capab_freq;
+
+if (!expected_freq) {
+return;
+}
+capab = sdhci_readq(addr, SDHC_CAPAB);
+capab_freq = FIELD_EX64(capab, SDHC_CAPAB, BASECLKFREQ);
+g_assert_cmpuint(capab_freq, ==, expected_freq);
+}
+
 static void machine_start(const struct sdhci_t *test)
 {
 if (test->pci.vendor_id) {
@@ -136,6 +149,7 @@ static void test_machine(const void *data)
 
 check_capab_capareg(test->sdhci.addr, test->sdhci.capab.reg);
 check_capab_readonly(test->sdhci.addr);
+check_capab_baseclock(test->sdhci.addr, test->sdhci.baseclock);
 
 machine_stop();
 }
-- 
2.15.1




[Qemu-devel] [PATCH v9 16/16] hw/arm/xilinx_zynq: fix the capabilities register to match the datasheet

2018-01-22 Thread Philippe Mathieu-Daudé
checking Xilinx datasheet "UG585" (v1.12.1)

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/xilinx_zynq.c | 53 
 tests/sdhci-test.c   |  5 +
 2 files changed, 34 insertions(+), 24 deletions(-)

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 1836a4ed45..0f76333770 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -61,6 +61,8 @@ static const int dma_irqs[8] = {
 #define SLCR_XILINX_UNLOCK_KEY  0xdf0d
 #define SLCR_XILINX_LOCK_KEY0x767b
 
+#define ZYNQ_SDHCI_CAPABILITIES 0x69ec0080  /* Datasheet: UG585 (v1.12.1) */
+
 #define ARMV7_IMM16(x) (extract32((x),  0, 12) | \
 extract32((x), 12,  4) << 16)
 
@@ -165,10 +167,8 @@ static void zynq_init(MachineState *machine)
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
 MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
-DeviceState *dev, *carddev;
+DeviceState *dev;
 SysBusDevice *busdev;
-DriveInfo *di;
-BlockBackend *blk;
 qemu_irq pic[64];
 int n;
 
@@ -247,27 +247,32 @@ static void zynq_init(MachineState *machine)
 gem_init(_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
 gem_init(_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
 
-dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
-qdev_init_nofail(dev);
-sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE010);
-sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
-
-di = drive_get_next(IF_SD);
-blk = di ? blk_by_legacy_dinfo(di) : NULL;
-carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
-qdev_prop_set_drive(carddev, "drive", blk, _fatal);
-object_property_set_bool(OBJECT(carddev), true, "realized", _fatal);
-
-dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
-qdev_init_nofail(dev);
-sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
-sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
-
-di = drive_get_next(IF_SD);
-blk = di ? blk_by_legacy_dinfo(di) : NULL;
-carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
-qdev_prop_set_drive(carddev, "drive", blk, _fatal);
-object_property_set_bool(OBJECT(carddev), true, "realized", _fatal);
+for (n = 0; n < 2; n++) {
+int hci_irq = n ? 79 : 56;
+hwaddr hci_addr = n ? 0xE0101000 : 0xE010;
+DriveInfo *di;
+BlockBackend *blk;
+DeviceState *carddev;
+
+/* Compatible with:
+ * - SD Host Controller Specification Version 2.0 Part A2
+ * - SDIO Specification Version 2.0
+ * - MMC Specification Version 3.31
+ */
+dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
+qdev_prop_set_uint8(dev, "sd-spec-version", 2);
+qdev_prop_set_uint64(dev, "capareg", ZYNQ_SDHCI_CAPABILITIES);
+qdev_init_nofail(dev);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, hci_addr);
+sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[hci_irq - IRQ_OFFSET]);
+
+di = drive_get_next(IF_SD);
+blk = di ? blk_by_legacy_dinfo(di) : NULL;
+carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
+qdev_prop_set_drive(carddev, "drive", blk, _fatal);
+object_property_set_bool(OBJECT(carddev), true, "realized",
+ _fatal);
+}
 
 dev = qdev_create(NULL, TYPE_ZYNQ_XADC);
 qdev_init_nofail(dev);
diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
index 094e0570e1..aae2cfc1b5 100644
--- a/tests/sdhci-test.c
+++ b/tests/sdhci-test.c
@@ -41,6 +41,11 @@ static const struct sdhci_t {
 /* Exynos4210 */
 { "arm","smdkc210",
 {0x1251, 2, 0,  {1, 0x5e80080} } },
+
+/* Zynq-7000 */
+{ "arm","xilinx-zynq-a9",   /* Datasheet: UG585 (v1.12.1) */
+{0xe010, 2, 0,  {1, 0x69ec0080} } },
+
 };
 
 static struct {
-- 
2.15.1




[Qemu-devel] [PATCH v9 06/16] sdhci: add qtest to check the SD Spec version

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Stefan Hajnoczi 
---
 tests/sdhci-test.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
index f4c43b8120..094e0570e1 100644
--- a/tests/sdhci-test.c
+++ b/tests/sdhci-test.c
@@ -49,6 +49,21 @@ static struct {
 QPCIBar mem_bar;
 } g = { };
 
+static uint32_t sdhci_readl(uintptr_t base, uint32_t reg_addr)
+{
+if (g.dev) {
+uint32_t value;
+
+qpci_memread(g.dev, g.mem_bar, reg_addr, , sizeof(value));
+
+return value;
+} else {
+QTestState *qtest = global_qtest;
+
+return qtest_readl(qtest, base + reg_addr);
+}
+}
+
 static uint64_t sdhci_readq(uintptr_t base, uint32_t reg_addr)
 {
 if (g.dev) {
@@ -75,6 +90,16 @@ static void sdhci_writeq(uintptr_t base, uint32_t reg_addr, 
uint64_t value)
 }
 }
 
+static void check_specs_version(uintptr_t addr, uint8_t version)
+{
+uint32_t v;
+
+v = sdhci_readl(addr, SDHC_HCVER);
+v &= 0xff;
+v += 1;
+g_assert_cmpuint(v, ==, version);
+}
+
 static void check_capab_capareg(uintptr_t addr, uint64_t expected_capab)
 {
 uint64_t capab;
@@ -157,6 +182,7 @@ static void test_machine(const void *data)
 
 machine_start(test);
 
+check_specs_version(test->sdhci.addr, test->sdhci.version);
 check_capab_capareg(test->sdhci.addr, test->sdhci.capab.reg);
 check_capab_readonly(test->sdhci.addr);
 check_capab_sdma(test->sdhci.addr, test->sdhci.capab.sdma);
-- 
2.15.1




[Qemu-devel] [PATCH v9 00/16] SDHCI: clean v1/v2 Specs (part 2)

2018-01-22 Thread Philippe Mathieu-Daudé
Since v8:
- we keep the 'capareg' property, this simplify a lot the series
- the Zynq 7000 uses the datasheet CAPAREG
- reset R-b/A-b

Since v7:
- use error_propagate()

Since v6:
- rebased on upstream to use DEFINE_SDHCI_COMMON_PROPERTIES
- included qtests back
- add PCI qtests
- series was getting big, splitting again; next one is "implement Spec v3"
- following Alistair advice, new properties default to current
  SDHC_CAPAB_REG_DEFAULT (probably 'default' for historical reason, being
  the first capabilities set). This leads to weird properties imho, i.e.
  defaulting 'max-frequency' to 52 MHz, the Exynos SoC has to set this
  property to 0. 
- addressed Alistair reviews
- confirmed the Exynos4210 specs after chatting on IRC with Krzysztof
  Kozlowski who kindly verified in the datasheet.

Since v5:
- addressed Alistair reviews
- dropped "abstract generic-sdhci"
- dropped Linux Device Tree names
- split qtests in another series
- change the bcm2835 minimum blocksize to 1KB (Andrew Baumann)
- added Alistair R-b
- based on Alistair work:
  - add SD tunning sequence via Host Control 2 to use UHS-I cards
  - add CMD/DAT[] fields in the Present State (used in next series
to switch card voltage)

based on Alistair work:
- add SD tunning sequence via Host Control 2 to use UHS-I cards
- add CMD/DAT[] fields in the Present State (used in next series
  to switch card voltage)

Since v4 ("SDHCI: add qtests and fix few issues"):
- spec_version default to v2 (current behaviour)
- addressed Alistair review (no v1, tell user about valid version)

Since v3:
- no change, but split back in 2 series, 1st part is "SDHCI: housekeeping v5",

Since v2:
- more detailed 'capabilities', all boards converted to use these properties
- since all qtests pass, removed the previous 'capareg' property
- added Stefan/Alistair R-b
- corrected 'access' LED behavior (Alistair's review)
- more uses of the registerfields API
- remove some dead code
- cosmetix:
  - added more comments
  - renamed a pair of registers
  - reordered few struct members

Since v1:
- addressed Alistair Francis review comments, added some R-b
- only move register defines to "sd-internal.h"
- fixed deposit64() arguments
- dropped unuseful s->fifo_buffer = NULL
- use a qemu_irq for the LED, restrict the logging to ON/OFF
- fixed a trace format string error
- included Andrey Smirnov ACMD12ERRSTS write patch
- dropped few unuseful patches, and separate the Python polemical ones for later

>From the "SDHCI housekeeping" series:
- 1: we restrict part of "sd/sd.h" into local "sd-internal.h",
- 2,3: we somehow beautiful the code, no logical changes,
- 4-7: we refactor the common sysbus/pci qdev code,
- 8-10: we add plenty of trace events which will result useful later,
- 11: we finally expose a "dma-memory" property.
>From the "SDHCI: add a qtest and fix few issues" series:
- 12,13: fix registers
- 14,15: boards can specify which SDHCI Spec to use (v2 and v3 so far)
- 15-20: HCI qtest

Regards,

Phil.

$ git backport-diff with v8
001/16:[] [--] 'sdhci: use error_propagate(local_err) in realize()'
002/16:[0004] [FC] 'sdhci: add qtest to check the SD capabilities register'
003/16:[] [--] 'sdhci: add check_capab_readonly() qtest'
004/16:[] [--] 'sdhci: add a check_capab_baseclock() qtest'
005/16:[] [--] 'sdhci: add a check_capab_sdma() qtest'
006/16:[] [--] 'sdhci: add qtest to check the SD Spec version'
007/16:[0022] [FC] 'sdhci: add a 'spec_version property' (default to v2)'
008/16:[down] 'sdhci: use a numeric value for the default CAPAB register'
009/16:[down] 'sdhci: simplify sdhci_get_fifolen()'
010/16:[down] 'sdhci: check the Spec v1 capabilities correctness'
011/16:[] [--] 'sdhci: add BLOCK_SIZE_MASK for DMA'
012/16:[] [--] 'sdhci: Fix 64-bit ADMA2'
013/16:[down] 'sdhci: check Spec v2 capabilities (DMA and 64-bit bus)'
014/16:[down] 'hw/arm/exynos4210: access the 64-bit capareg with 
qdev_prop_set_uint64()'
015/16:[down] 'hw/arm/exynos4210: add a comment about a very similar SDHCI 
(Spec. v2)'
016/16:[down] 'hw/arm/xilinx_zynq: fix the capabilities register to match the 
datasheet'

Philippe Mathieu-Daudé (15):
  sdhci: use error_propagate(local_err) in realize()
  sdhci: add qtest to check the SD capabilities register
  sdhci: add check_capab_readonly() qtest
  sdhci: add a check_capab_baseclock() qtest
  sdhci: add a check_capab_sdma() qtest
  sdhci: add qtest to check the SD Spec version
  sdhci: add a 'spec_version property' (default to v2)
  sdhci: use a numeric value for the default CAPAB register
  sdhci: simplify sdhci_get_fifolen()
  sdhci: check the Spec v1 capabilities correctness
  sdhci: add BLOCK_SIZE_MASK for DMA
  sdhci: check Spec v2 capabilities (DMA and 64-bit bus)
  hw/arm/exynos4210: access the 64-bit capareg with qdev_prop_set_uint64()
  hw/arm/exynos4210: add a comment about a very similar SDHCI (Spec. v2)
  hw/arm/xilinx_zynq: fix the capabilities register to match the datasheet

Sai Pavan Boddu (1):
  sdhci: Fix 

[Qemu-devel] [PATCH v9 10/16] sdhci: check the Spec v1 capabilities correctness

2018-01-22 Thread Philippe Mathieu-Daudé
Incorrect value will throw an error.

Note than Spec v2 is supported by default.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sdhci-internal.h | 21 ++-
 hw/sd/sdhci.c  | 97 +-
 hw/sd/trace-events |  1 +
 3 files changed, 117 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 577ca9da54..c5e26bf8f3 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -86,6 +86,9 @@
 
 /* R/W Host control Register 0x0 */
 #define SDHC_HOSTCTL   0x28
+FIELD(SDHC_HOSTCTL, LED_CTRL,  0, 1);
+FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
+FIELD(SDHC_HOSTCTL, HIGH_SPEED,2, 1);
 #define SDHC_CTRL_DMA_CHECK_MASK   0x18
 #define SDHC_CTRL_SDMA 0x00
 #define SDHC_CTRL_ADMA1_32 0x08
@@ -96,6 +99,7 @@
 /* R/W Power Control Register 0x0 */
 #define SDHC_PWRCON0x29
 #define SDHC_POWER_ON  (1 << 0)
+FIELD(SDHC_PWRCON, BUS_VOLTAGE,1, 3);
 
 /* R/W Block Gap Control Register 0x0 */
 #define SDHC_BLKGAP0x2A
@@ -118,6 +122,7 @@
 
 /* R/W Timeout Control Register 0x0 */
 #define SDHC_TIMEOUTCON0x2E
+FIELD(SDHC_TIMEOUTCON, COUNTER,0, 4);
 
 /* R/W Software Reset Register 0x0 */
 #define SDHC_SWRST 0x2F
@@ -174,17 +179,31 @@
 
 /* ROC Auto CMD12 error status register 0x0 */
 #define SDHC_ACMD12ERRSTS  0x3C
+FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
+FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,  2, 1);
+FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,4, 1);
 
 /* HWInit Capabilities Register 0x05E80080 */
 #define SDHC_CAPAB 0x40
-#define SDHC_CAN_DO_DMA0x0040
 #define SDHC_CAN_DO_ADMA2  0x0008
 #define SDHC_CAN_DO_ADMA1  0x0010
 #define SDHC_64_BIT_BUS_SUPPORT(1 << 28)
+FIELD(SDHC_CAPAB, TOCLKFREQ,   0, 6);
+FIELD(SDHC_CAPAB, TOUNIT,  7, 1);
+FIELD(SDHC_CAPAB, BASECLKFREQ, 8, 8);
 FIELD(SDHC_CAPAB, MAXBLOCKLENGTH, 16, 2);
+FIELD(SDHC_CAPAB, HIGHSPEED,  21, 1);
+FIELD(SDHC_CAPAB, SDMA,   22, 1);
+FIELD(SDHC_CAPAB, SUSPRESUME, 23, 1);
+FIELD(SDHC_CAPAB, V33,24, 1);
+FIELD(SDHC_CAPAB, V30,25, 1);
+FIELD(SDHC_CAPAB, V18,26, 1);
 
 /* HWInit Maximum Current Capabilities Register 0x0 */
 #define SDHC_MAXCURR   0x48
+FIELD(SDHC_MAXCURR, V33_VDD1,  0, 8);
+FIELD(SDHC_MAXCURR, V30_VDD1,  8, 8);
+FIELD(SDHC_MAXCURR, V18_VDD1, 16, 8);
 
 /* W Force Event Auto CMD12 Error Interrupt Register 0x */
 #define SDHC_FEAER 0x50
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index dce1a49af1..91dfd684d8 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -23,6 +23,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "hw/hw.h"
 #include "sysemu/block-backend.h"
@@ -64,6 +65,92 @@ static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
 return 1 << (9 + FIELD_EX32(s->capareg, SDHC_CAPAB, MAXBLOCKLENGTH));
 }
 
+/* return true on error */
+static bool sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
+ uint8_t freq, Error **errp)
+{
+switch (freq) {
+case 0:
+case 10 ... 63:
+break;
+default:
+error_setg(errp, "SD %s clock frequency can have value"
+   "in range 0-63 only", desc);
+return true;
+}
+return false;
+}
+
+static void sdhci_check_capareg(SDHCIState *s, Error **errp)
+{
+uint64_t msk = s->capareg;
+uint32_t val;
+bool y;
+
+switch (s->sd_spec_version) {
+case 2: /* default version */
+
+/* fallback */
+case 1:
+y = FIELD_EX64(s->capareg, SDHC_CAPAB, TOUNIT);
+msk = FIELD_DP64(msk, SDHC_CAPAB, TOUNIT, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, TOCLKFREQ);
+trace_sdhci_capareg(y ? "timeout (MHz)" : "Timeout (KHz)", val);
+if (sdhci_check_capab_freq_range(s, "timeout", val, errp)) {
+return;
+}
+msk = FIELD_DP64(msk, SDHC_CAPAB, TOCLKFREQ, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, BASECLKFREQ);
+trace_sdhci_capareg(y ? "base (MHz)" : "Base (KHz)", val);
+if (sdhci_check_capab_freq_range(s, "base", val, errp)) {
+return;
+}
+msk = FIELD_DP64(msk, SDHC_CAPAB, BASECLKFREQ, 0);
+
+val = FIELD_EX64(s->capareg, SDHC_CAPAB, MAXBLOCKLENGTH);
+if (val >= 0b11) {
+error_setg(errp, "block size can be 512, 1024 or 2048 only");
+return;
+}
+trace_sdhci_capareg("max block length", sdhci_get_fifolen(s));
+msk = FIELD_DP64(msk, SDHC_CAPAB, MAXBLOCKLENGTH, 0);
+
+val = FIELD_EX64(s->capareg, 

[Qemu-devel] [PATCH v9 05/16] sdhci: add a check_capab_sdma() qtest

2018-01-22 Thread Philippe Mathieu-Daudé
Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Stefan Hajnoczi 
---
 tests/sdhci-test.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
index 5f036c8a75..f4c43b8120 100644
--- a/tests/sdhci-test.c
+++ b/tests/sdhci-test.c
@@ -15,6 +15,7 @@
 
 #define SDHC_CAPAB  0x40
 FIELD(SDHC_CAPAB, BASECLKFREQ,   8, 8); /* since v2 */
+FIELD(SDHC_CAPAB, SDMA, 22, 1);
 #define SDHC_HCVER  0xFE
 
 static const struct sdhci_t {
@@ -108,6 +109,15 @@ static void check_capab_baseclock(uintptr_t addr, uint8_t 
expected_freq)
 g_assert_cmpuint(capab_freq, ==, expected_freq);
 }
 
+static void check_capab_sdma(uintptr_t addr, bool supported)
+{
+uint64_t capab, capab_sdma;
+
+capab = sdhci_readq(addr, SDHC_CAPAB);
+capab_sdma = FIELD_EX64(capab, SDHC_CAPAB, SDMA);
+g_assert_cmpuint(capab_sdma, ==, supported);
+}
+
 static void machine_start(const struct sdhci_t *test)
 {
 if (test->pci.vendor_id) {
@@ -149,6 +159,7 @@ static void test_machine(const void *data)
 
 check_capab_capareg(test->sdhci.addr, test->sdhci.capab.reg);
 check_capab_readonly(test->sdhci.addr);
+check_capab_sdma(test->sdhci.addr, test->sdhci.capab.sdma);
 check_capab_baseclock(test->sdhci.addr, test->sdhci.baseclock);
 
 machine_stop();
-- 
2.15.1




[Qemu-devel] [PATCH v9 01/16] sdhci: use error_propagate(local_err) in realize()

2018-01-22 Thread Philippe Mathieu-Daudé
avoid the "errp && *errp" pattern (not recommended in "qapi/error.h" comments).

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
---
 hw/sd/sdhci.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index f9264d3be5..8c9c0fbc2a 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1300,10 +1300,12 @@ static Property sdhci_pci_properties[] = {
 static void sdhci_pci_realize(PCIDevice *dev, Error **errp)
 {
 SDHCIState *s = PCI_SDHCI(dev);
+Error *local_err = NULL;
 
 sdhci_initfn(s);
 sdhci_common_realize(s, errp);
-if (errp && *errp) {
+if (local_err) {
+error_propagate(errp, local_err);
 return;
 }
 
@@ -1381,9 +1383,11 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error 
** errp)
 {
 SDHCIState *s = SYSBUS_SDHCI(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+Error *local_err = NULL;
 
 sdhci_common_realize(s, errp);
-if (errp && *errp) {
+if (local_err) {
+error_propagate(errp, local_err);
 return;
 }
 
-- 
2.15.1




[Qemu-devel] [PATCH qemu v3] RFC: vfio-pci: Allow mmap of MSIX BAR

2018-01-22 Thread Alexey Kardashevskiy
This makes use of a new VFIO_REGION_INFO_CAP_MSIX_MAPPABLE capability
which tells that a region with MSIX data can be mapped entirely, i.e.
the VFIO PCI driver won't prevent MSIX vectors area from being mapped.

With this change, all BARs are mapped in a single chunk and MSIX vectors
are emulated on top unless the machine requests not to by defining and
enabling a new "vfio-no-msix-emulation" property. At the moment only
sPAPR machine does so - it prohibits MSIX emulation and does not allow
enabling it as it does not define the "set" callback for the new property;
the new property also does not appear in "-machine pseries,help".

If MSIX vectors section is not aligned to the page size, the KVM memory
listener does not register it with the KVM as a memory slot and MSIX is
emulated by QEMU as before. This may create MMIO RAM memory sections with
an address or/and a size not aligned which will make vfio_dma_map() fail;
to address this, this makes treats such failures as non-fatal.

This requires the kernel change - "vfio-pci: Allow mapping MSIX BAR" -
for the new capability: https://www.spinics.net/lists/kvm/msg160282.html

Signed-off-by: Alexey Kardashevskiy 
---
Changes:
v3:
* vfio_listener_region_add() won't make qemu exit if failed on MMIO MR

---
 include/hw/vfio/vfio-common.h |  1 +
 linux-headers/linux/vfio.h|  5 +
 hw/ppc/spapr.c|  7 +++
 hw/vfio/common.c  | 19 +++
 hw/vfio/pci.c | 10 ++
 5 files changed, 42 insertions(+)

diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index f3a2ac9..927d600 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -171,6 +171,7 @@ int vfio_get_region_info(VFIODevice *vbasedev, int index,
  struct vfio_region_info **info);
 int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
  uint32_t subtype, struct vfio_region_info **info);
+bool vfio_is_cap_present(VFIODevice *vbasedev, uint16_t cap_type, int region);
 #endif
 extern const MemoryListener vfio_prereg_listener;
 
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 4312e96..b45182e 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -301,6 +301,11 @@ struct vfio_region_info_cap_type {
 #define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
 #define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG  (3)
 
+/*
+ * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped.
+ */
+#define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3
+
 /**
  * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
  * struct vfio_irq_info)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d1acfe8..5ff43ce 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2789,6 +2789,11 @@ static void spapr_set_modern_hotplug_events(Object *obj, 
bool value,
 spapr->use_hotplug_event_source = value;
 }
 
+static bool spapr_get_msix_emulation(Object *obj, Error **errp)
+{
+return true;
+}
+
 static char *spapr_get_resize_hpt(Object *obj, Error **errp)
 {
 sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
@@ -2870,6 +2875,8 @@ static void spapr_instance_init(Object *obj)
 object_property_set_description(obj, "vsmt",
 "Virtual SMT: KVM behaves as if this were"
 " the host's SMT mode", _abort);
+object_property_add_bool(obj, "vfio-no-msix-emulation",
+ spapr_get_msix_emulation, NULL, NULL);
 }
 
 static void spapr_machine_finalizefn(Object *obj)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b77be3a..842c5b2 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -530,6 +530,10 @@ static void vfio_listener_region_add(MemoryListener 
*listener,
 return;
 
 fail:
+if (memory_region_is_ram_device(section->mr)) {
+error_report("failed to vfio_dma_map. pci p2p may not work");
+return;
+}
 /*
  * On the initfn path, store the first error in the container so we
  * can gracefully fail.  Runtime, there's not much we can do other
@@ -1387,6 +1391,21 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, 
uint32_t type,
 return -ENODEV;
 }
 
+bool vfio_is_cap_present(VFIODevice *vbasedev, uint16_t cap_type, int region)
+{
+struct vfio_region_info *info = NULL;
+bool ret = false;
+
+if (!vfio_get_region_info(vbasedev, region, )) {
+if (vfio_get_region_info_cap(info, cap_type)) {
+ret = true;
+}
+g_free(info);
+}
+
+return ret;
+}
+
 /*
  * Interfaces for IBM EEH (Enhanced Error Handling)
  */
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 359a8f1..a96ece6 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -1289,6 +1289,11 @@ static void vfio_pci_fixup_msix_region(VFIOPCIDevice 
*vdev)
 off_t start, end;
 VFIORegion *region = 

Re: [Qemu-devel] [PATCH] linux-user: implement renameat2

2018-01-22 Thread Laurent Vivier
Le 22/01/2018 à 18:44, Andreas Schwab a écrit :
> This is needed for new architectures like RISC-V which do not provide any
> other rename-like syscall.
> 
> Signed-off-by: Andreas Schwab 
> ---
>  linux-user/syscall.c | 33 +
>  1 file changed, 33 insertions(+)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 5e54889522..12ca06c65a 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -598,6 +598,23 @@ static int sys_utimensat(int dirfd, const char *pathname,
>  #endif
>  #endif /* TARGET_NR_utimensat */
>  
> +#ifdef TARGET_NR_renameat2
> +#if defined(__NR_renameat2)
> +#define __NR_sys_renameat2 __NR_renameat2
> +_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
> +  const char *, new, unsigned int, flags)
> +#else
> +static int sys_renameat2(int oldfd, const char *old,
> + int newfd, const chat *new, int flags)

"const char *" would look better.

And, please, test it (build/run).

Thanks,
Laurent




Re: [Qemu-devel] [PATCH] linux-user: implement renameat2

2018-01-22 Thread Laurent Vivier
Le 22/01/2018 à 18:44, Andreas Schwab a écrit :
> This is needed for new architectures like RISC-V which do not provide any
> other rename-like syscall.
> 
> Signed-off-by: Andreas Schwab 
> ---
>  linux-user/syscall.c | 33 +
>  1 file changed, 33 insertions(+)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 5e54889522..12ca06c65a 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -598,6 +598,23 @@ static int sys_utimensat(int dirfd, const char *pathname,
>  #endif
>  #endif /* TARGET_NR_utimensat */
>  
> +#ifdef TARGET_NR_renameat2
> +#if defined(__NR_renameat2)
> +#define __NR_sys_renameat2 __NR_renameat2
> +_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
> +  const char *, new, unsigned int, flags)
> +#else
> +static int sys_renameat2(int oldfd, const char *old,
> + int newfd, const chat *new, int flags)
> +{
> +if (flags == 0)
> +return renameat(oldfd, old, newfd, new);

Please fix style problem reported by patchew
(or ./scripts/checkpatch.pl)

> +errno = ENOSYS;
> +return -1;
> +}
> +#endif
> +#endif /* TARGET_NR_renameat2 */
> +
>  #ifdef CONFIG_INOTIFY
>  #include 
>  
> @@ -8342,6 +8359,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
> arg1,
>  }
>  break;
>  #endif
> +#if defined(TARGET_NR_renameat2)
> +case TARGET_NR_renameat2:
> +{
> +void *p2;
> +p  = lock_user_string(arg2);
> +p2 = lock_user_string(arg4);
> +if (!p || !p2)
> +ret = -TARGET_EFAULT;
> +else
> +ret = get_errno(sys_renameat2(arg1, p, arg3, p2,
> +  target_to_host_bitmask(arg5, 
> fcntl_flags_tbl)));

You can't use fcntl_flags_tbl
(because it converts fcntl/open flags O_*).

I think you can provide directly arg5 to sys_renameat2() because flags
are the same for all architectures (and value is already byte-swapped).

Thanks,
Laurent



Re: [Qemu-devel] [PATCH v3] ppc: Deprecate qemu-system-ppcemb

2018-01-22 Thread David Gibson
On Sun, Jan 21, 2018 at 10:57:58PM +0100, Thomas Huth wrote:
> qemu-system-ppcemb has been once split of qemu-system-ppc to support
> CPU page sizes < 4096 for some of the embedded 4xx PowerPC CPUs.
> However, there was hardly any OS available in the wild that really
> used such small page sizes (Linux uses 4096 on PPC), so there is
> no known recent use case for this separate build anymore. It's
> rather cumbersome to maintain a separate set of config switches for
> this, and it's wasting compile and test time of all the developers
> who have to build all QEMU targets to verify that their changes did
> not break anything.
> 
> Except for the small CPU page sizes, qemu-system-ppc can be used as
> a full replacement for qemu-system-ppcemb since it contains all the
> embedded 4xx PPC boards and CPUs, too. Thus let's start the deprecation
> process for qemu-system-ppcemb to see whether somebody still needs
> the small page sizes or whether we could finally remove this unloved
> separate build.
> 
> Signed-off-by: Thomas Huth 

Applied, thanks.

> ---
>  v3: Use qtest_enabled() and emit the deprecation message in the
>  machine init functions (I unfortunately haven't found a better
>  common spot for all 4xx machines where qtest_enabled() works).
> 
>  hw/ppc/ppc405_boards.c | 14 ++
>  hw/ppc/ppc440_bamboo.c |  9 +
>  hw/ppc/virtex_ml507.c  |  8 
>  qemu-doc.texi  |  6 ++
>  4 files changed, 37 insertions(+)
> 
> diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
> index e92db2c..6f7f2ee 100644
> --- a/hw/ppc/ppc405_boards.c
> +++ b/hw/ppc/ppc405_boards.c
> @@ -202,6 +202,13 @@ static void ref405ep_init(MachineState *machine)
>  DriveInfo *dinfo;
>  MemoryRegion *sysmem = get_system_memory();
>  
> +#ifdef TARGET_PPCEMB
> +if (!qtest_enabled()) {
> +warn_report("qemu-system-ppcemb is deprecated, "
> +"please use qemu-system-ppc instead.");
> +}
> +#endif
> +
>  /* XXX: fix this */
>  memory_region_allocate_system_memory(_memories[0], NULL, 
> "ef405ep.ram",
>   0x0800);
> @@ -497,6 +504,13 @@ static void taihu_405ep_init(MachineState *machine)
>  int fl_idx, fl_sectors;
>  DriveInfo *dinfo;
>  
> +#ifdef TARGET_PPCEMB
> +if (!qtest_enabled()) {
> +warn_report("qemu-system-ppcemb is deprecated, "
> +"please use qemu-system-ppc instead.");
> +}
> +#endif
> +
>  /* RAM is soldered to the board so the size cannot be changed */
>  ram_size = 0x0800;
>  memory_region_allocate_system_memory(ram, NULL, "taihu_405ep.ram",
> diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
> index 693c215..a299206 100644
> --- a/hw/ppc/ppc440_bamboo.c
> +++ b/hw/ppc/ppc440_bamboo.c
> @@ -13,6 +13,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/error-report.h"
>  #include "net/net.h"
>  #include "hw/hw.h"
>  #include "hw/pci/pci.h"
> @@ -27,6 +28,7 @@
>  #include "hw/ppc/ppc.h"
>  #include "ppc405.h"
>  #include "sysemu/sysemu.h"
> +#include "sysemu/qtest.h"
>  #include "hw/sysbus.h"
>  
>  #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
> @@ -191,6 +193,13 @@ static void bamboo_init(MachineState *machine)
>  exit(1);
>  }
>  
> +#ifdef TARGET_PPCEMB
> +if (!qtest_enabled()) {
> +warn_report("qemu-system-ppcemb is deprecated, "
> +"please use qemu-system-ppc instead.");
> +}
> +#endif
> +
>  qemu_register_reset(main_cpu_reset, cpu);
>  ppc_booke_timers_init(cpu, 4, 0);
>  ppc_dcr_init(env, NULL, NULL);
> diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
> index 5ac4f76..9fe7655 100644
> --- a/hw/ppc/virtex_ml507.c
> +++ b/hw/ppc/virtex_ml507.c
> @@ -29,6 +29,7 @@
>  #include "hw/char/serial.h"
>  #include "hw/block/flash.h"
>  #include "sysemu/sysemu.h"
> +#include "sysemu/qtest.h"
>  #include "hw/devices.h"
>  #include "hw/boards.h"
>  #include "sysemu/device_tree.h"
> @@ -210,6 +211,13 @@ static void virtex_init(MachineState *machine)
>  int kernel_size;
>  int i;
>  
> +#ifdef TARGET_PPCEMB
> +if (!qtest_enabled()) {
> +warn_report("qemu-system-ppcemb is deprecated, "
> +"please use qemu-system-ppc instead.");
> +}
> +#endif
> +
>  /* init CPUs */
>  cpu = ppc440_init_xilinx(_size, 1, machine->cpu_type, 4);
>  env = >env;
> diff --git a/qemu-doc.texi b/qemu-doc.texi
> index 3e9eb81..b13c633 100644
> --- a/qemu-doc.texi
> +++ b/qemu-doc.texi
> @@ -2766,6 +2766,12 @@ The ``host_net_remove'' command is replaced by the 
> ``netdev_del'' command.
>  The ``ivshmem'' device type is replaced by either the ``ivshmem-plain''
>  or ``ivshmem-doorbell`` device types.
>  
> +@subsection Page size support < 4k for embedded PowerPC CPUs (since 2.12.0)
> +
> +qemu-system-ppcemb will be removed. qemu-system-ppc (or qemu-system-ppc64)
> 

Re: [Qemu-devel] [PATCH] tpm: Set the flags of the CMD_INIT command to 0

2018-01-22 Thread Marc-André Lureau
On Mon, Jan 22, 2018 at 10:33 PM, Stefan Berger
 wrote:
> The flags of the CMD_INIT control channel command were not
> initialized properly. Fix this and set to 0.
>
> Signed-off-by: Stefan Berger 

Reviewed-by: Marc-André Lureau 


> ---
>  hw/tpm/tpm_emulator.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
> index 35c78de..532d3e3 100644
> --- a/hw/tpm/tpm_emulator.c
> +++ b/hw/tpm/tpm_emulator.c
> @@ -320,7 +320,9 @@ static int tpm_emulator_set_buffer_size(TPMBackend *tb,
>  static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
>  {
>  TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
> -ptm_init init;
> +ptm_init init = {
> +.u.req.init_flags = 0,
> +};
>  ptm_res res;
>
>  if (buffersize != 0 &&
> --
> 2.5.5
>
>



-- 
Marc-André Lureau



Re: [Qemu-devel] [PATCH v3 2/5] qapi: add nbd-server-remove

2018-01-22 Thread Eric Blake
On 01/19/2018 07:57 AM, Vladimir Sementsov-Ogievskiy wrote:
> Add command for removing an export. It is needed for cases when we
> don't want to keep export after the operation on it was completed.
> The other example is temporary node, created with blockdev-add.
> If we want to delete it we should firstly remove corresponding
> NBD export.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---

> +++ b/nbd/server.c
> @@ -1177,6 +1177,26 @@ void nbd_export_close(NBDExport *exp)
>  nbd_export_put(exp);
>  }
>  
> +void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error 
> **errp)
> +{
> +NBDClient *client;
> +int nb_clients = 0;
> +
> +if (mode == NBD_SERVER_REMOVE_MODE_HARD || QTAILQ_EMPTY(>clients)) {
> +nbd_export_close(exp);
> +return;
> +}
> +
> +assert(mode == NBD_SERVER_REMOVE_MODE_SAFE);
> +
> +QTAILQ_FOREACH(client, >clients, next) {
> +nb_clients++;
> +}
> +

Now that the error message is not using nb_clients, we can simplify the
code to quit computing it.

> +error_setg(errp, "export '%s' still in use", exp->name);
> +error_append_hint(errp, "Use mode='hard' to force client disconnect\n");
> +}
> +
>  void nbd_export_get(NBDExport *exp)
>  {
>  assert(exp->refcount > 0);
> 

I'll make that change as part of adding it to my NBD queue.
Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [PATCH v2 12/16] block/mirror: Distinguish active from passive ops

2018-01-22 Thread Max Reitz
Currently, the mirror block job only knows passive operations.  But once
we introduce active writes, we need to distinguish between the two; for
example, mirror_wait_for_free_in_flight_slot() should wait for a passive
operation because active writes will not use the same in-flight slots.

Signed-off-by: Max Reitz 
---
 block/mirror.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 2363e79563..bb46f3c4e9 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -89,6 +89,7 @@ struct MirrorOp {
 int64_t *bytes_handled;
 
 bool is_pseudo_op;
+bool is_active_write;
 CoQueue waiting_requests;
 
 QTAILQ_ENTRY(MirrorOp) next;
@@ -281,8 +282,10 @@ static inline void 
mirror_wait_for_free_in_flight_slot(MirrorBlockJob *s)
  * some other operation to start, which may in fact be the
  * caller of this function.  Since there is only one pseudo op
  * at any given time, we will always find some real operation
- * to wait on. */
-if (!op->is_pseudo_op) {
+ * to wait on.
+ * Also, only non-active operations use up in-flight slots, so
+ * we can ignore active operations. */
+if (!op->is_pseudo_op && !op->is_active_write) {
 qemu_co_queue_wait(>waiting_requests, NULL);
 return;
 }
-- 
2.14.3




[Qemu-devel] [PATCH v2 10/16] hbitmap: Add @advance param to hbitmap_iter_next()

2018-01-22 Thread Max Reitz
This new parameter allows the caller to just query the next dirty
position without moving the iterator.

Signed-off-by: Max Reitz 
---
 include/qemu/hbitmap.h |  5 -
 block/backup.c |  2 +-
 block/dirty-bitmap.c   |  2 +-
 tests/test-hbitmap.c   | 26 +-
 util/hbitmap.c | 10 +++---
 5 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h
index 6b6490ecad..ddca52c48e 100644
--- a/include/qemu/hbitmap.h
+++ b/include/qemu/hbitmap.h
@@ -324,11 +324,14 @@ void hbitmap_free_meta(HBitmap *hb);
 /**
  * hbitmap_iter_next:
  * @hbi: HBitmapIter to operate on.
+ * @advance: If true, advance the iterator.  Otherwise, the next call
+ *   of this function will return the same result (if that
+ *   position is still dirty).
  *
  * Return the next bit that is set in @hbi's associated HBitmap,
  * or -1 if all remaining bits are zero.
  */
-int64_t hbitmap_iter_next(HBitmapIter *hbi);
+int64_t hbitmap_iter_next(HBitmapIter *hbi, bool advance);
 
 /**
  * hbitmap_iter_next_word:
diff --git a/block/backup.c b/block/backup.c
index 4a16a37229..c083ce0deb 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -368,7 +368,7 @@ static int coroutine_fn 
backup_run_incremental(BackupBlockJob *job)
 HBitmapIter hbi;
 
 hbitmap_iter_init(, job->copy_bitmap, 0);
-while ((cluster = hbitmap_iter_next()) != -1) {
+while ((cluster = hbitmap_iter_next(, true)) != -1) {
 do {
 if (yield_and_check(job)) {
 return 0;
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 7879d13ddb..50564fa1e2 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -498,7 +498,7 @@ void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
 
 int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
 {
-return hbitmap_iter_next(>hbi);
+return hbitmap_iter_next(>hbi, true);
 }
 
 /* Called within bdrv_dirty_bitmap_lock..unlock */
diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c
index 9091c639b3..2a2aa5bd43 100644
--- a/tests/test-hbitmap.c
+++ b/tests/test-hbitmap.c
@@ -46,7 +46,7 @@ static void hbitmap_test_check(TestHBitmapData *data,
 
 i = first;
 for (;;) {
-next = hbitmap_iter_next();
+next = hbitmap_iter_next(, true);
 if (next < 0) {
 next = data->size;
 }
@@ -435,25 +435,25 @@ static void test_hbitmap_iter_granularity(TestHBitmapData 
*data,
 /* Note that hbitmap_test_check has to be invoked manually in this test.  
*/
 hbitmap_test_init(data, 131072 << 7, 7);
 hbitmap_iter_init(, data->hb, 0);
-g_assert_cmpint(hbitmap_iter_next(), <, 0);
+g_assert_cmpint(hbitmap_iter_next(, true), <, 0);
 
 hbitmap_test_set(data, ((L2 + L1 + 1) << 7) + 8, 8);
 hbitmap_iter_init(, data->hb, 0);
-g_assert_cmpint(hbitmap_iter_next(), ==, (L2 + L1 + 1) << 7);
-g_assert_cmpint(hbitmap_iter_next(), <, 0);
+g_assert_cmpint(hbitmap_iter_next(, true), ==, (L2 + L1 + 1) << 7);
+g_assert_cmpint(hbitmap_iter_next(, true), <, 0);
 
 hbitmap_iter_init(, data->hb, (L2 + L1 + 2) << 7);
-g_assert_cmpint(hbitmap_iter_next(), <, 0);
+g_assert_cmpint(hbitmap_iter_next(, true), <, 0);
 
 hbitmap_test_set(data, (131072 << 7) - 8, 8);
 hbitmap_iter_init(, data->hb, 0);
-g_assert_cmpint(hbitmap_iter_next(), ==, (L2 + L1 + 1) << 7);
-g_assert_cmpint(hbitmap_iter_next(), ==, 131071 << 7);
-g_assert_cmpint(hbitmap_iter_next(), <, 0);
+g_assert_cmpint(hbitmap_iter_next(, true), ==, (L2 + L1 + 1) << 7);
+g_assert_cmpint(hbitmap_iter_next(, true), ==, 131071 << 7);
+g_assert_cmpint(hbitmap_iter_next(, true), <, 0);
 
 hbitmap_iter_init(, data->hb, (L2 + L1 + 2) << 7);
-g_assert_cmpint(hbitmap_iter_next(), ==, 131071 << 7);
-g_assert_cmpint(hbitmap_iter_next(), <, 0);
+g_assert_cmpint(hbitmap_iter_next(, true), ==, 131071 << 7);
+g_assert_cmpint(hbitmap_iter_next(, true), <, 0);
 }
 
 static void hbitmap_test_set_boundary_bits(TestHBitmapData *data, ssize_t diff)
@@ -893,7 +893,7 @@ static void test_hbitmap_serialize_zeroes(TestHBitmapData 
*data,
 for (i = 0; i < num_positions; i++) {
 hbitmap_deserialize_zeroes(data->hb, positions[i], min_l1, true);
 hbitmap_iter_init(, data->hb, 0);
-next = hbitmap_iter_next();
+next = hbitmap_iter_next(, true);
 if (i == num_positions - 1) {
 g_assert_cmpint(next, ==, -1);
 } else {
@@ -919,10 +919,10 @@ static void test_hbitmap_iter_and_reset(TestHBitmapData 
*data,
 
 hbitmap_iter_init(, data->hb, BITS_PER_LONG - 1);
 
-hbitmap_iter_next();
+hbitmap_iter_next(, true);
 
 hbitmap_reset_all(data->hb);
-hbitmap_iter_next();
+hbitmap_iter_next(, true);
 }
 
 static void test_hbitmap_next_zero_check(TestHBitmapData *data, int64_t start)
diff --git a/util/hbitmap.c b/util/hbitmap.c
index 

[Qemu-devel] [PATCH v2 09/16] block: Generalize should_update_child() rule

2018-01-22 Thread Max Reitz
Currently, bdrv_replace_node() refuses to create loops from one BDS to
itself if the BDS to be replaced is the backing node of the BDS to
replace it: Say there is a node A and a node B.  Replacing B by A means
making all references to B point to A.  If B is a child of A (i.e. A has
a reference to B), that would mean we would have to make this reference
point to A itself -- so we'd create a loop.

bdrv_replace_node() (through should_update_child()) refuses to do so if
B is the backing node of A.  There is no reason why we should create
loops if B is not the backing node of A, though.  The BDS graph should
never contain loops, so we should always refuse to create them.

If B is a child of A and B is to be replaced by A, we should simply
leave B in place there because it is the most sensible choice.

A more specific argument would be: Putting filter drivers into the BDS
graph is basically the same as appending an overlay to a backing chain.
But the main child BDS of a filter driver is not "backing" but "file",
so restricting the no-loop rule to backing nodes would fail here.

Signed-off-by: Max Reitz 
---
 include/block/block_int.h |  2 ++
 block.c   | 44 ++--
 2 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/include/block/block_int.h b/include/block/block_int.h
index 29cafa4236..03f3fdd129 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -587,6 +587,8 @@ struct BdrvChild {
 QLIST_ENTRY(BdrvChild) next_parent;
 };
 
+typedef QLIST_HEAD(BdrvChildList, BdrvChild) BdrvChildList;
+
 /*
  * Note: the function bdrv_append() copies and swaps contents of
  * BlockDriverStates, so if you add new fields to this struct, please
diff --git a/block.c b/block.c
index a8da4f2b25..df50825d94 100644
--- a/block.c
+++ b/block.c
@@ -3320,16 +3320,39 @@ static bool should_update_child(BdrvChild *c, 
BlockDriverState *to)
 return false;
 }
 
-if (c->role == _backing) {
-/* If @from is a backing file of @to, ignore the child to avoid
- * creating a loop. We only want to change the pointer of other
- * parents. */
-QLIST_FOREACH(to_c, >children, next) {
-if (to_c == c) {
-break;
-}
-}
-if (to_c) {
+/* If the child @c belongs to the BDS @to, replacing the current
+ * c->bs by @to would mean to create a loop.
+ *
+ * Such a case occurs when appending a BDS to a backing chain.
+ * For instance, imagine the following chain:
+ *
+ *   guest device -> node A -> further backing chain...
+ *
+ * Now we create a new BDS B which we want to put on top of this
+ * chain, so we first attach A as its backing node:
+ *
+ *   node B
+ * |
+ * v
+ *   guest device -> node A -> further backing chain...
+ *
+ * Finally we want to replace A by B.  When doing that, we want to
+ * replace all pointers to A by pointers to B -- except for the
+ * pointer from B because (1) that would create a loop, and (2)
+ * that pointer should simply stay intact:
+ *
+ *   guest device -> node B
+ * |
+ * v
+ *   node A -> further backing chain...
+ *
+ * In general, when replacing a node A (c->bs) by a node B (@to),
+ * if A is a child of B, that means we cannot replace A by B there
+ * because that would create a loop.  Silently detaching A from B
+ * is also not really an option.  So overall just leaving A in
+ * place there is the most sensible choice. */
+QLIST_FOREACH(to_c, >children, next) {
+if (to_c == c) {
 return false;
 }
 }
@@ -3355,6 +3378,7 @@ void bdrv_replace_node(BlockDriverState *from, 
BlockDriverState *to,
 
 /* Put all parents into @list and calculate their cumulative permissions */
 QLIST_FOREACH_SAFE(c, >parents, next_parent, next) {
+assert(c->bs == from);
 if (!should_update_child(c, to)) {
 continue;
 }
-- 
2.14.3




[Qemu-devel] [PATCH v2 08/16] block/mirror: Use source as a BdrvChild

2018-01-22 Thread Max Reitz
With this, the mirror_top_bs is no longer just a technically required
node in the BDS graph but actually represents the block job operation.

Also, drop MirrorBlockJob.source, as we can reach it through
mirror_top_bs->backing.

Signed-off-by: Max Reitz 
---
 block/mirror.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 9dbe6a9130..2363e79563 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -43,7 +43,6 @@ typedef struct MirrorBlockJob {
 RateLimit limit;
 BlockBackend *target;
 BlockDriverState *mirror_top_bs;
-BlockDriverState *source;
 BlockDriverState *base;
 
 /* The name of the graph node to replace */
@@ -303,7 +302,6 @@ static void coroutine_fn mirror_co_read(void *opaque)
 {
 MirrorOp *op = opaque;
 MirrorBlockJob *s = op->s;
-BlockBackend *source = s->common.blk;
 int nb_chunks;
 uint64_t ret;
 uint64_t max_bytes;
@@ -353,7 +351,8 @@ static void coroutine_fn mirror_co_read(void *opaque)
 s->bytes_in_flight += op->bytes;
 trace_mirror_one_iteration(s, op->offset, op->bytes);
 
-ret = blk_co_preadv(source, op->offset, op->bytes, >qiov, 0);
+ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
+ >qiov, 0);
 mirror_read_complete(op, ret);
 }
 
@@ -431,7 +430,7 @@ static unsigned mirror_perform(MirrorBlockJob *s, int64_t 
offset,
 
 static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
 {
-BlockDriverState *source = s->source;
+BlockDriverState *source = s->mirror_top_bs->backing->bs;
 MirrorOp *pseudo_op;
 int64_t offset;
 uint64_t delay_ns = 0, ret = 0;
@@ -606,7 +605,7 @@ static void mirror_exit(BlockJob *job, void *opaque)
 MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
 MirrorExitData *data = opaque;
 AioContext *replace_aio_context = NULL;
-BlockDriverState *src = s->source;
+BlockDriverState *src = s->mirror_top_bs->backing->bs;
 BlockDriverState *target_bs = blk_bs(s->target);
 BlockDriverState *mirror_top_bs = s->mirror_top_bs;
 Error *local_err = NULL;
@@ -721,7 +720,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
 {
 int64_t offset;
 BlockDriverState *base = s->base;
-BlockDriverState *bs = s->source;
+BlockDriverState *bs = s->mirror_top_bs->backing->bs;
 BlockDriverState *target_bs = blk_bs(s->target);
 int ret;
 int64_t count;
@@ -803,7 +802,7 @@ static void coroutine_fn mirror_run(void *opaque)
 {
 MirrorBlockJob *s = opaque;
 MirrorExitData *data;
-BlockDriverState *bs = s->source;
+BlockDriverState *bs = s->mirror_top_bs->backing->bs;
 BlockDriverState *target_bs = blk_bs(s->target);
 bool need_drain = true;
 int64_t length;
@@ -1290,7 +1289,6 @@ static void mirror_start_job(const char *job_id, 
BlockDriverState *bs,
 /* The block job now has a reference to this node */
 bdrv_unref(mirror_top_bs);
 
-s->source = bs;
 s->mirror_top_bs = mirror_top_bs;
 
 /* No resize for the target either; while the mirror is still running, a
-- 
2.14.3




[Qemu-devel] [PATCH v2 14/16] block/mirror: Add active mirroring

2018-01-22 Thread Max Reitz
This patch implements active synchronous mirroring.  In active mode, the
passive mechanism will still be in place and is used to copy all
initially dirty clusters off the source disk; but every write request
will write data both to the source and the target disk, so the source
cannot be dirtied faster than data is mirrored to the target.  Also,
once the block job has converged (BLOCK_JOB_READY sent), source and
target are guaranteed to stay in sync (unless an error occurs).

Active mode is completely optional and currently disabled at runtime.  A
later patch will add a way for users to enable it.

Signed-off-by: Max Reitz 
---
 qapi/block-core.json |  18 +
 block/mirror.c   | 188 +--
 2 files changed, 200 insertions(+), 6 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 89ed2bc6a4..ba1fd736f5 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -937,6 +937,24 @@
 { 'enum': 'MirrorSyncMode',
   'data': ['top', 'full', 'none', 'incremental'] }
 
+##
+# @MirrorCopyMode:
+#
+# An enumeration whose values tell the mirror block job when to
+# trigger writes to the target.
+#
+# @background: copy data in background only.
+#
+# @write-blocking: when data is written to the source, write it
+#  (synchronously) to the target as well.  In
+#  addition, data is copied in background just like in
+#  @background mode.
+#
+# Since: 2.12
+##
+{ 'enum': 'MirrorCopyMode',
+  'data': ['background', 'write-blocking'] }
+
 ##
 # @BlockJobType:
 #
diff --git a/block/mirror.c b/block/mirror.c
index c1987b0230..83082adb64 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -53,8 +53,12 @@ typedef struct MirrorBlockJob {
 Error *replace_blocker;
 bool is_none_mode;
 BlockMirrorBackingMode backing_mode;
+MirrorCopyMode copy_mode;
 BlockdevOnError on_source_error, on_target_error;
 bool synced;
+/* Set when the target is synced (dirty bitmap is clean, nothing
+ * in flight) and the job is running in active mode */
+bool actively_synced;
 bool should_complete;
 int64_t granularity;
 size_t buf_size;
@@ -76,6 +80,7 @@ typedef struct MirrorBlockJob {
 int target_cluster_size;
 int max_iov;
 bool initial_zeroing_ongoing;
+int in_active_write_counter;
 } MirrorBlockJob;
 
 typedef struct MirrorBDSOpaque {
@@ -109,6 +114,7 @@ static BlockErrorAction mirror_error_action(MirrorBlockJob 
*s, bool read,
 int error)
 {
 s->synced = false;
+s->actively_synced = false;
 if (read) {
 return block_job_error_action(>common, s->on_source_error,
   true, error);
@@ -277,7 +283,7 @@ static int mirror_cow_align(MirrorBlockJob *s, int64_t 
*offset,
 return ret;
 }
 
-static inline void mirror_wait_for_free_in_flight_slot(MirrorBlockJob *s)
+static inline void mirror_wait_for_any_operation(MirrorBlockJob *s, bool 
active)
 {
 MirrorOp *op;
 
@@ -286,10 +292,8 @@ static inline void 
mirror_wait_for_free_in_flight_slot(MirrorBlockJob *s)
  * some other operation to start, which may in fact be the
  * caller of this function.  Since there is only one pseudo op
  * at any given time, we will always find some real operation
- * to wait on.
- * Also, only non-active operations use up in-flight slots, so
- * we can ignore active operations. */
-if (!op->is_pseudo_op && !op->is_active_write) {
+ * to wait on. */
+if (!op->is_pseudo_op && op->is_active_write == active) {
 qemu_co_queue_wait(>waiting_requests, NULL);
 return;
 }
@@ -297,6 +301,12 @@ static inline void 
mirror_wait_for_free_in_flight_slot(MirrorBlockJob *s)
 abort();
 }
 
+static inline void mirror_wait_for_free_in_flight_slot(MirrorBlockJob *s)
+{
+/* Only non-active operations use up in-flight slots */
+mirror_wait_for_any_operation(s, false);
+}
+
 /* Perform a mirror copy operation.
  *
  * *op->bytes_handled is set to the number of bytes copied after and
@@ -854,6 +864,7 @@ static void coroutine_fn mirror_run(void *opaque)
 /* Report BLOCK_JOB_READY and wait for complete. */
 block_job_event_ready(>common);
 s->synced = true;
+s->actively_synced = true;
 while (!block_job_is_cancelled(>common) && !s->should_complete) {
 block_job_yield(>common);
 }
@@ -905,6 +916,12 @@ static void coroutine_fn mirror_run(void *opaque)
 int64_t cnt, delta;
 bool should_complete;
 
+/* Do not start passive operations while there are active
+ * writes in progress */
+while (s->in_active_write_counter) {
+mirror_wait_for_any_operation(s, true);
+}
+
 if (s->ret < 0) {
 ret = s->ret;
 goto immediate_exit;
@@ -952,6 +969,9 @@ 

[Qemu-devel] [PATCH v2 15/16] block/mirror: Add copy mode QAPI interface

2018-01-22 Thread Max Reitz
This patch allows the user to specify whether to use active or only
passive mode for mirror block jobs.  Currently, this setting will remain
constant for the duration of the entire block job.

Signed-off-by: Max Reitz 
---
 qapi/block-core.json  | 11 +--
 include/block/block_int.h |  4 +++-
 block/mirror.c| 12 +++-
 blockdev.c|  9 -
 4 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index ba1fd736f5..5fafa5fcac 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1573,6 +1573,9 @@
 # written. Both will result in identical contents.
 # Default is true. (Since 2.4)
 #
+# @copy-mode: when to copy data to the destination; defaults to 'passive'
+# (Since: 2.12)
+#
 # Since: 1.3
 ##
 { 'struct': 'DriveMirror',
@@ -1582,7 +1585,7 @@
 '*speed': 'int', '*granularity': 'uint32',
 '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
 '*on-target-error': 'BlockdevOnError',
-'*unmap': 'bool' } }
+'*unmap': 'bool', '*copy-mode': 'MirrorCopyMode' } }
 
 ##
 # @BlockDirtyBitmap:
@@ -1761,6 +1764,9 @@
 #above @device. If this option is not given, a node name is
 #autogenerated. (Since: 2.9)
 #
+# @copy-mode: when to copy data to the destination; defaults to 'passive'
+# (Since: 2.12)
+#
 # Returns: nothing on success.
 #
 # Since: 2.6
@@ -1781,7 +1787,8 @@
 '*speed': 'int', '*granularity': 'uint32',
 '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
 '*on-target-error': 'BlockdevOnError',
-'*filter-node-name': 'str' } }
+'*filter-node-name': 'str',
+'*copy-mode': 'MirrorCopyMode' } }
 
 ##
 # @block_set_io_throttle:
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 03f3fdd129..1fda4d3d43 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -948,6 +948,7 @@ void commit_active_start(const char *job_id, 
BlockDriverState *bs,
  * @filter_node_name: The node name that should be assigned to the filter
  * driver that the mirror job inserts into the graph above @bs. NULL means that
  * a node name should be autogenerated.
+ * @copy_mode: When to trigger writes to the target.
  * @errp: Error object.
  *
  * Start a mirroring operation on @bs.  Clusters that are allocated
@@ -961,7 +962,8 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
   MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
   BlockdevOnError on_source_error,
   BlockdevOnError on_target_error,
-  bool unmap, const char *filter_node_name, Error **errp);
+  bool unmap, const char *filter_node_name,
+  MirrorCopyMode copy_mode, Error **errp);
 
 /*
  * backup_job_create:
diff --git a/block/mirror.c b/block/mirror.c
index 83082adb64..3b23886a5a 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1409,7 +1409,7 @@ static void mirror_start_job(const char *job_id, 
BlockDriverState *bs,
  const BlockJobDriver *driver,
  bool is_none_mode, BlockDriverState *base,
  bool auto_complete, const char *filter_node_name,
- bool is_mirror,
+ bool is_mirror, MirrorCopyMode copy_mode,
  Error **errp)
 {
 MirrorBlockJob *s;
@@ -1515,7 +1515,7 @@ static void mirror_start_job(const char *job_id, 
BlockDriverState *bs,
 s->on_target_error = on_target_error;
 s->is_none_mode = is_none_mode;
 s->backing_mode = backing_mode;
-s->copy_mode = MIRROR_COPY_MODE_BACKGROUND;
+s->copy_mode = copy_mode;
 s->base = base;
 s->granularity = granularity;
 s->buf_size = ROUND_UP(buf_size, granularity);
@@ -1582,7 +1582,8 @@ void mirror_start(const char *job_id, BlockDriverState 
*bs,
   MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
   BlockdevOnError on_source_error,
   BlockdevOnError on_target_error,
-  bool unmap, const char *filter_node_name, Error **errp)
+  bool unmap, const char *filter_node_name,
+  MirrorCopyMode copy_mode, Error **errp)
 {
 bool is_none_mode;
 BlockDriverState *base;
@@ -1597,7 +1598,7 @@ void mirror_start(const char *job_id, BlockDriverState 
*bs,
  speed, granularity, buf_size, backing_mode,
  on_source_error, on_target_error, unmap, NULL, NULL,
  _job_driver, is_none_mode, base, false,
- filter_node_name, true, errp);
+ filter_node_name, true, copy_mode, errp);
 }
 
 void commit_active_start(const char *job_id, BlockDriverState *bs,

[Qemu-devel] [PATCH v2 05/16] block/mirror: Convert to coroutines

2018-01-22 Thread Max Reitz
In order to talk to the source BDS (and maybe in the future to the
target BDS as well) directly, we need to convert our existing AIO
requests into coroutine I/O requests.

Signed-off-by: Max Reitz 
---
 block/mirror.c | 154 ++---
 1 file changed, 92 insertions(+), 62 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 4066788ee2..71a8e66850 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -80,6 +80,10 @@ typedef struct MirrorOp {
 QEMUIOVector qiov;
 int64_t offset;
 uint64_t bytes;
+
+/* The pointee is set by mirror_co_read(), mirror_co_zero(), and
+ * mirror_co_discard() before yielding for the first time */
+int64_t *bytes_handled;
 } MirrorOp;
 
 typedef enum MirrorMethod {
@@ -101,7 +105,7 @@ static BlockErrorAction mirror_error_action(MirrorBlockJob 
*s, bool read,
 }
 }
 
-static void mirror_iteration_done(MirrorOp *op, int ret)
+static void coroutine_fn mirror_iteration_done(MirrorOp *op, int ret)
 {
 MirrorBlockJob *s = op->s;
 struct iovec *iov;
@@ -138,9 +142,8 @@ static void mirror_iteration_done(MirrorOp *op, int ret)
 }
 }
 
-static void mirror_write_complete(void *opaque, int ret)
+static void coroutine_fn mirror_write_complete(MirrorOp *op, int ret)
 {
-MirrorOp *op = opaque;
 MirrorBlockJob *s = op->s;
 
 aio_context_acquire(blk_get_aio_context(s->common.blk));
@@ -157,9 +160,8 @@ static void mirror_write_complete(void *opaque, int ret)
 aio_context_release(blk_get_aio_context(s->common.blk));
 }
 
-static void mirror_read_complete(void *opaque, int ret)
+static void coroutine_fn mirror_read_complete(MirrorOp *op, int ret)
 {
-MirrorOp *op = opaque;
 MirrorBlockJob *s = op->s;
 
 aio_context_acquire(blk_get_aio_context(s->common.blk));
@@ -174,8 +176,11 @@ static void mirror_read_complete(void *opaque, int ret)
 
 mirror_iteration_done(op, ret);
 } else {
-blk_aio_pwritev(s->target, op->offset, >qiov,
-0, mirror_write_complete, op);
+int ret;
+
+ret = blk_co_pwritev(s->target, op->offset,
+ op->qiov.size, >qiov, 0);
+mirror_write_complete(op, ret);
 }
 aio_context_release(blk_get_aio_context(s->common.blk));
 }
@@ -232,60 +237,57 @@ static inline void mirror_wait_for_io(MirrorBlockJob *s)
 s->waiting_for_io = false;
 }
 
-/* Submit async read while handling COW.
- * Returns: The number of bytes copied after and including offset,
- *  excluding any bytes copied prior to offset due to alignment.
- *  This will be @bytes if no alignment is necessary, or
- *  (new_end - offset) if tail is rounded up or down due to
- *  alignment or buffer limit.
+/* Perform a mirror copy operation.
+ *
+ * *op->bytes_handled is set to the number of bytes copied after and
+ * including offset, excluding any bytes copied prior to offset due
+ * to alignment.  This will be op->bytes if no alignment is necessary,
+ * or (new_end - op->offset) if the tail is rounded up or down due to
+ * alignment or buffer limit.
  */
-static uint64_t mirror_do_read(MirrorBlockJob *s, int64_t offset,
-   uint64_t bytes)
+static void coroutine_fn mirror_co_read(void *opaque)
 {
+MirrorOp *op = opaque;
+MirrorBlockJob *s = op->s;
 BlockBackend *source = s->common.blk;
 int nb_chunks;
 uint64_t ret;
-MirrorOp *op;
 uint64_t max_bytes;
 
 max_bytes = s->granularity * s->max_iov;
 
 /* We can only handle as much as buf_size at a time. */
-bytes = MIN(s->buf_size, MIN(max_bytes, bytes));
-assert(bytes);
-assert(bytes < BDRV_REQUEST_MAX_BYTES);
-ret = bytes;
+op->bytes = MIN(s->buf_size, MIN(max_bytes, op->bytes));
+assert(op->bytes);
+assert(op->bytes < BDRV_REQUEST_MAX_BYTES);
+*op->bytes_handled = op->bytes;
 
 if (s->cow_bitmap) {
-ret += mirror_cow_align(s, , );
+*op->bytes_handled += mirror_cow_align(s, >offset, >bytes);
 }
-assert(bytes <= s->buf_size);
+/* Cannot exceed BDRV_REQUEST_MAX_BYTES + INT_MAX */
+assert(*op->bytes_handled <= UINT_MAX);
+assert(op->bytes <= s->buf_size);
 /* The offset is granularity-aligned because:
  * 1) Caller passes in aligned values;
  * 2) mirror_cow_align is used only when target cluster is larger. */
-assert(QEMU_IS_ALIGNED(offset, s->granularity));
+assert(QEMU_IS_ALIGNED(op->offset, s->granularity));
 /* The range is sector-aligned, since bdrv_getlength() rounds up. */
-assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
-nb_chunks = DIV_ROUND_UP(bytes, s->granularity);
+assert(QEMU_IS_ALIGNED(op->bytes, BDRV_SECTOR_SIZE));
+nb_chunks = DIV_ROUND_UP(op->bytes, s->granularity);
 
 while (s->buf_free_count < nb_chunks) {
-trace_mirror_yield_in_flight(s, offset, s->in_flight);
+trace_mirror_yield_in_flight(s, 

[Qemu-devel] [PATCH v2 13/16] block/mirror: Add MirrorBDSOpaque

2018-01-22 Thread Max Reitz
This will allow us to access the block job data when the mirror block
driver becomes more complex.

Signed-off-by: Max Reitz 
---
 block/mirror.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/block/mirror.c b/block/mirror.c
index bb46f3c4e9..c1987b0230 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -78,6 +78,10 @@ typedef struct MirrorBlockJob {
 bool initial_zeroing_ongoing;
 } MirrorBlockJob;
 
+typedef struct MirrorBDSOpaque {
+MirrorBlockJob *job;
+} MirrorBDSOpaque;
+
 struct MirrorOp {
 MirrorBlockJob *s;
 QEMUIOVector qiov;
@@ -607,6 +611,7 @@ static void mirror_exit(BlockJob *job, void *opaque)
 {
 MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
 MirrorExitData *data = opaque;
+MirrorBDSOpaque *bs_opaque = s->mirror_top_bs->opaque;
 AioContext *replace_aio_context = NULL;
 BlockDriverState *src = s->mirror_top_bs->backing->bs;
 BlockDriverState *target_bs = blk_bs(s->target);
@@ -699,6 +704,7 @@ static void mirror_exit(BlockJob *job, void *opaque)
 blk_set_perm(job->blk, 0, BLK_PERM_ALL, _abort);
 blk_insert_bs(job->blk, mirror_top_bs, _abort);
 
+bs_opaque->job = NULL;
 block_job_completed(>common, data->ret);
 
 g_free(data);
@@ -1232,6 +1238,7 @@ static void mirror_start_job(const char *job_id, 
BlockDriverState *bs,
  Error **errp)
 {
 MirrorBlockJob *s;
+MirrorBDSOpaque *bs_opaque;
 BlockDriverState *mirror_top_bs;
 bool target_graph_mod;
 bool target_is_backing;
@@ -1265,6 +1272,8 @@ static void mirror_start_job(const char *job_id, 
BlockDriverState *bs,
 mirror_top_bs->implicit = true;
 }
 mirror_top_bs->total_sectors = bs->total_sectors;
+bs_opaque = g_new0(MirrorBDSOpaque, 1);
+mirror_top_bs->opaque = bs_opaque;
 bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));
 
 /* bdrv_append takes ownership of the mirror_top_bs reference, need to keep
@@ -1289,6 +1298,8 @@ static void mirror_start_job(const char *job_id, 
BlockDriverState *bs,
 if (!s) {
 goto fail;
 }
+bs_opaque->job = s;
+
 /* The block job now has a reference to this node */
 bdrv_unref(mirror_top_bs);
 
@@ -1378,6 +1389,7 @@ fail:
 
 g_free(s->replaces);
 blk_unref(s->target);
+bs_opaque->job = NULL;
 block_job_early_fail(>common);
 }
 
-- 
2.14.3




[Qemu-devel] [PATCH v2 16/16] iotests: Add test for active mirroring

2018-01-22 Thread Max Reitz
Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/151 | 114 +
 tests/qemu-iotests/151.out |   5 ++
 tests/qemu-iotests/group   |   1 +
 3 files changed, 120 insertions(+)
 create mode 100755 tests/qemu-iotests/151
 create mode 100644 tests/qemu-iotests/151.out

diff --git a/tests/qemu-iotests/151 b/tests/qemu-iotests/151
new file mode 100755
index 00..5e064d62a2
--- /dev/null
+++ b/tests/qemu-iotests/151
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# Tests for active mirroring
+#
+# Copyright (C) 2017 Red Hat, Inc.
+#
+# 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 .
+#
+
+import os
+import iotests
+from iotests import qemu_img
+
+source_img = os.path.join(iotests.test_dir, 'source.' + iotests.imgfmt)
+target_img = os.path.join(iotests.test_dir, 'target.' + iotests.imgfmt)
+
+class TestActiveMirror(iotests.QMPTestCase):
+image_len = 128 * 1024 * 1024 # MB
+potential_writes_in_flight = True
+
+def setUp(self):
+qemu_img('create', '-f', iotests.imgfmt, source_img, '128M')
+qemu_img('create', '-f', iotests.imgfmt, target_img, '128M')
+
+blk_source = {'id': 'source',
+  'if': 'none',
+  'node-name': 'source-node',
+  'driver': iotests.imgfmt,
+  'file': {'driver': 'file',
+   'filename': source_img}}
+
+blk_target = {'node-name': 'target-node',
+  'driver': iotests.imgfmt,
+  'file': {'driver': 'file',
+   'filename': target_img}}
+
+self.vm = iotests.VM()
+self.vm.add_drive_raw(self.qmp_to_opts(blk_source))
+self.vm.add_blockdev(self.qmp_to_opts(blk_target))
+self.vm.add_device('virtio-blk,drive=source')
+self.vm.launch()
+
+def tearDown(self):
+self.vm.shutdown()
+
+if not self.potential_writes_in_flight:
+self.assertTrue(iotests.compare_images(source_img, target_img),
+'mirror target does not match source')
+
+os.remove(source_img)
+os.remove(target_img)
+
+def doActiveIO(self, sync_source_and_target):
+# Fill the source image
+self.vm.hmp_qemu_io('source',
+'write -P 1 0 %i' % self.image_len);
+
+# Start some background requests
+for offset in range(0, self.image_len, 1024 * 1024):
+self.vm.hmp_qemu_io('source', 'aio_write -P 2 %i 1M' % offset)
+
+# Start the block job
+result = self.vm.qmp('blockdev-mirror',
+ job_id='mirror',
+ filter_node_name='mirror-node',
+ device='source-node',
+ target='target-node',
+ sync='full',
+ copy_mode='write-blocking')
+self.assert_qmp(result, 'return', {})
+
+# Start some more requests
+for offset in range(0, self.image_len, 1024 * 1024):
+self.vm.hmp_qemu_io('source', 'aio_write -P 3 %i 1M' % offset)
+
+# Wait for the READY event
+self.wait_ready(drive='mirror')
+
+# Now start some final requests; all of these (which land on
+# the source) should be settled using the active mechanism.
+# The mirror code itself asserts that the source BDS's dirty
+# bitmap will stay clean between READY and COMPLETED.
+for offset in range(0, self.image_len, 1024 * 1024):
+self.vm.hmp_qemu_io('source', 'aio_write -P 4 %i 1M' % offset)
+
+if sync_source_and_target:
+# If source and target should be in sync after the mirror,
+# we have to flush before completion
+self.vm.hmp_qemu_io('source', 'aio_flush')
+self.potential_writes_in_flight = False
+
+self.complete_and_wait(drive='mirror', wait_ready=False)
+
+def testActiveIO(self):
+self.doActiveIO(False)
+
+def testActiveIOFlushed(self):
+self.doActiveIO(True)
+
+
+
+if __name__ == '__main__':
+iotests.main(supported_fmts=['qcow2', 'raw'])
diff --git a/tests/qemu-iotests/151.out b/tests/qemu-iotests/151.out
new file mode 100644
index 00..fbc63e62f8
--- /dev/null
+++ b/tests/qemu-iotests/151.out
@@ 

[Qemu-devel] [PATCH v2 11/16] block/dirty-bitmap: Add bdrv_dirty_iter_next_area

2018-01-22 Thread Max Reitz
This new function allows to look for a consecutively dirty area in a
dirty bitmap.

Signed-off-by: Max Reitz 
---
 include/block/dirty-bitmap.h |  2 ++
 block/dirty-bitmap.c | 51 
 2 files changed, 53 insertions(+)

diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index a591c27213..35f3ccc44c 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -79,6 +79,8 @@ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
 void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
 int64_t offset, int64_t bytes);
 int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter);
+bool bdrv_dirty_iter_next_area(BdrvDirtyBitmapIter *iter, uint64_t max_offset,
+   uint64_t *offset, int *bytes);
 void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t offset);
 int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap);
 int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap);
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 50564fa1e2..484b5dda43 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -501,6 +501,57 @@ int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
 return hbitmap_iter_next(>hbi, true);
 }
 
+/**
+ * Return the next consecutively dirty area in the dirty bitmap
+ * belonging to the given iterator @iter.
+ *
+ * @max_offset: Maximum value that may be returned for
+ *  *offset + *bytes
+ * @offset: Will contain the start offset of the next dirty area
+ * @bytes:  Will contain the length of the next dirty area
+ *
+ * Returns: True if a dirty area could be found before max_offset
+ *  (which means that *offset and *bytes then contain valid
+ *  values), false otherwise.
+ */
+bool bdrv_dirty_iter_next_area(BdrvDirtyBitmapIter *iter, uint64_t max_offset,
+   uint64_t *offset, int *bytes)
+{
+uint32_t granularity = bdrv_dirty_bitmap_granularity(iter->bitmap);
+uint64_t gran_max_offset;
+int64_t ret;
+int size;
+
+if (max_offset == iter->bitmap->size) {
+/* If max_offset points to the image end, round it up by the
+ * bitmap granularity */
+gran_max_offset = ROUND_UP(max_offset, granularity);
+} else {
+gran_max_offset = max_offset;
+}
+
+ret = hbitmap_iter_next(>hbi, false);
+if (ret < 0 || ret + granularity > gran_max_offset) {
+return false;
+}
+
+*offset = ret;
+size = 0;
+
+assert(granularity <= INT_MAX);
+
+do {
+/* Advance iterator */
+ret = hbitmap_iter_next(>hbi, true);
+size += granularity;
+} while (ret + granularity <= gran_max_offset &&
+ hbitmap_iter_next(>hbi, false) == ret + granularity &&
+ size <= INT_MAX - granularity);
+
+*bytes = MIN(size, max_offset - *offset);
+return true;
+}
+
 /* Called within bdrv_dirty_bitmap_lock..unlock */
 void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
   int64_t offset, int64_t bytes)
-- 
2.14.3




[Qemu-devel] [PATCH v2 04/16] block/mirror: Pull out mirror_perform()

2018-01-22 Thread Max Reitz
When converting mirror's I/O to coroutines, we are going to need a point
where these coroutines are created.  mirror_perform() is going to be
that point.

Signed-off-by: Max Reitz 
Reviewed-by: Fam Zheng 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 block/mirror.c | 51 +--
 1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index c9badc1203..4066788ee2 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -82,6 +82,12 @@ typedef struct MirrorOp {
 uint64_t bytes;
 } MirrorOp;
 
+typedef enum MirrorMethod {
+MIRROR_METHOD_COPY,
+MIRROR_METHOD_ZERO,
+MIRROR_METHOD_DISCARD,
+} MirrorMethod;
+
 static BlockErrorAction mirror_error_action(MirrorBlockJob *s, bool read,
 int error)
 {
@@ -321,6 +327,22 @@ static void mirror_do_zero_or_discard(MirrorBlockJob *s,
 }
 }
 
+static unsigned mirror_perform(MirrorBlockJob *s, int64_t offset,
+   unsigned bytes, MirrorMethod mirror_method)
+{
+switch (mirror_method) {
+case MIRROR_METHOD_COPY:
+return mirror_do_read(s, offset, bytes);
+case MIRROR_METHOD_ZERO:
+case MIRROR_METHOD_DISCARD:
+mirror_do_zero_or_discard(s, offset, bytes,
+  mirror_method == MIRROR_METHOD_DISCARD);
+return bytes;
+default:
+abort();
+}
+}
+
 static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
 {
 BlockDriverState *source = s->source;
@@ -387,11 +409,7 @@ static uint64_t coroutine_fn 
mirror_iteration(MirrorBlockJob *s)
 int ret;
 int64_t io_bytes;
 int64_t io_bytes_acct;
-enum MirrorMethod {
-MIRROR_METHOD_COPY,
-MIRROR_METHOD_ZERO,
-MIRROR_METHOD_DISCARD
-} mirror_method = MIRROR_METHOD_COPY;
+MirrorMethod mirror_method = MIRROR_METHOD_COPY;
 
 assert(!(offset % s->granularity));
 ret = bdrv_block_status_above(source, NULL, offset,
@@ -429,22 +447,11 @@ static uint64_t coroutine_fn 
mirror_iteration(MirrorBlockJob *s)
 }
 
 io_bytes = mirror_clip_bytes(s, offset, io_bytes);
-switch (mirror_method) {
-case MIRROR_METHOD_COPY:
-io_bytes = io_bytes_acct = mirror_do_read(s, offset, io_bytes);
-break;
-case MIRROR_METHOD_ZERO:
-case MIRROR_METHOD_DISCARD:
-mirror_do_zero_or_discard(s, offset, io_bytes,
-  mirror_method == MIRROR_METHOD_DISCARD);
-if (write_zeroes_ok) {
-io_bytes_acct = 0;
-} else {
-io_bytes_acct = io_bytes;
-}
-break;
-default:
-abort();
+io_bytes = mirror_perform(s, offset, io_bytes, mirror_method);
+if (mirror_method != MIRROR_METHOD_COPY && write_zeroes_ok) {
+io_bytes_acct = 0;
+} else {
+io_bytes_acct = io_bytes;
 }
 assert(io_bytes);
 offset += io_bytes;
@@ -638,7 +645,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
 continue;
 }
 
-mirror_do_zero_or_discard(s, offset, bytes, false);
+mirror_perform(s, offset, bytes, MIRROR_METHOD_ZERO);
 offset += bytes;
 }
 
-- 
2.14.3




[Qemu-devel] [PATCH v2 06/16] block/mirror: Use CoQueue to wait on in-flight ops

2018-01-22 Thread Max Reitz
Attach a CoQueue to each in-flight operation so if we need to wait for
any we can use it to wait instead of just blindly yielding and hoping
for some operation to wake us.

A later patch will use this infrastructure to allow requests accessing
the same area of the virtual disk to specifically wait for each other.

Signed-off-by: Max Reitz 
---
 block/mirror.c | 34 +++---
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 71a8e66850..fdd6385766 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -13,6 +13,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/cutils.h"
+#include "qemu/coroutine.h"
 #include "trace.h"
 #include "block/blockjob_int.h"
 #include "block/block_int.h"
@@ -34,6 +35,8 @@ typedef struct MirrorBuffer {
 QSIMPLEQ_ENTRY(MirrorBuffer) next;
 } MirrorBuffer;
 
+typedef struct MirrorOp MirrorOp;
+
 typedef struct MirrorBlockJob {
 BlockJob common;
 RateLimit limit;
@@ -67,15 +70,15 @@ typedef struct MirrorBlockJob {
 unsigned long *in_flight_bitmap;
 int in_flight;
 int64_t bytes_in_flight;
+QTAILQ_HEAD(MirrorOpList, MirrorOp) ops_in_flight;
 int ret;
 bool unmap;
-bool waiting_for_io;
 int target_cluster_size;
 int max_iov;
 bool initial_zeroing_ongoing;
 } MirrorBlockJob;
 
-typedef struct MirrorOp {
+struct MirrorOp {
 MirrorBlockJob *s;
 QEMUIOVector qiov;
 int64_t offset;
@@ -84,7 +87,11 @@ typedef struct MirrorOp {
 /* The pointee is set by mirror_co_read(), mirror_co_zero(), and
  * mirror_co_discard() before yielding for the first time */
 int64_t *bytes_handled;
-} MirrorOp;
+
+CoQueue waiting_requests;
+
+QTAILQ_ENTRY(MirrorOp) next;
+};
 
 typedef enum MirrorMethod {
 MIRROR_METHOD_COPY,
@@ -125,7 +132,9 @@ static void coroutine_fn mirror_iteration_done(MirrorOp 
*op, int ret)
 
 chunk_num = op->offset / s->granularity;
 nb_chunks = DIV_ROUND_UP(op->bytes, s->granularity);
+
 bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks);
+QTAILQ_REMOVE(>ops_in_flight, op, next);
 if (ret >= 0) {
 if (s->cow_bitmap) {
 bitmap_set(s->cow_bitmap, chunk_num, nb_chunks);
@@ -135,11 +144,9 @@ static void coroutine_fn mirror_iteration_done(MirrorOp 
*op, int ret)
 }
 }
 qemu_iovec_destroy(>qiov);
-g_free(op);
 
-if (s->waiting_for_io) {
-qemu_coroutine_enter(s->common.co);
-}
+qemu_co_queue_restart_all(>waiting_requests);
+g_free(op);
 }
 
 static void coroutine_fn mirror_write_complete(MirrorOp *op, int ret)
@@ -231,10 +238,11 @@ static int mirror_cow_align(MirrorBlockJob *s, int64_t 
*offset,
 
 static inline void mirror_wait_for_io(MirrorBlockJob *s)
 {
-assert(!s->waiting_for_io);
-s->waiting_for_io = true;
-qemu_coroutine_yield();
-s->waiting_for_io = false;
+MirrorOp *op;
+
+op = QTAILQ_FIRST(>ops_in_flight);
+assert(op);
+qemu_co_queue_wait(>waiting_requests, NULL);
 }
 
 /* Perform a mirror copy operation.
@@ -344,6 +352,7 @@ static unsigned mirror_perform(MirrorBlockJob *s, int64_t 
offset,
 .bytes  = bytes,
 .bytes_handled  = _handled,
 };
+qemu_co_queue_init(>waiting_requests);
 
 switch (mirror_method) {
 case MIRROR_METHOD_COPY:
@@ -359,6 +368,7 @@ static unsigned mirror_perform(MirrorBlockJob *s, int64_t 
offset,
 abort();
 }
 
+QTAILQ_INSERT_TAIL(>ops_in_flight, op, next);
 qemu_coroutine_enter(co);
 /* At this point, ownership of op has been moved to the coroutine
  * and the object may already be freed */
@@ -1287,6 +1297,8 @@ static void mirror_start_job(const char *job_id, 
BlockDriverState *bs,
 }
 }
 
+QTAILQ_INIT(>ops_in_flight);
+
 trace_mirror_start(bs, s, opaque);
 block_job_start(>common);
 return;
-- 
2.14.3




  1   2   3   4   >