From fa2f7f996457cb1c506be5584178db250a3b1a2c Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 7 Sep 2015 15:35:49 +0100 Subject: qemu: Add fixes for smc91c11 qemu segfaults on arm The smc91c111.c driver appears to have several issues. The can_receive() function can return that the driver is ready when rx_fifo has not been freed yet. There is also no sanity check of rx_fifo() in _receive() which can lead to corruption of the rx_fifo array. release_packet() can also call qemu_flush_queued_packets() before rx_fifo has been cleaned up, resulting in cases where packets are submitted for which there is not yet any space. This patch therefore: * fixes the logic in can_receive() * adds logic to receive() as a sanity check * moves the flush() calls to the correct places where data is ready to be received Its currently undergoing discussion upstream about exactly which pieces are the correct fix but for now, this stops the segfaults OE is seeing which has to be an improvement. [YOCTO #8234] (From OE-Core rev: 414a5256d6f00d5682ce226ee4bc49674ee6c614) Signed-off-by: Richard Purdie --- .../recipes-devtools/qemu/qemu/smc91c111_fix.patch | 77 ++++++++++++++++++++++ meta/recipes-devtools/qemu/qemu_2.4.0.bb | 1 + 2 files changed, 78 insertions(+) create mode 100644 meta/recipes-devtools/qemu/qemu/smc91c111_fix.patch (limited to 'meta/recipes-devtools/qemu') diff --git a/meta/recipes-devtools/qemu/qemu/smc91c111_fix.patch b/meta/recipes-devtools/qemu/qemu/smc91c111_fix.patch new file mode 100644 index 0000000000..e69af94476 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/smc91c111_fix.patch @@ -0,0 +1,77 @@ +The smc91c111.c driver appears to have several issues. The can_receive() +function can return that the driver is ready when rx_fifo has not been +freed yet. There is also no sanity check of rx_fifo() in _receive() which +can lead to corruption of the rx_fifo array. + +release_packet() can also call qemu_flush_queued_packets() before rx_fifo +has been cleaned up, resulting in cases where packets are submitted +for which there is not yet any space. + +This patch therefore: + +* fixes the logic in can_receive() +* adds logic to receive() as a sanity check +* moves the flush() calls to the correct places where data is ready + to be received + +Upstream-Status: Pending [discussion in progress on mailing list] +RP 2015/9/7 + +Index: qemu-2.4.0/hw/net/smc91c111.c +=================================================================== +--- qemu-2.4.0.orig/hw/net/smc91c111.c ++++ qemu-2.4.0/hw/net/smc91c111.c +@@ -185,7 +185,6 @@ static void smc91c111_release_packet(smc + s->allocated &= ~(1 << packet); + if (s->tx_alloc == 0x80) + smc91c111_tx_alloc(s); +- qemu_flush_queued_packets(qemu_get_queue(s->nic)); + } + + /* Flush the TX FIFO. */ +@@ -237,9 +236,11 @@ static void smc91c111_do_tx(smc91c111_st + } + } + #endif +- if (s->ctr & CTR_AUTO_RELEASE) ++ if (s->ctr & CTR_AUTO_RELEASE) { + /* Race? */ + smc91c111_release_packet(s, packetnum); ++ qemu_flush_queued_packets(qemu_get_queue(s->nic)); ++ } + else if (s->tx_fifo_done_len < NUM_PACKETS) + s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum; + qemu_send_packet(qemu_get_queue(s->nic), p, len); +@@ -379,9 +380,11 @@ static void smc91c111_writeb(void *opaqu + smc91c111_release_packet(s, s->rx_fifo[0]); + } + smc91c111_pop_rx_fifo(s); ++ qemu_flush_queued_packets(qemu_get_queue(s->nic)); + break; + case 5: /* Release. */ + smc91c111_release_packet(s, s->packet_num); ++ qemu_flush_queued_packets(qemu_get_queue(s->nic)); + break; + case 6: /* Add to TX FIFO. */ + smc91c111_queue_tx(s, s->packet_num); +@@ -642,7 +642,7 @@ static int smc91c111_can_receive(NetClie + + if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) + return 1; +- if (s->allocated == (1 << NUM_PACKETS) - 1) ++ if ((s->allocated == (1 << NUM_PACKETS) - 1) || (s->rx_fifo_len == NUM_PACKETS)) + return 0; + return 1; + } +@@ -671,9 +671,11 @@ static ssize_t smc91c111_receive(NetClie + /* TODO: Flag overrun and receive errors. */ + if (packetsize > 2048) + return -1; ++ if (s->rx_fifo_len == NUM_PACKETS) ++ return -1; + packetnum = smc91c111_allocate_packet(s); + if (packetnum == 0x80) + return -1; + s->rx_fifo[s->rx_fifo_len++] = packetnum; + + p = &s->data[packetnum][0]; diff --git a/meta/recipes-devtools/qemu/qemu_2.4.0.bb b/meta/recipes-devtools/qemu/qemu_2.4.0.bb index 5e5f786b10..d545b60f64 100644 --- a/meta/recipes-devtools/qemu/qemu_2.4.0.bb +++ b/meta/recipes-devtools/qemu/qemu_2.4.0.bb @@ -6,6 +6,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=441c28d2cf86e15a37fa47e15a72fbac \ SRC_URI += "file://configure-fix-Darwin-target-detection.patch \ file://qemu-enlarge-env-entry-size.patch \ file://Qemu-Arm-versatilepb-Add-memory-size-checking.patch \ + file://smc91c111_fix.patch \ " SRC_URI_prepend = "http://wiki.qemu-project.org/download/${BP}.tar.bz2" SRC_URI[md5sum] = "186ee8194140a484a455f8e3c74589f4" -- cgit v1.2.3-54-g00ecf