All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL for-2.3 0/2] Ide patches
@ 2015-03-27 22:27 John Snow
  2015-03-27 22:27 ` John Snow
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: John Snow @ 2015-03-27 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jsnow

The following changes since commit b27e767e8c8d56cb7c9d0b78eadd89521bdf836c:

  Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request' into staging (2015-03-27 12:12:27 +0000)

are available in the git repository at:

  https://github.com/jnsnow/qemu.git tags/ide-pull-request

for you to fetch changes up to fc3d8e1138cd0c843d6fd75272633a31be6554ef:

  AHCI: Protect cmd register (2015-03-27 15:48:11 -0400)

----------------------------------------------------------------

----------------------------------------------------------------

John Snow (2):
  AHCI: Do not (re)map FB/CLB buffers while not running
  AHCI: Protect cmd register

 hw/ide/ahci.c | 76 +++++++++++++++++++++++++++++++++++++++++++++--------------
 hw/ide/ahci.h |  2 ++
 2 files changed, 60 insertions(+), 18 deletions(-)

-- 
2.1.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PULL for-2.3 0/2] Ide patches
  2015-03-27 22:27 [Qemu-devel] [PULL for-2.3 0/2] Ide patches John Snow
@ 2015-03-27 22:27 ` John Snow
  2015-03-29 13:16   ` Peter Maydell
  2015-03-27 22:27 ` [Qemu-devel] [PULL for-2.3 1/2] AHCI: Do not (re)map FB/CLB buffers while not running John Snow
  2015-03-27 22:27 ` [Qemu-devel] [PULL for-2.3 2/2] AHCI: Protect cmd register John Snow
  2 siblings, 1 reply; 5+ messages in thread
From: John Snow @ 2015-03-27 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jsnow

The following changes since commit b27e767e8c8d56cb7c9d0b78eadd89521bdf836c:

  Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request' into staging (2015-03-27 12:12:27 +0000)

are available in the git repository at:

  https://github.com/jnsnow/qemu.git tags/ide-pull-request

for you to fetch changes up to fc3d8e1138cd0c843d6fd75272633a31be6554ef:

  AHCI: Protect cmd register (2015-03-27 15:48:11 -0400)

----------------------------------------------------------------

----------------------------------------------------------------

John Snow (2):
  AHCI: Do not (re)map FB/CLB buffers while not running
  AHCI: Protect cmd register

 hw/ide/ahci.c | 76 +++++++++++++++++++++++++++++++++++++++++++++--------------
 hw/ide/ahci.h |  2 ++
 2 files changed, 60 insertions(+), 18 deletions(-)

-- 
2.1.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PULL for-2.3 1/2] AHCI: Do not (re)map FB/CLB buffers while not running
  2015-03-27 22:27 [Qemu-devel] [PULL for-2.3 0/2] Ide patches John Snow
  2015-03-27 22:27 ` John Snow
@ 2015-03-27 22:27 ` John Snow
  2015-03-27 22:27 ` [Qemu-devel] [PULL for-2.3 2/2] AHCI: Protect cmd register John Snow
  2 siblings, 0 replies; 5+ messages in thread
From: John Snow @ 2015-03-27 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jsnow

The FIS Receive Buffer and Command List Buffer pointers
should not be edited while the FIS receive engine or
Command Receive engines are running.

Currently, we attempt to re-map the buffers every time they
are adjusted, but while the AHCI engines are off, these registers
may contain stale values, so we should not attempt to re-map these
values until the engines are reactivated.

Reported-by: Jordan Hargrave <jharg93@gmail.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 1426283454-15590-2-git-send-email-jsnow@redhat.com
---
 hw/ide/ahci.c | 50 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 7a223be..4ccfcf3 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -51,6 +51,8 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis);
 static void ahci_init_d2h(AHCIDevice *ad);
 static int ahci_dma_prepare_buf(IDEDMA *dma, int is_write);
 static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes);
+static bool ahci_map_clb_address(AHCIDevice *ad);
+static bool ahci_map_fis_address(AHCIDevice *ad);
 
 
 static uint32_t  ahci_port_read(AHCIState *s, int port, int offset)
@@ -202,25 +204,15 @@ static void  ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
     switch (offset) {
         case PORT_LST_ADDR:
             pr->lst_addr = val;
-            map_page(s->as, &s->dev[port].lst,
-                     ((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024);
-            s->dev[port].cur_cmd = NULL;
             break;
         case PORT_LST_ADDR_HI:
             pr->lst_addr_hi = val;
-            map_page(s->as, &s->dev[port].lst,
-                     ((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024);
-            s->dev[port].cur_cmd = NULL;
             break;
         case PORT_FIS_ADDR:
             pr->fis_addr = val;
-            map_page(s->as, &s->dev[port].res_fis,
-                     ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
             break;
         case PORT_FIS_ADDR_HI:
             pr->fis_addr_hi = val;
-            map_page(s->as, &s->dev[port].res_fis,
-                     ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
             break;
         case PORT_IRQ_STAT:
             pr->irq_stat &= ~val;
@@ -234,11 +226,21 @@ static void  ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
             pr->cmd = val & ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON);
 
             if (pr->cmd & PORT_CMD_START) {
-                pr->cmd |= PORT_CMD_LIST_ON;
+                if (ahci_map_clb_address(&s->dev[port])) {
+                    pr->cmd |= PORT_CMD_LIST_ON;
+                } else {
+                    error_report("AHCI: Failed to start DMA engine: "
+                                 "bad command list buffer address");
+                }
             }
 
             if (pr->cmd & PORT_CMD_FIS_RX) {
-                pr->cmd |= PORT_CMD_FIS_ON;
+                if (ahci_map_fis_address(&s->dev[port])) {
+                    pr->cmd |= PORT_CMD_FIS_ON;
+                } else {
+                    error_report("AHCI: Failed to start FIS receive engine: "
+                                 "bad FIS receive buffer address");
+                }
             }
 
             /* XXX usually the FIS would be pending on the bus here and
@@ -565,6 +567,23 @@ static void debug_print_fis(uint8_t *fis, int cmd_len)
 #endif
 }
 
+static bool ahci_map_fis_address(AHCIDevice *ad)
+{
+    AHCIPortRegs *pr = &ad->port_regs;
+    map_page(ad->hba->as, &ad->res_fis,
+             ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
+    return ad->res_fis != NULL;
+}
+
+static bool ahci_map_clb_address(AHCIDevice *ad)
+{
+    AHCIPortRegs *pr = &ad->port_regs;
+    ad->cur_cmd = NULL;
+    map_page(ad->hba->as, &ad->lst,
+             ((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024);
+    return ad->lst != NULL;
+}
+
 static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished)
 {
     AHCIDevice *ad = &s->dev[port];
@@ -1360,12 +1379,9 @@ static int ahci_state_post_load(void *opaque, int version_id)
 
     for (i = 0; i < s->ports; i++) {
         ad = &s->dev[i];
-        AHCIPortRegs *pr = &ad->port_regs;
 
-        map_page(s->as, &ad->lst,
-                 ((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024);
-        map_page(s->as, &ad->res_fis,
-                 ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
+        ahci_map_clb_address(ad);
+        ahci_map_fis_address(ad);
         /*
          * If an error is present, ad->busy_slot will be valid and not -1.
          * In this case, an operation is waiting to resume and will re-check
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PULL for-2.3 2/2] AHCI: Protect cmd register
  2015-03-27 22:27 [Qemu-devel] [PULL for-2.3 0/2] Ide patches John Snow
  2015-03-27 22:27 ` John Snow
  2015-03-27 22:27 ` [Qemu-devel] [PULL for-2.3 1/2] AHCI: Do not (re)map FB/CLB buffers while not running John Snow
@ 2015-03-27 22:27 ` John Snow
  2 siblings, 0 replies; 5+ messages in thread
From: John Snow @ 2015-03-27 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jsnow

Many bits in the CMD register are supposed to be strictly read-only.
We should not be deleting them on every write.

As a side-effect: pay explicit attention to when a guest marks off
the FIS Receive or Start bits, and disable the status bits ourselves,
instead of letting them implicitly fall off.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 1426283454-15590-3-git-send-email-jsnow@redhat.com
---
 hw/ide/ahci.c | 26 +++++++++++++++++++++++++-
 hw/ide/ahci.h |  2 ++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 4ccfcf3..833fd45 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -53,6 +53,8 @@ static int ahci_dma_prepare_buf(IDEDMA *dma, int is_write);
 static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes);
 static bool ahci_map_clb_address(AHCIDevice *ad);
 static bool ahci_map_fis_address(AHCIDevice *ad);
+static void ahci_unmap_clb_address(AHCIDevice *ad);
+static void ahci_unmap_fis_address(AHCIDevice *ad);
 
 
 static uint32_t  ahci_port_read(AHCIState *s, int port, int offset)
@@ -223,7 +225,9 @@ static void  ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
             ahci_check_irq(s);
             break;
         case PORT_CMD:
-            pr->cmd = val & ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON);
+            /* Block any Read-only fields from being set;
+             * including LIST_ON and FIS_ON. */
+            pr->cmd = (pr->cmd & PORT_CMD_RO_MASK) | (val & ~PORT_CMD_RO_MASK);
 
             if (pr->cmd & PORT_CMD_START) {
                 if (ahci_map_clb_address(&s->dev[port])) {
@@ -232,6 +236,9 @@ static void  ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
                     error_report("AHCI: Failed to start DMA engine: "
                                  "bad command list buffer address");
                 }
+            } else if (pr->cmd & PORT_CMD_LIST_ON) {
+                ahci_unmap_clb_address(&s->dev[port]);
+                pr->cmd = pr->cmd & ~(PORT_CMD_LIST_ON);
             }
 
             if (pr->cmd & PORT_CMD_FIS_RX) {
@@ -241,6 +248,9 @@ static void  ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
                     error_report("AHCI: Failed to start FIS receive engine: "
                                  "bad FIS receive buffer address");
                 }
+            } else if (pr->cmd & PORT_CMD_FIS_ON) {
+                ahci_unmap_fis_address(&s->dev[port]);
+                pr->cmd = pr->cmd & ~(PORT_CMD_FIS_ON);
             }
 
             /* XXX usually the FIS would be pending on the bus here and
@@ -575,6 +585,13 @@ static bool ahci_map_fis_address(AHCIDevice *ad)
     return ad->res_fis != NULL;
 }
 
+static void ahci_unmap_fis_address(AHCIDevice *ad)
+{
+    dma_memory_unmap(ad->hba->as, ad->res_fis, 256,
+                     DMA_DIRECTION_FROM_DEVICE, 256);
+    ad->res_fis = NULL;
+}
+
 static bool ahci_map_clb_address(AHCIDevice *ad)
 {
     AHCIPortRegs *pr = &ad->port_regs;
@@ -584,6 +601,13 @@ static bool ahci_map_clb_address(AHCIDevice *ad)
     return ad->lst != NULL;
 }
 
+static void ahci_unmap_clb_address(AHCIDevice *ad)
+{
+    dma_memory_unmap(ad->hba->as, ad->lst, 1024,
+                     DMA_DIRECTION_FROM_DEVICE, 1024);
+    ad->lst = NULL;
+}
+
 static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished)
 {
     AHCIDevice *ad = &s->dev[port];
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 99aa0c9..501c002 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -132,6 +132,8 @@
 #define PORT_CMD_ICC_PARTIAL      (0x2 << 28) /* Put i/f in partial state */
 #define PORT_CMD_ICC_SLUMBER      (0x6 << 28) /* Put i/f in slumber state */
 
+#define PORT_CMD_RO_MASK          0x007dffe0 /* Which CMD bits are read only? */
+
 /* ap->flags bits */
 #define AHCI_FLAG_NO_NCQ                  (1 << 24)
 #define AHCI_FLAG_IGN_IRQ_IF_ERR          (1 << 25) /* ignore IRQ_IF_ERR */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PULL for-2.3 0/2] Ide patches
  2015-03-27 22:27 ` John Snow
@ 2015-03-29 13:16   ` Peter Maydell
  0 siblings, 0 replies; 5+ messages in thread
From: Peter Maydell @ 2015-03-29 13:16 UTC (permalink / raw)
  To: John Snow; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 701 bytes --]

On Friday, 27 March 2015, John Snow <jsnow@redhat.com> wrote:

> The following changes since commit
> b27e767e8c8d56cb7c9d0b78eadd89521bdf836c:
>
>   Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request'
> into staging (2015-03-27 12:12:27 +0000)
>
> are available in the git repository at:
>
>   https://github.com/jnsnow/qemu.git tags/ide-pull-request
>
> for you to fetch changes up to fc3d8e1138cd0c843d6fd75272633a31be6554ef:
>
>   AHCI: Protect cmd register (2015-03-27 15:48:11 -0400)
>
>
Applied, thanks.

--PMM



-- 
12345678901234567890123456789012345678901234567890123456789012345678901234567890
         1         2         3         4         5         6         7
    8

[-- Attachment #2: Type: text/html, Size: 1097 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-03-29 13:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-27 22:27 [Qemu-devel] [PULL for-2.3 0/2] Ide patches John Snow
2015-03-27 22:27 ` John Snow
2015-03-29 13:16   ` Peter Maydell
2015-03-27 22:27 ` [Qemu-devel] [PULL for-2.3 1/2] AHCI: Do not (re)map FB/CLB buffers while not running John Snow
2015-03-27 22:27 ` [Qemu-devel] [PULL for-2.3 2/2] AHCI: Protect cmd register John Snow

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.