All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: famz@redhat.com, mst@redhat.com, armbru@redhat.com,
	stefanha@redhat.com, pbonzini@redhat.com,
	John Snow <jsnow@redhat.com>
Subject: [Qemu-devel] [PATCH v2 08/19] libqos/ahci: Add cmd response sanity check helpers
Date: Tue,  3 Feb 2015 16:46:28 -0500	[thread overview]
Message-ID: <1422999999-25868-9-git-send-email-jsnow@redhat.com> (raw)
In-Reply-To: <1422999999-25868-1-git-send-email-jsnow@redhat.com>

This patch adds a few helpers to help sanity-check the response of the
AHCI device after a command.

ahci_d2h_check_sanity inspects the D2H Register FIS,
ahci_pio_check_sanity inspects the PIO Setup FIS, and
ahci_cmd_check_sanity inspects the command header.

To support the PIO sanity check, a new structure is added for the
PIO Setup FIS type. Existing FIS types (H2D and D2H) have had their
members renamed slightly to condense reserved members into fewer
fields; and LBA fields are now represented by arrays of 8 byte chunks
instead of independent variables.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/ahci-test.c   | 29 ++++------------------------
 tests/libqos/ahci.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/libqos/ahci.h | 54 ++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 88 insertions(+), 42 deletions(-)

diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index 4cc7e21..b67d935 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -657,12 +657,10 @@ static void ahci_test_port_spec(AHCIQState *ahci, uint8_t port)
  */
 static void ahci_test_identify(AHCIQState *ahci)
 {
-    RegD2HFIS *d2h = g_malloc0(0x20);
-    RegD2HFIS *pio = g_malloc0(0x20);
     RegH2DFIS fis;
     AHCICommandHeader cmd;
     PRD prd;
-    uint32_t reg, data_ptr;
+    uint32_t data_ptr;
     uint16_t buff[256];
     unsigned i;
     int rc;
@@ -752,27 +750,11 @@ static void ahci_test_identify(AHCIQState *ahci)
     /* BUG: we expect AHCI_PX_IS_DPS to be set. */
     ahci_port_check_interrupts(ahci, i, AHCI_PX_IS_DHRS | AHCI_PX_IS_PSS);
     ahci_port_check_nonbusy(ahci, i, cx);
-
     /* Investigate the CMD, assert that we read 512 bytes */
-    ahci_get_command_header(ahci, i, cx, &cmd);
-    g_assert_cmphex(512, ==, cmd.prdbc);
-
+    ahci_port_check_cmd_sanity(ahci, i, cx, 512);
     /* Investigate FIS responses */
-    memread(ahci->port[i].fb + 0x20, pio, 0x20);
-    memread(ahci->port[i].fb + 0x40, d2h, 0x20);
-    g_assert_cmphex(pio->fis_type, ==, 0x5f);
-    g_assert_cmphex(d2h->fis_type, ==, 0x34);
-    g_assert_cmphex(pio->flags, ==, d2h->flags);
-    g_assert_cmphex(pio->status, ==, d2h->status);
-    g_assert_cmphex(pio->error, ==, d2h->error);
-
-    reg = ahci_px_rreg(ahci, i, AHCI_PX_TFD);
-    g_assert_cmphex((reg & AHCI_PX_TFD_ERR), ==, pio->error);
-    g_assert_cmphex((reg & AHCI_PX_TFD_STS), ==, pio->status);
-    /* The PIO Setup FIS contains a "bytes read" field, which is a
-     * 16-bit value. The Physical Region Descriptor Byte Count is
-     * 32-bit, but for small transfers using one PRD, it should match. */
-    g_assert_cmphex(le16_to_cpu(pio->res4), ==, cmd.prdbc);
+    ahci_port_check_d2h_sanity(ahci, i, cx);
+    ahci_port_check_pio_sanity(ahci, i, cx, 512);
 
     /* Last, but not least: Investigate the IDENTIFY response data. */
     memread(data_ptr, &buff, 512);
@@ -789,9 +771,6 @@ static void ahci_test_identify(AHCIQState *ahci)
     string_bswap16(&buff[23], 8);
     rc = memcmp(&buff[23], "version ", 8);
     g_assert_cmphex(rc, ==, 0);
-
-    g_free(d2h);
-    g_free(pio);
 }
 
 /******************************************************************************/
diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
index c9af691..ec72627 100644
--- a/tests/libqos/ahci.c
+++ b/tests/libqos/ahci.c
@@ -365,6 +365,53 @@ void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t px, uint8_t cx)
     ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_DRQ);
 }
 
+void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t px, uint8_t cx)
+{
+    RegD2HFIS *d2h = g_malloc0(0x20);
+    uint32_t reg;
+
+    memread(ahci->port[px].fb + 0x40, d2h, 0x20);
+    g_assert_cmphex(d2h->fis_type, ==, 0x34);
+
+    reg = ahci_px_rreg(ahci, px, AHCI_PX_TFD);
+    g_assert_cmphex((reg & AHCI_PX_TFD_ERR) >> 8, ==, d2h->error);
+    g_assert_cmphex((reg & AHCI_PX_TFD_STS), ==, d2h->status);
+
+    g_free(d2h);
+}
+
+void ahci_port_check_pio_sanity(AHCIQState *ahci, uint8_t px,
+                                uint8_t cx, size_t buffsize)
+{
+    PIOSetupFIS *pio = g_malloc0(0x20);
+
+    /* We cannot check the Status or E_Status registers, becuase
+     * the status may have again changed between the PIO Setup FIS
+     * and the conclusion of the command with the D2H Register FIS. */
+    memread(ahci->port[px].fb + 0x20, pio, 0x20);
+    g_assert_cmphex(pio->fis_type, ==, 0x5f);
+
+    /* BUG: PIO Setup FIS as utilized by QEMU tries to fit the entire
+     * transfer size in a uint16_t field. The maximum transfer size can
+     * eclipse this; the field is meant to convey the size of data per
+     * each Data FIS, not the entire operation as a whole. For now,
+     * we will sanity check the broken case where applicable. */
+    if (buffsize <= UINT16_MAX) {
+        g_assert_cmphex(le16_to_cpu(pio->tx_count), ==, buffsize);
+    }
+
+    g_free(pio);
+}
+
+void ahci_port_check_cmd_sanity(AHCIQState *ahci, uint8_t px,
+                                uint8_t cx, size_t buffsize)
+{
+    AHCICommandHeader cmd;
+
+    ahci_get_command_header(ahci, px, cx, &cmd);
+    g_assert_cmphex(buffsize, ==, cmd.prdbc);
+}
+
 /* Get the #cx'th command of port #px. */
 void ahci_get_command_header(AHCIQState *ahci, uint8_t px,
                              uint8_t cx, AHCICommandHeader *cmd)
diff --git a/tests/libqos/ahci.h b/tests/libqos/ahci.h
index 7c504a5..3b4e1ef 100644
--- a/tests/libqos/ahci.h
+++ b/tests/libqos/ahci.h
@@ -283,25 +283,44 @@ typedef struct RegD2HFIS {
     uint8_t status;
     uint8_t error;
     /* DW1 */
-    uint8_t lba_low;
-    uint8_t lba_mid;
-    uint8_t lba_high;
+    uint8_t lba_lo[3];
     uint8_t device;
     /* DW2 */
-    uint8_t lba3;
-    uint8_t lba4;
-    uint8_t lba5;
-    uint8_t res1;
+    uint8_t lba_hi[3];
+    uint8_t res0;
     /* DW3 */
     uint16_t count;
-    uint8_t res2;
-    uint8_t res3;
+    uint16_t res1;
     /* DW4 */
-    uint16_t res4;
-    uint16_t res5;
+    uint32_t res2;
 } __attribute__((__packed__)) RegD2HFIS;
 
 /**
+ * Register device-to-host FIS structure;
+ * PIO Setup variety.
+ */
+typedef struct PIOSetupFIS {
+    /* DW0 */
+    uint8_t fis_type;
+    uint8_t flags;
+    uint8_t status;
+    uint8_t error;
+    /* DW1 */
+    uint8_t lba_lo[3];
+    uint8_t device;
+    /* DW2 */
+    uint8_t lba_hi[3];
+    uint8_t res0;
+    /* DW3 */
+    uint16_t count;
+    uint8_t res1;
+    uint8_t e_status;
+    /* DW4 */
+    uint16_t tx_count;
+    uint16_t res2;
+} __attribute__((__packed__)) PIOSetupFIS;
+
+/**
  * Register host-to-device FIS structure.
  */
 typedef struct RegH2DFIS {
@@ -311,14 +330,10 @@ typedef struct RegH2DFIS {
     uint8_t command;
     uint8_t feature_low;
     /* DW1 */
-    uint8_t lba_low;
-    uint8_t lba_mid;
-    uint8_t lba_high;
+    uint8_t lba_lo[3];
     uint8_t device;
     /* DW2 */
-    uint8_t lba3;
-    uint8_t lba4;
-    uint8_t lba5;
+    uint8_t lba_hi[3];
     uint8_t feature_high;
     /* DW3 */
     uint16_t count;
@@ -437,6 +452,11 @@ void ahci_port_check_error(AHCIQState *ahci, uint8_t px);
 void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t px,
                                 uint32_t intr_mask);
 void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t px, uint8_t cx);
+void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t px, uint8_t cx);
+void ahci_port_check_pio_sanity(AHCIQState *ahci, uint8_t px,
+                                uint8_t cx, size_t buffsize);
+void ahci_port_check_cmd_sanity(AHCIQState *ahci, uint8_t px,
+                                uint8_t cx, size_t buffsize);
 void ahci_get_command_header(AHCIQState *ahci, uint8_t px,
                              uint8_t cx, AHCICommandHeader *cmd);
 void ahci_set_command_header(AHCIQState *ahci, uint8_t px,
-- 
1.9.3

  parent reply	other threads:[~2015-02-03 21:46 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-03 21:46 [Qemu-devel] [PATCH v2 00/19] qtest/ahci: add dma test John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 01/19] libqos/ahci: Add ahci_port_select helper John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 02/19] libqos/ahci: Add ahci_port_clear helper John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 03/19] qtest/ahci: rename 'Command' to 'CommandHeader' John Snow
2015-02-05 13:06   ` Stefan Hajnoczi
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 04/19] libqos/ahci: Add command header helpers John Snow
2015-02-05 13:17   ` Stefan Hajnoczi
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 05/19] libqos/ahci: Add ahci_port_check_error helper John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 06/19] libqos/ahci: Add ahci_port_check_interrupts helper John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 07/19] libqos/ahci: Add port_check_nonbusy helper John Snow
2015-02-03 21:46 ` John Snow [this message]
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 09/19] qtest/ahci: Demagic ahci tests John Snow
2015-02-05 13:22   ` Stefan Hajnoczi
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 10/19] qtest/ahci: add ahci_write_fis John Snow
2015-02-05 13:29   ` Stefan Hajnoczi
2015-02-05 16:19     ` John Snow
2015-02-06 10:41       ` Stefan Hajnoczi
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 11/19] libqos/ahci: Add ide cmd properties John Snow
2015-02-05 13:43   ` Stefan Hajnoczi
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 12/19] libqos/ahci: add ahci command functions John Snow
2015-02-05 13:44   ` Stefan Hajnoczi
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 13/19] libqos/ahci: add ahci command verify John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 14/19] libqos/ahci: add ahci command size setters John Snow
2015-02-05 13:45   ` Stefan Hajnoczi
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 15/19] libqos/ahci: Add ahci_guest_io John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 16/19] libqos/ahci: add ahci_io John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 17/19] libqos/ahci: Add ahci_clean_mem John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 18/19] qtest/ahci: Assert sector size in identify test John Snow
2015-02-03 21:46 ` [Qemu-devel] [PATCH v2 19/19] qtest/ahci: Adding simple dma read-write test John Snow
2015-02-05 13:41   ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1422999999-25868-9-git-send-email-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=armbru@redhat.com \
    --cc=famz@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.