All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 08/13] dp8393x: Don't clobber packet checksum
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
  2019-12-20  4:17 ` [PATCH v2 07/13] dp8393x: Don't stop reception upon RBE interrupt assertion Finn Thain
  2019-12-20  4:17 ` [PATCH v2 12/13] dp8393x: Always update RRA pointers and sequence numbers Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 05/13] dp8393x: Clear RRRA command register bit only when appropriate Finn Thain
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

A received packet consumes pkt_size bytes in the buffer and the frame
checksum that's appended to it consumes another 4 bytes. The Receive
Buffer Address register takes the former quantity into account but
not the latter. So the next packet written to the buffer overwrites
the frame checksum. Fix this.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/net/dp8393x.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 46b92ebf65..d722bbe8c1 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -813,6 +813,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
     address += rx_len;
     address_space_rw(&s->as, address,
         MEMTXATTRS_UNSPECIFIED, (uint8_t *)&checksum, 4, 1);
+    address += 4;
     rx_len += 4;
     s->regs[SONIC_CRBA1] = address >> 16;
     s->regs[SONIC_CRBA0] = address & 0xffff;
-- 
2.23.0



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

* [PATCH v2 03/13] dp8393x: Have dp8393x_receive() return the packet size
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (6 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 01/13] dp8393x: Mask EOL bit from descriptor addresses Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 11/13] dp8393x: Clear descriptor in_use field when necessary Finn Thain
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

This function re-uses its 'size' argument as a scratch variable.
Instead, declare a local 'size' variable for that purpose so that the
function result doesn't get messed up.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/net/dp8393x.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index b2cc768d9b..a3e3a82ff4 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -746,20 +746,21 @@ static int dp8393x_receive_filter(dp8393xState *s, const uint8_t * buf,
 }
 
 static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
-                               size_t size)
+                               size_t pkt_size)
 {
     dp8393xState *s = qemu_get_nic_opaque(nc);
     int packet_type;
     uint32_t available, address;
-    int width, rx_len = size;
+    int width, rx_len = pkt_size;
     uint32_t checksum;
+    int size;
 
     width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
 
     s->regs[SONIC_RCR] &= ~(SONIC_RCR_PRX | SONIC_RCR_LBK | SONIC_RCR_FAER |
         SONIC_RCR_CRCR | SONIC_RCR_LPKT | SONIC_RCR_BC | SONIC_RCR_MC);
 
-    packet_type = dp8393x_receive_filter(s, buf, size);
+    packet_type = dp8393x_receive_filter(s, buf, pkt_size);
     if (packet_type < 0) {
         DPRINTF("packet not for netcard\n");
         return -1;
@@ -853,7 +854,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
     /* Done */
     dp8393x_update_irq(s);
 
-    return size;
+    return pkt_size;
 }
 
 static void dp8393x_reset(DeviceState *dev)
-- 
2.23.0



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

* [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation
@ 2019-12-20  4:17 Finn Thain
  2019-12-20  4:17 ` [PATCH v2 07/13] dp8393x: Don't stop reception upon RBE interrupt assertion Finn Thain
                   ` (13 more replies)
  0 siblings, 14 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

Hi All,

There are bugs in the DP8393X emulation that can stop packet reception.

Whilst debugging the device I found that the receiver algorithm differs
from the one described in the National Semiconductor datasheet.

These issues and others are addressed by this patch series.

This series has only been tested with Linux/m68k guests. It needs further
testing with MIPS Magnum guests such as NetBSD or Windows NT.

Note that the mainline Linux sonic driver also has bugs.
Those bugs have been fixed in a series of patches at,
https://github.com/fthain/linux/commits/mac68k

---
Changed since v1:
 - Minor revisions described in patch descriptions.
 - Dropped patches 4/10 and 7/10.
 - Added 5 new patches.


Finn Thain (13):
  dp8393x: Mask EOL bit from descriptor addresses
  dp8393x: Clean up endianness hacks
  dp8393x: Have dp8393x_receive() return the packet size
  dp8393x: Update LLFA and CRDA registers from rx descriptor
  dp8393x: Clear RRRA command register bit only when appropriate
  dp8393x: Implement packet size limit and RBAE interrupt
  dp8393x: Don't stop reception upon RBE interrupt assertion
  dp8393x: Don't clobber packet checksum
  dp8393x: Use long-word-aligned RRA pointers in 32-bit mode
  dp8393x: Pad frames to word or long word boundary
  dp8393x: Clear descriptor in_use field when necessary
  dp8393x: Always update RRA pointers and sequence numbers
  dp8393x: Correctly advance RRP

 hw/net/dp8393x.c | 147 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 100 insertions(+), 47 deletions(-)

-- 
2.23.0



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

* [PATCH v2 02/13] dp8393x: Clean up endianness hacks
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (8 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 11/13] dp8393x: Clear descriptor in_use field when necessary Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2020-01-06 22:19   ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 09/13] dp8393x: Use long-word-aligned RRA pointers in 32-bit mode Finn Thain
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

The in_use field is no different to the other words handled using
dp8393x_put() and dp8393x_get(). Use the same technique for in_use
that is used everywhere else.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
Changed since v1:
 - Use existing 'address' variable rather than declare a new one.

Laurent tells me that this clean-up has been tried before. He referred
me to commit c744cf7879 ("dp8393x: fix dp8393x_receive()") and
commit 409b52bfe1 ("net/dp8393x: correctly reset in_use field").

Both of those patches look wrong to me because they both pass the wrong
byte count to address_space_rw(). It's possible that those patches were
needed to work around some kind of bug elsewhere, for example, an
off-by-one result from dp8393x_crda(). The preceding patch in this series
might help there.
---
 hw/net/dp8393x.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 1957bd391e..b2cc768d9b 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -765,8 +765,6 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
         return -1;
     }
 
-    /* XXX: Check byte ordering */
-
     /* Check for EOL */
     if (s->regs[SONIC_LLFA] & SONIC_DESC_EOL) {
         /* Are we still in resource exhaustion? */
@@ -836,15 +834,12 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
         /* EOL detected */
         s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
     } else {
-        /* Clear in_use, but it is always 16bit wide */
-        int offset = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
-        if (s->big_endian && width == 2) {
-            /* we need to adjust the offset of the 16bit field */
-            offset += sizeof(uint16_t);
-        }
-        s->data[0] = 0;
-        address_space_rw(&s->as, offset, MEMTXATTRS_UNSPECIFIED,
-                         (uint8_t *)s->data, sizeof(uint16_t), 1);
+        /* Clear in_use */
+        address = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
+        size = sizeof(uint16_t) * width;
+        dp8393x_put(s, width, 0, 0);
+        address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
+                         (uint8_t *)s->data, size, 1);
         s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
         s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
         s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
-- 
2.23.0



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

* [PATCH v2 10/13] dp8393x: Pad frames to word or long word boundary
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (3 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 05/13] dp8393x: Clear RRRA command register bit only when appropriate Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 04/13] dp8393x: Update LLFA and CRDA registers from rx descriptor Finn Thain
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

The existing code has a bug where the Remaining Buffer Word Count (RBWC)
is calculated with a truncating division, which gives the wrong result
for odd-sized packets.

Section 1.4.1 of the datasheet says,

    Once the end of the packet has been reached, the serializer will
    fill out the last word (16-bit mode) or long word (32-bit mode)
    if the last byte did not end on a word or long word boundary
    respectively. The fill byte will be 0FFh.

Implement buffer padding so that buffer limits are correctly enforced.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
 hw/net/dp8393x.c | 39 ++++++++++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index a3936d3b7b..f35b8b48aa 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -763,16 +763,23 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
     dp8393xState *s = qemu_get_nic_opaque(nc);
     int packet_type;
     uint32_t available, address;
-    int width, rx_len = pkt_size;
+    int width, rx_len, padded_len;
     uint32_t checksum;
     int size;
 
-    width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
-
     s->regs[SONIC_RCR] &= ~(SONIC_RCR_PRX | SONIC_RCR_LBK | SONIC_RCR_FAER |
         SONIC_RCR_CRCR | SONIC_RCR_LPKT | SONIC_RCR_BC | SONIC_RCR_MC);
 
-    if (pkt_size + 4 > dp8393x_rbwc(s) * 2) {
+    rx_len = pkt_size + sizeof(checksum);
+    if (s->regs[SONIC_DCR] & SONIC_DCR_DW) {
+        width = 2;
+        padded_len = ((rx_len - 1) | 3) + 1;
+    } else {
+        width = 1;
+        padded_len = ((rx_len - 1) | 1) + 1;
+    }
+
+    if (padded_len > dp8393x_rbwc(s) * 2) {
         DPRINTF("oversize packet, pkt_size is %d\n", pkt_size);
         s->regs[SONIC_ISR] |= SONIC_ISR_RBAE;
         dp8393x_update_irq(s);
@@ -807,22 +814,32 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
     s->regs[SONIC_TRBA0] = s->regs[SONIC_CRBA0];
 
     /* Calculate the ethernet checksum */
-    checksum = cpu_to_le32(crc32(0, buf, rx_len));
+    checksum = cpu_to_le32(crc32(0, buf, pkt_size));
 
     /* Put packet into RBA */
     DPRINTF("Receive packet at %08x\n", dp8393x_crba(s));
     address = dp8393x_crba(s);
     address_space_rw(&s->as, address,
-        MEMTXATTRS_UNSPECIFIED, (uint8_t *)buf, rx_len, 1);
-    address += rx_len;
+        MEMTXATTRS_UNSPECIFIED, (uint8_t *)buf, pkt_size, 1);
+    address += pkt_size;
+
+    /* Put frame checksum into RBA */
     address_space_rw(&s->as, address,
-        MEMTXATTRS_UNSPECIFIED, (uint8_t *)&checksum, 4, 1);
-    address += 4;
-    rx_len += 4;
+        MEMTXATTRS_UNSPECIFIED, (uint8_t *)&checksum, sizeof(checksum), 1);
+    address += sizeof(checksum);
+
+    /* Pad short packets to keep pointers aligned */
+    if (rx_len < padded_len) {
+        size = padded_len - rx_len;
+        address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
+            (uint8_t *)"\xFF\xFF\xFF", size, 1);
+        address += size;
+    }
+
     s->regs[SONIC_CRBA1] = address >> 16;
     s->regs[SONIC_CRBA0] = address & 0xffff;
     available = dp8393x_rbwc(s);
-    available -= rx_len / 2;
+    available -= padded_len >> 1;
     s->regs[SONIC_RBWC1] = available >> 16;
     s->regs[SONIC_RBWC0] = available & 0xffff;
 
-- 
2.23.0



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

* [PATCH v2 04/13] dp8393x: Update LLFA and CRDA registers from rx descriptor
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (4 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 10/13] dp8393x: Pad frames to word or long word boundary Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 01/13] dp8393x: Mask EOL bit from descriptor addresses Finn Thain
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

Follow the algorithm given in the National Semiconductor DP83932C
datasheet in section 3.4.7:

    At the next reception, the SONIC re-reads the last RXpkt.link field,
    and updates its CRDA register to point to the next descriptor.

The chip is designed to allow the host to provide a new list of
descriptors in this way.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
Changed since v1:
 - Update CRDA register from LLFA register after EOL is cleared.
---
 hw/net/dp8393x.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index a3e3a82ff4..1ead502a8f 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -773,12 +773,13 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
         address = dp8393x_crda(s) + sizeof(uint16_t) * 5 * width;
         address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
                          (uint8_t *)s->data, size, 0);
-        if (dp8393x_get(s, width, 0) & SONIC_DESC_EOL) {
+        s->regs[SONIC_LLFA] = dp8393x_get(s, width, 0);
+        if (s->regs[SONIC_LLFA] & SONIC_DESC_EOL) {
             /* Still EOL ; stop reception */
             return -1;
-        } else {
-            s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
         }
+        /* Link has been updated by host */
+        s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
     }
 
     /* Save current position */
@@ -826,7 +827,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
     address_space_rw(&s->as, dp8393x_crda(s),
         MEMTXATTRS_UNSPECIFIED, (uint8_t *)s->data, size, 1);
 
-    /* Move to next descriptor */
+    /* Check link field */
     size = sizeof(uint16_t) * width;
     address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 5 * width,
         MEMTXATTRS_UNSPECIFIED, (uint8_t *)s->data, size, 0);
@@ -841,6 +842,8 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
         dp8393x_put(s, width, 0, 0);
         address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
                          (uint8_t *)s->data, size, 1);
+
+        /* Move to next descriptor */
         s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
         s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
         s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
-- 
2.23.0



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

* [PATCH v2 13/13] dp8393x: Correctly advance RRP
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (11 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 06/13] dp8393x: Implement packet size limit and RBAE interrupt Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20 22:15   ` Finn Thain
  2019-12-20 10:16 ` [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Laurent Vivier
  13 siblings, 1 reply; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

The last entry in the RRA is at the address given by the REA register.
The address wrap-around logic is off-by-one entry. The last resource
never gets used and RRP can jump over the RWP. The guest driver fails
badly because the SONIC starts re-using old buffer addresses. Fix this.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
 hw/net/dp8393x.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index bd92fa28f6..92a30f9f69 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -340,7 +340,7 @@ static void dp8393x_do_read_rra(dp8393xState *s)
     s->regs[SONIC_RRP] += size;
 
     /* Handle wrap */
-    if (s->regs[SONIC_RRP] == s->regs[SONIC_REA]) {
+    if (s->regs[SONIC_RRP] == s->regs[SONIC_REA] + size) {
         s->regs[SONIC_RRP] = s->regs[SONIC_RSA];
     }
 
-- 
2.23.0



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

* [PATCH v2 11/13] dp8393x: Clear descriptor in_use field when necessary
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (7 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 03/13] dp8393x: Have dp8393x_receive() return the packet size Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 02/13] dp8393x: Clean up endianness hacks Finn Thain
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

This is in accordance with section 3.4.7 of the datasheet:

    When the system appends more descriptors, the SONIC releases ownership
    of the descriptor after writing 0000h to the RXpkt.in_use field.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
 hw/net/dp8393x.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index f35b8b48aa..6b69cca329 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -806,6 +806,15 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
             return -1;
         }
         /* Link has been updated by host */
+
+        /* Clear in_use */
+        size = sizeof(uint16_t) * width;
+        address = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
+        dp8393x_put(s, width, 0, 0);
+        address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
+                         (uint8_t *)s->data, size, 1);
+
+        /* Move to next descriptor */
         s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
     }
 
-- 
2.23.0



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

* [PATCH v2 06/13] dp8393x: Implement packet size limit and RBAE interrupt
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (10 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 09/13] dp8393x: Use long-word-aligned RRA pointers in 32-bit mode Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 13/13] dp8393x: Correctly advance RRP Finn Thain
  2019-12-20 10:16 ` [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Laurent Vivier
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

Add a bounds check to prevent a large packet from causing a buffer
overflow. This is defensive programming -- I haven't actually tried
sending an oversized packet or a jumbo ethernet frame.

The SONIC handles packets that are too big for the buffer by raising
the RBAE interrupt and dropping them. Linux uses that interrupt to
count dropped packets.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
Changed since v1:
 - Perform length check after Recieve Control Register initialization.
---
 hw/net/dp8393x.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 593853244d..9d2c205dce 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -137,6 +137,7 @@ do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
 #define SONIC_TCR_CRCI   0x2000
 #define SONIC_TCR_PINT   0x8000
 
+#define SONIC_ISR_RBAE   0x0010
 #define SONIC_ISR_RBE    0x0020
 #define SONIC_ISR_RDE    0x0040
 #define SONIC_ISR_TC     0x0080
@@ -759,6 +760,14 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
     s->regs[SONIC_RCR] &= ~(SONIC_RCR_PRX | SONIC_RCR_LBK | SONIC_RCR_FAER |
         SONIC_RCR_CRCR | SONIC_RCR_LPKT | SONIC_RCR_BC | SONIC_RCR_MC);
 
+    if (pkt_size + 4 > dp8393x_rbwc(s) * 2) {
+        DPRINTF("oversize packet, pkt_size is %d\n", pkt_size);
+        s->regs[SONIC_ISR] |= SONIC_ISR_RBAE;
+        dp8393x_update_irq(s);
+        dp8393x_do_read_rra(s);
+        return pkt_size;
+    }
+
     packet_type = dp8393x_receive_filter(s, buf, pkt_size);
     if (packet_type < 0) {
         DPRINTF("packet not for netcard\n");
-- 
2.23.0



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

* [PATCH v2 12/13] dp8393x: Always update RRA pointers and sequence numbers
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
  2019-12-20  4:17 ` [PATCH v2 07/13] dp8393x: Don't stop reception upon RBE interrupt assertion Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 08/13] dp8393x: Don't clobber packet checksum Finn Thain
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

These operations have to take place regardless of whether or not rx
descriptors have been used up (that is, EOL flag was observed).

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
 hw/net/dp8393x.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 6b69cca329..bd92fa28f6 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -893,12 +893,14 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
         /* Move to next descriptor */
         s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
         s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
-        s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
+    }
 
-        if (s->regs[SONIC_RCR] & SONIC_RCR_LPKT) {
-            /* Read next RRA */
-            dp8393x_do_read_rra(s);
-        }
+    s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) |
+                         ((s->regs[SONIC_RSC] + 1) & 0x00ff);
+
+    if (s->regs[SONIC_RCR] & SONIC_RCR_LPKT) {
+        /* Read next RRA */
+        dp8393x_do_read_rra(s);
     }
 
     /* Done */
-- 
2.23.0



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

* [PATCH v2 01/13] dp8393x: Mask EOL bit from descriptor addresses
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (5 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 04/13] dp8393x: Update LLFA and CRDA registers from rx descriptor Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 03/13] dp8393x: Have dp8393x_receive() return the packet size Finn Thain
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

The LSB of descriptor address registers is used as an EOL flag.
It has to be masked when those registers are to be used as actual
addresses for copying memory around. But when the registers are
to be updated the EOL bit should not be masked.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
Changed since v1:
 - Added macros to name constants as requested by Philippe Mathieu-Daudé.
---
 hw/net/dp8393x.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 3d991af163..1957bd391e 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -145,6 +145,9 @@ do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
 #define SONIC_ISR_PINT   0x0800
 #define SONIC_ISR_LCD    0x1000
 
+#define SONIC_DESC_EOL   0x0001
+#define SONIC_DESC_ADDR  0xFFFE
+
 #define TYPE_DP8393X "dp8393x"
 #define DP8393X(obj) OBJECT_CHECK(dp8393xState, (obj), TYPE_DP8393X)
 
@@ -197,7 +200,8 @@ static uint32_t dp8393x_crba(dp8393xState *s)
 
 static uint32_t dp8393x_crda(dp8393xState *s)
 {
-    return (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA];
+    return (s->regs[SONIC_URDA] << 16) |
+           (s->regs[SONIC_CRDA] & SONIC_DESC_ADDR);
 }
 
 static uint32_t dp8393x_rbwc(dp8393xState *s)
@@ -217,7 +221,8 @@ static uint32_t dp8393x_tsa(dp8393xState *s)
 
 static uint32_t dp8393x_ttda(dp8393xState *s)
 {
-    return (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA];
+    return (s->regs[SONIC_UTDA] << 16) |
+           (s->regs[SONIC_TTDA] & SONIC_DESC_ADDR);
 }
 
 static uint32_t dp8393x_wt(dp8393xState *s)
@@ -506,8 +511,8 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
                              sizeof(uint16_t) *
                              (4 + 3 * s->regs[SONIC_TFC]) * width,
                 MEMTXATTRS_UNSPECIFIED, (uint8_t *)s->data, size, 0);
-            s->regs[SONIC_CTDA] = dp8393x_get(s, width, 0) & ~0x1;
-            if (dp8393x_get(s, width, 0) & 0x1) {
+            s->regs[SONIC_CTDA] = dp8393x_get(s, width, 0);
+            if (s->regs[SONIC_CTDA] & SONIC_DESC_EOL) {
                 /* EOL detected */
                 break;
             }
@@ -763,13 +768,13 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
     /* XXX: Check byte ordering */
 
     /* Check for EOL */
-    if (s->regs[SONIC_LLFA] & 0x1) {
+    if (s->regs[SONIC_LLFA] & SONIC_DESC_EOL) {
         /* Are we still in resource exhaustion? */
         size = sizeof(uint16_t) * 1 * width;
         address = dp8393x_crda(s) + sizeof(uint16_t) * 5 * width;
         address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
                          (uint8_t *)s->data, size, 0);
-        if (dp8393x_get(s, width, 0) & 0x1) {
+        if (dp8393x_get(s, width, 0) & SONIC_DESC_EOL) {
             /* Still EOL ; stop reception */
             return -1;
         } else {
@@ -827,7 +832,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
     address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 5 * width,
         MEMTXATTRS_UNSPECIFIED, (uint8_t *)s->data, size, 0);
     s->regs[SONIC_LLFA] = dp8393x_get(s, width, 0);
-    if (s->regs[SONIC_LLFA] & 0x1) {
+    if (s->regs[SONIC_LLFA] & SONIC_DESC_EOL) {
         /* EOL detected */
         s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
     } else {
-- 
2.23.0



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

* [PATCH v2 05/13] dp8393x: Clear RRRA command register bit only when appropriate
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (2 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 08/13] dp8393x: Don't clobber packet checksum Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 10/13] dp8393x: Pad frames to word or long word boundary Finn Thain
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

It doesn't make sense to clear the command register bit unless the
command was actually issued.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/net/dp8393x.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 1ead502a8f..593853244d 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -342,9 +342,6 @@ static void dp8393x_do_read_rra(dp8393xState *s)
         s->regs[SONIC_ISR] |= SONIC_ISR_RBE;
         dp8393x_update_irq(s);
     }
-
-    /* Done */
-    s->regs[SONIC_CR] &= ~SONIC_CR_RRRA;
 }
 
 static void dp8393x_do_software_reset(dp8393xState *s)
@@ -553,8 +550,10 @@ static void dp8393x_do_command(dp8393xState *s, uint16_t command)
         dp8393x_do_start_timer(s);
     if (command & SONIC_CR_RST)
         dp8393x_do_software_reset(s);
-    if (command & SONIC_CR_RRRA)
+    if (command & SONIC_CR_RRRA) {
         dp8393x_do_read_rra(s);
+        s->regs[SONIC_CR] &= ~SONIC_CR_RRRA;
+    }
     if (command & SONIC_CR_LCAM)
         dp8393x_do_load_cam(s);
 }
-- 
2.23.0



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

* [PATCH v2 09/13] dp8393x: Use long-word-aligned RRA pointers in 32-bit mode
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (9 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 02/13] dp8393x: Clean up endianness hacks Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 06/13] dp8393x: Implement packet size limit and RBAE interrupt Finn Thain
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

Section 3.4.1 of the datasheet says,

    The alignment of the RRA is confined to either word or long word
    boundaries, depending upon the data width mode. In 16-bit mode,
    the RRA must be aligned to a word boundary (A0 is always zero)
    and in 32-bit mode, the RRA is aligned to a long word boundary
    (A0 and A1 are always zero).

This constraint has been implemented for 16-bit mode; implement it
for 32-bit mode too.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
 hw/net/dp8393x.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index d722bbe8c1..a3936d3b7b 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -659,12 +659,16 @@ static void dp8393x_write(void *opaque, hwaddr addr, uint64_t data,
                 qemu_flush_queued_packets(qemu_get_queue(s->nic));
             }
             break;
-        /* Ignore least significant bit */
+        /* The guest is required to store aligned pointers here */
         case SONIC_RSA:
         case SONIC_REA:
         case SONIC_RRP:
         case SONIC_RWP:
-            s->regs[reg] = data & 0xfffe;
+            if (s->regs[SONIC_DCR] & SONIC_DCR_DW) {
+                s->regs[reg] = data & 0xfffc;
+            } else {
+                s->regs[reg] = data & 0xfffe;
+            }
             break;
         /* Invert written value for some registers */
         case SONIC_CRCT:
-- 
2.23.0



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

* [PATCH v2 07/13] dp8393x: Don't stop reception upon RBE interrupt assertion
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
@ 2019-12-20  4:17 ` Finn Thain
  2019-12-20  4:17 ` [PATCH v2 12/13] dp8393x: Always update RRA pointers and sequence numbers Finn Thain
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20  4:17 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable

Section 5.4.7 of the datasheet explains that the RBE interrupt is an
"early warning". It indicates that the last RBA is still available to
receive a packet. It doesn't imply actual receive buffer exhaustion.

This is an important distinction because Linux will not check and clear
the RBE interrupt until it receives another packet. But that won't
happen if can_receive returns false. So the SONIC becomes deaf (until
reset).

Fix this with a new flag to indicate actual receive buffer exhaustion.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
 hw/net/dp8393x.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 9d2c205dce..46b92ebf65 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -158,6 +158,7 @@ typedef struct dp8393xState {
     /* Hardware */
     uint8_t it_shift;
     bool big_endian;
+    bool last_rba_is_full;
     qemu_irq irq;
 #ifdef DEBUG_SONIC
     int irq_level;
@@ -314,6 +315,12 @@ static void dp8393x_do_read_rra(dp8393xState *s)
 {
     int width, size;
 
+    /* Already on the last RBA? */
+    s->last_rba_is_full = s->regs[SONIC_ISR] & SONIC_ISR_RBE;
+    if (s->last_rba_is_full) {
+        return;
+    }
+
     /* Read memory */
     width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
     size = sizeof(uint16_t) * 4 * width;
@@ -337,7 +344,7 @@ static void dp8393x_do_read_rra(dp8393xState *s)
         s->regs[SONIC_RRP] = s->regs[SONIC_RSA];
     }
 
-    /* Check resource exhaustion */
+    /* Warn the host if this entry is the last one */
     if (s->regs[SONIC_RRP] == s->regs[SONIC_RWP])
     {
         s->regs[SONIC_ISR] |= SONIC_ISR_RBE;
@@ -706,8 +713,9 @@ static int dp8393x_can_receive(NetClientState *nc)
 
     if (!(s->regs[SONIC_CR] & SONIC_CR_RXEN))
         return 0;
-    if (s->regs[SONIC_ISR] & SONIC_ISR_RBE)
+    if (s->last_rba_is_full) {
         return 0;
+    }
     return 1;
 }
 
-- 
2.23.0



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

* Re: [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation
  2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
                   ` (12 preceding siblings ...)
  2019-12-20  4:17 ` [PATCH v2 13/13] dp8393x: Correctly advance RRP Finn Thain
@ 2019-12-20 10:16 ` Laurent Vivier
  13 siblings, 0 replies; 19+ messages in thread
From: Laurent Vivier @ 2019-12-20 10:16 UTC (permalink / raw)
  To: Finn Thain, Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, qemu-stable

Le 20/12/2019 à 05:17, Finn Thain a écrit :
> Hi All,
> 
> There are bugs in the DP8393X emulation that can stop packet reception.
> 
> Whilst debugging the device I found that the receiver algorithm differs
> from the one described in the National Semiconductor datasheet.
> 
> These issues and others are addressed by this patch series.
> 
> This series has only been tested with Linux/m68k guests. It needs further
> testing with MIPS Magnum guests such as NetBSD or Windows NT.
> 
> Note that the mainline Linux sonic driver also has bugs.
> Those bugs have been fixed in a series of patches at,
> https://github.com/fthain/linux/commits/mac68k
> 
> ---
> Changed since v1:
>  - Minor revisions described in patch descriptions.
>  - Dropped patches 4/10 and 7/10.
>  - Added 5 new patches.
> 
> 
> Finn Thain (13):
>   dp8393x: Mask EOL bit from descriptor addresses
>   dp8393x: Clean up endianness hacks
>   dp8393x: Have dp8393x_receive() return the packet size
>   dp8393x: Update LLFA and CRDA registers from rx descriptor
>   dp8393x: Clear RRRA command register bit only when appropriate
>   dp8393x: Implement packet size limit and RBAE interrupt
>   dp8393x: Don't stop reception upon RBE interrupt assertion
>   dp8393x: Don't clobber packet checksum
>   dp8393x: Use long-word-aligned RRA pointers in 32-bit mode
>   dp8393x: Pad frames to word or long word boundary
>   dp8393x: Clear descriptor in_use field when necessary
>   dp8393x: Always update RRA pointers and sequence numbers
>   dp8393x: Correctly advance RRP
> 
>  hw/net/dp8393x.c | 147 ++++++++++++++++++++++++++++++++---------------
>  1 file changed, 100 insertions(+), 47 deletions(-)
> 

For q800:

Tested-by: Laurent Vivier <laurent@vivier.eu>


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

* Re: [PATCH v2 13/13] dp8393x: Correctly advance RRP
  2019-12-20  4:17 ` [PATCH v2 13/13] dp8393x: Correctly advance RRP Finn Thain
@ 2019-12-20 22:15   ` Finn Thain
  0 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2019-12-20 22:15 UTC (permalink / raw)
  To: Jason Wang, qemu-devel
  Cc: Aleksandar Rikalo, Hervé Poussineau, Laurent Vivier, qemu-stable


Please disregard this patch. An off-by-one bug was found in one of my 
Linux sonic driver patches. When I fixed that bug, this patch (13/13) was 
shown to be incorrect.

The Linux sonic driver patches are being tested on actual SONIC hardware 
(Mac Centris 610). I will send v3 of this series after I've finished 
debugging the Linux sonic driver.

On Fri, 20 Dec 2019, Finn Thain wrote:

> The last entry in the RRA is at the address given by the REA register.
> The address wrap-around logic is off-by-one entry. The last resource
> never gets used and RRP can jump over the RWP. The guest driver fails
> badly because the SONIC starts re-using old buffer addresses. Fix this.
> 
> Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
> ---
>  hw/net/dp8393x.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
> index bd92fa28f6..92a30f9f69 100644
> --- a/hw/net/dp8393x.c
> +++ b/hw/net/dp8393x.c
> @@ -340,7 +340,7 @@ static void dp8393x_do_read_rra(dp8393xState *s)
>      s->regs[SONIC_RRP] += size;
>  
>      /* Handle wrap */
> -    if (s->regs[SONIC_RRP] == s->regs[SONIC_REA]) {
> +    if (s->regs[SONIC_RRP] == s->regs[SONIC_REA] + size) {
>          s->regs[SONIC_RRP] = s->regs[SONIC_RSA];
>      }
>  
> 


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

* Re: [PATCH v2 02/13] dp8393x: Clean up endianness hacks
  2019-12-20  4:17 ` [PATCH v2 02/13] dp8393x: Clean up endianness hacks Finn Thain
@ 2020-01-06 22:19   ` Finn Thain
  2020-01-07  7:20     ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 19+ messages in thread
From: Finn Thain @ 2020-01-06 22:19 UTC (permalink / raw)
  To: Hervé Poussineau, Laurent Vivier
  Cc: Aleksandar Rikalo, qemu-stable, Jason Wang, qemu-devel

On Fri, 20 Dec 2019, Finn Thain wrote:

> The in_use field is no different to the other words handled using
> dp8393x_put() and dp8393x_get(). Use the same technique for in_use
> that is used everywhere else.
> 
> Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
> ---
> Changed since v1:
>  - Use existing 'address' variable rather than declare a new one.
> 
> Laurent tells me that this clean-up has been tried before. He referred
> me to commit c744cf7879 ("dp8393x: fix dp8393x_receive()") and
> commit 409b52bfe1 ("net/dp8393x: correctly reset in_use field").
> 
> Both of those patches look wrong to me because they both pass the wrong
> byte count to address_space_rw(). It's possible that those patches were
> needed to work around some kind of bug elsewhere, for example, an
> off-by-one result from dp8393x_crda(). The preceding patch in this series
> might help there.

Unfortunately this patch really does break NetBSD/arc 5.1, just as
Laurent said it would, just as commit c744cf7879 did.

Yet these patches are correct. What gives?

I found that one more change can make guests work (for both m68k q800 and 
mips64el magnum machines) --

--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -246,8 +246,10 @@ static void dp8393x_put(dp8393xState *s, int width, 
int offset,
                         uint16_t val)
 {
     if (s->big_endian) {
+        s->data[offset * width] = 0;
         s->data[offset * width + width - 1] = cpu_to_be16(val);
     } else {
+        s->data[offset * width + width - 1] = 0;
         s->data[offset * width] = cpu_to_le16(val);
     }
 }

For a wide bus interface, this forces the Most Significant Word (MSW) to 
zero. Yet another endianness hack, but it makes NetBSD 5.1 'sn' driver 
happy.

There is a similar issue with the Linux jazzsonic driver. This driver uses 
long-word-sized loads with word-sized MMIO registers --

#define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))

This driver also expects the MSW to be zero. But the MSW actually equals 
the LSW, and the driver fails to probe:

SONIC ethernet controller not found (0x40004)

This seems to indicate that qemu-system-mips64el -M magnum is doing word 
smearing on the processor bus. Does anyone know how to prevent that?

> ---
>  hw/net/dp8393x.c | 17 ++++++-----------
>  1 file changed, 6 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
> index 1957bd391e..b2cc768d9b 100644
> --- a/hw/net/dp8393x.c
> +++ b/hw/net/dp8393x.c
> @@ -765,8 +765,6 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
>          return -1;
>      }
>  
> -    /* XXX: Check byte ordering */
> -
>      /* Check for EOL */
>      if (s->regs[SONIC_LLFA] & SONIC_DESC_EOL) {
>          /* Are we still in resource exhaustion? */
> @@ -836,15 +834,12 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
>          /* EOL detected */
>          s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
>      } else {
> -        /* Clear in_use, but it is always 16bit wide */
> -        int offset = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
> -        if (s->big_endian && width == 2) {
> -            /* we need to adjust the offset of the 16bit field */
> -            offset += sizeof(uint16_t);
> -        }
> -        s->data[0] = 0;
> -        address_space_rw(&s->as, offset, MEMTXATTRS_UNSPECIFIED,
> -                         (uint8_t *)s->data, sizeof(uint16_t), 1);
> +        /* Clear in_use */
> +        address = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
> +        size = sizeof(uint16_t) * width;
> +        dp8393x_put(s, width, 0, 0);
> +        address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
> +                         (uint8_t *)s->data, size, 1);
>          s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
>          s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
>          s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
> 


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

* Re: [PATCH v2 02/13] dp8393x: Clean up endianness hacks
  2020-01-06 22:19   ` Finn Thain
@ 2020-01-07  7:20     ` Philippe Mathieu-Daudé
  2020-01-08  0:21       ` Finn Thain
  0 siblings, 1 reply; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-01-07  7:20 UTC (permalink / raw)
  To: Finn Thain, Hervé Poussineau, Laurent Vivier
  Cc: Jason Wang, Aleksandar Rikalo, qemu-stable, qemu-devel

On 1/6/20 11:19 PM, Finn Thain wrote:
> On Fri, 20 Dec 2019, Finn Thain wrote:
> 
>> The in_use field is no different to the other words handled using
>> dp8393x_put() and dp8393x_get(). Use the same technique for in_use
>> that is used everywhere else.
>>
>> Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
>> ---
>> Changed since v1:
>>   - Use existing 'address' variable rather than declare a new one.
>>
>> Laurent tells me that this clean-up has been tried before. He referred
>> me to commit c744cf7879 ("dp8393x: fix dp8393x_receive()") and
>> commit 409b52bfe1 ("net/dp8393x: correctly reset in_use field").
>>
>> Both of those patches look wrong to me because they both pass the wrong
>> byte count to address_space_rw(). It's possible that those patches were
>> needed to work around some kind of bug elsewhere, for example, an
>> off-by-one result from dp8393x_crda(). The preceding patch in this series
>> might help there.
> 
> Unfortunately this patch really does break NetBSD/arc 5.1, just as
> Laurent said it would, just as commit c744cf7879 did.
> 
> Yet these patches are correct. What gives?
> 
> I found that one more change can make guests work (for both m68k q800 and
> mips64el magnum machines) --
> 
> --- a/hw/net/dp8393x.c
> +++ b/hw/net/dp8393x.c
> @@ -246,8 +246,10 @@ static void dp8393x_put(dp8393xState *s, int width,
> int offset,
>                           uint16_t val)
>   {
>       if (s->big_endian) {
> +        s->data[offset * width] = 0;
>           s->data[offset * width + width - 1] = cpu_to_be16(val);
>       } else {
> +        s->data[offset * width + width - 1] = 0;
>           s->data[offset * width] = cpu_to_le16(val);
>       }
>   }
> 
> For a wide bus interface, this forces the Most Significant Word (MSW) to
> zero. Yet another endianness hack, but it makes NetBSD 5.1 'sn' driver
> happy.

Can you write a list of real word addresses/values/result expected for 
each endianess, so we can add a qtest for this?

> There is a similar issue with the Linux jazzsonic driver. This driver uses
> long-word-sized loads with word-sized MMIO registers --
> 
> #define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))
> 
> This driver also expects the MSW to be zero. But the MSW actually equals
> the LSW, and the driver fails to probe:
> 
> SONIC ethernet controller not found (0x40004)
> 
> This seems to indicate that qemu-system-mips64el -M magnum is doing word
> smearing on the processor bus. Does anyone know how to prevent that?

I remember a similar issue with another MIPS board because QEMU doesn't 
model the bus controller, which might do such magic.

> 
>> ---
>>   hw/net/dp8393x.c | 17 ++++++-----------
>>   1 file changed, 6 insertions(+), 11 deletions(-)
>>
>> diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
>> index 1957bd391e..b2cc768d9b 100644
>> --- a/hw/net/dp8393x.c
>> +++ b/hw/net/dp8393x.c
>> @@ -765,8 +765,6 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
>>           return -1;
>>       }
>>   
>> -    /* XXX: Check byte ordering */
>> -
>>       /* Check for EOL */
>>       if (s->regs[SONIC_LLFA] & SONIC_DESC_EOL) {
>>           /* Are we still in resource exhaustion? */
>> @@ -836,15 +834,12 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
>>           /* EOL detected */
>>           s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
>>       } else {
>> -        /* Clear in_use, but it is always 16bit wide */
>> -        int offset = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
>> -        if (s->big_endian && width == 2) {
>> -            /* we need to adjust the offset of the 16bit field */
>> -            offset += sizeof(uint16_t);
>> -        }
>> -        s->data[0] = 0;
>> -        address_space_rw(&s->as, offset, MEMTXATTRS_UNSPECIFIED,
>> -                         (uint8_t *)s->data, sizeof(uint16_t), 1);
>> +        /* Clear in_use */
>> +        address = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
>> +        size = sizeof(uint16_t) * width;
>> +        dp8393x_put(s, width, 0, 0);
>> +        address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
>> +                         (uint8_t *)s->data, size, 1);
>>           s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
>>           s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
>>           s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
>>
> 



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

* Re: [PATCH v2 02/13] dp8393x: Clean up endianness hacks
  2020-01-07  7:20     ` Philippe Mathieu-Daudé
@ 2020-01-08  0:21       ` Finn Thain
  0 siblings, 0 replies; 19+ messages in thread
From: Finn Thain @ 2020-01-08  0:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Jason Wang, qemu-devel, Laurent Vivier, Hervé Poussineau,
	Aleksandar Rikalo, qemu-stable

On Tue, 7 Jan 2020, Philippe Mathieu-Daud? wrote:

> On 1/6/20 11:19 PM, Finn Thain wrote:
> > On Fri, 20 Dec 2019, Finn Thain wrote:
> > 
> > > The in_use field is no different to the other words handled using
> > > dp8393x_put() and dp8393x_get(). Use the same technique for in_use
> > > that is used everywhere else.
> > > 
> > > Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
> > > ---
> > > Changed since v1:
> > >   - Use existing 'address' variable rather than declare a new one.
> > > 
> > > Laurent tells me that this clean-up has been tried before. He referred
> > > me to commit c744cf7879 ("dp8393x: fix dp8393x_receive()") and
> > > commit 409b52bfe1 ("net/dp8393x: correctly reset in_use field").
> > > 
> > > Both of those patches look wrong to me because they both pass the wrong
> > > byte count to address_space_rw(). It's possible that those patches were
> > > needed to work around some kind of bug elsewhere, for example, an
> > > off-by-one result from dp8393x_crda(). The preceding patch in this series
> > > might help there.
> > 
> > Unfortunately this patch really does break NetBSD/arc 5.1, just as
> > Laurent said it would, just as commit c744cf7879 did.
> > 
> > Yet these patches are correct. What gives?
> > 
> > I found that one more change can make guests work (for both m68k q800 and
> > mips64el magnum machines) --
> > 
> > --- a/hw/net/dp8393x.c
> > +++ b/hw/net/dp8393x.c
> > @@ -246,8 +246,10 @@ static void dp8393x_put(dp8393xState *s, int width,
> > int offset,
> >                           uint16_t val)
> >   {
> >       if (s->big_endian) {
> > +          s->data[offset * width] = 0;
> >           s->data[offset * width + width - 1] = cpu_to_be16(val);
> >       } else {
> > +          s->data[offset * width + width - 1] = 0;
> >           s->data[offset * width] = cpu_to_le16(val);
> >       }
> >   }
> > 
> > For a wide bus interface, this forces the Most Significant Word (MSW) to
> > zero. Yet another endianness hack, but it makes NetBSD 5.1 'sn' driver
> > happy.
> 
> Can you write a list of real word addresses/values/result expected for each
> endianess, so we can add a qtest for this?
> 

I'm afraid I've no idea how qtests work. If you are talking about a unit 
test for dp8393x.c, this would be non-trivial because you need to have the 
SONIC in bus master mode (i.e. you have to get the chip to do some DMA).

The chip datasheet says,

    Data Bus: These bidirectional lines are used to transfer data on the 
    system bus. When the SONIC is a bus master, 16-bit data is transferred 
    on D15-D0 and 32-bit data is transferred on D31-D0. When the SONIC is 
    accessed as a slave, register data is driven onto lines D15-D0. 
    D31-D16 are held TRI-STATE if SONIC is in 16-bit mode. If SONIC is in 
    32-bit mode, they are driven, but invalid.

The datasheet does not explicitly state that D31-D16 are held low during a 
DMA write, it just says they are "not used". But I'm beginning to think 
that forcing the MSW to zero (see above) is the right thing to do.

> > There is a similar issue with the Linux jazzsonic driver. This driver uses
> > long-word-sized loads with word-sized MMIO registers --
> > 
> > #define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))
> > 
> > This driver also expects the MSW to be zero. But the MSW actually equals
> > the LSW, and the driver fails to probe:
> > 
> > SONIC ethernet controller not found (0x40004)
> > 
> > This seems to indicate that qemu-system-mips64el -M magnum is doing word
> > smearing on the processor bus. Does anyone know how to prevent that?
> 
> I remember a similar issue with another MIPS board because QEMU doesn't model
> the bus controller, which might do such magic.
> 

The bus slave situation relates to e.g. the Silicon Revision register 
access. This is what breaks the Linux jazzsonic driver.

In that situation, the datasheet says that D31-D16 are "driven, but 
invalid". I think the right fix for that is,

--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -695,8 +695,8 @@ static void dp8393x_write(void *opaque, hwaddr addr, 
uint64_t data,
 static const MemoryRegionOps dp8393x_ops = {
     .read = dp8393x_read,
     .write = dp8393x_write,
-    .impl.min_access_size = 2,
-    .impl.max_access_size = 2,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
     .endianness = DEVICE_NATIVE_ENDIAN,
 };

This change seems to fix Linux/mipsel and break Linux/m68k, even though 
both use the chip in 32-bit mode... I guess there's another endianness 
bug somewhere.

> > 
> > > ---
> > >   hw/net/dp8393x.c | 17 ++++++-----------
> > >   1 file changed, 6 insertions(+), 11 deletions(-)
> > > 
> > > diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
> > > index 1957bd391e..b2cc768d9b 100644
> > > --- a/hw/net/dp8393x.c
> > > +++ b/hw/net/dp8393x.c
> > > @@ -765,8 +765,6 @@ static ssize_t dp8393x_receive(NetClientState *nc,
> > > const uint8_t * buf,
> > >           return -1;
> > >       }
> > >   -    /* XXX: Check byte ordering */
> > > -
> > >       /* Check for EOL */
> > >       if (s->regs[SONIC_LLFA] & SONIC_DESC_EOL) {
> > >           /* Are we still in resource exhaustion? */
> > > @@ -836,15 +834,12 @@ static ssize_t dp8393x_receive(NetClientState *nc,
> > > const uint8_t * buf,
> > >           /* EOL detected */
> > >           s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
> > >       } else {
> > > -        /* Clear in_use, but it is always 16bit wide */
> > > -        int offset = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
> > > -        if (s->big_endian && width == 2) {
> > > -            /* we need to adjust the offset of the 16bit field */
> > > -            offset += sizeof(uint16_t);
> > > -        }
> > > -        s->data[0] = 0;
> > > -        address_space_rw(&s->as, offset, MEMTXATTRS_UNSPECIFIED,
> > > -                         (uint8_t *)s->data, sizeof(uint16_t), 1);
> > > +        /* Clear in_use */
> > > +        address = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
> > > +        size = sizeof(uint16_t) * width;
> > > +        dp8393x_put(s, width, 0, 0);
> > > +        address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
> > > +                         (uint8_t *)s->data, size, 1);
> > >           s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
> > >           s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
> > >           s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) |
> > > (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
> > > 
> > 
> 
> 


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

end of thread, other threads:[~2020-01-08  0:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-20  4:17 [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Finn Thain
2019-12-20  4:17 ` [PATCH v2 07/13] dp8393x: Don't stop reception upon RBE interrupt assertion Finn Thain
2019-12-20  4:17 ` [PATCH v2 12/13] dp8393x: Always update RRA pointers and sequence numbers Finn Thain
2019-12-20  4:17 ` [PATCH v2 08/13] dp8393x: Don't clobber packet checksum Finn Thain
2019-12-20  4:17 ` [PATCH v2 05/13] dp8393x: Clear RRRA command register bit only when appropriate Finn Thain
2019-12-20  4:17 ` [PATCH v2 10/13] dp8393x: Pad frames to word or long word boundary Finn Thain
2019-12-20  4:17 ` [PATCH v2 04/13] dp8393x: Update LLFA and CRDA registers from rx descriptor Finn Thain
2019-12-20  4:17 ` [PATCH v2 01/13] dp8393x: Mask EOL bit from descriptor addresses Finn Thain
2019-12-20  4:17 ` [PATCH v2 03/13] dp8393x: Have dp8393x_receive() return the packet size Finn Thain
2019-12-20  4:17 ` [PATCH v2 11/13] dp8393x: Clear descriptor in_use field when necessary Finn Thain
2019-12-20  4:17 ` [PATCH v2 02/13] dp8393x: Clean up endianness hacks Finn Thain
2020-01-06 22:19   ` Finn Thain
2020-01-07  7:20     ` Philippe Mathieu-Daudé
2020-01-08  0:21       ` Finn Thain
2019-12-20  4:17 ` [PATCH v2 09/13] dp8393x: Use long-word-aligned RRA pointers in 32-bit mode Finn Thain
2019-12-20  4:17 ` [PATCH v2 06/13] dp8393x: Implement packet size limit and RBAE interrupt Finn Thain
2019-12-20  4:17 ` [PATCH v2 13/13] dp8393x: Correctly advance RRP Finn Thain
2019-12-20 22:15   ` Finn Thain
2019-12-20 10:16 ` [PATCH v2 00/13] Fixes for DP8393X SONIC device emulation Laurent Vivier

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.