All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 0/9] Ide patches
@ 2020-10-01 17:46 John Snow
  2020-10-01 17:46 ` [PULL 1/9] MAINTAINERS: Update my git address John Snow
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: John Snow, qemu-block

The following changes since commit 37a712a0f969ca2df7f01182409a6c4825cebfb5:

  Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2020-10-01 12:23:19 +0100)

are available in the Git repository at:

  https://gitlab.com/jsnow/qemu.git tags/ide-pull-request

for you to fetch changes up to 55adb3c45620c31f29978f209e2a44a08d34e2da:

  ide: cancel pending callbacks on SRST (2020-10-01 13:04:16 -0400)

----------------------------------------------------------------
Pull request

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

John Snow (8):
  MAINTAINERS: Update my git address
  ide: rename cmd_write to ctrl_write
  ide: don't tamper with the device register
  ide: model HOB correctly
  ide: reorder set/get sector functions
  ide: remove magic constants from the device register
  ide: clear interrupt on command write
  ide: cancel pending callbacks on SRST

Philippe Mathieu-Daudé (1):
  hw/ide/ahci: Do not dma_memory_unmap(NULL)

 include/hw/ide/internal.h |  21 +++++--
 hw/ide/ahci.c             |   2 +-
 hw/ide/core.c             | 124 +++++++++++++++++++++++---------------
 hw/ide/ioport.c           |   2 +-
 hw/ide/macio.c            |   2 +-
 hw/ide/mmio.c             |   8 +--
 hw/ide/pci.c              |  12 ++--
 MAINTAINERS               |   6 +-
 hw/ide/trace-events       |   2 +-
 9 files changed, 110 insertions(+), 69 deletions(-)

-- 
2.26.2




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

* [PULL 1/9] MAINTAINERS: Update my git address
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 17:46 ` [PULL 2/9] hw/ide/ahci: Do not dma_memory_unmap(NULL) John Snow
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: John Snow, qemu-block

I am switching from github to gitlab.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 MAINTAINERS | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index ade11002022..b76fb31861b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1577,7 +1577,7 @@ F: tests/qtest/ide-test.c
 F: tests/qtest/ahci-test.c
 F: tests/qtest/cdrom-test.c
 F: tests/qtest/libqos/ahci*
-T: git https://github.com/jnsnow/qemu.git ide
+T: git https://gitlab.com/jsnow/qemu.git ide
 
 IPMI
 M: Corey Minyard <minyard@acm.org>
@@ -1595,7 +1595,7 @@ S: Supported
 F: hw/block/fdc.c
 F: include/hw/block/fdc.h
 F: tests/qtest/fdc-test.c
-T: git https://github.com/jnsnow/qemu.git ide
+T: git https://gitlab.com/jsnow/qemu.git ide
 
 OMAP
 M: Peter Maydell <peter.maydell@linaro.org>
@@ -2169,7 +2169,7 @@ F: block/commit.c
 F: block/stream.c
 F: block/mirror.c
 F: qapi/job.json
-T: git https://github.com/jnsnow/qemu.git jobs
+T: git https://gitlab.com/jsnow/qemu.git jobs
 
 Block QAPI, monitor, command line
 M: Markus Armbruster <armbru@redhat.com>
-- 
2.26.2



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

* [PULL 2/9] hw/ide/ahci: Do not dma_memory_unmap(NULL)
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
  2020-10-01 17:46 ` [PULL 1/9] MAINTAINERS: Update my git address John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 17:46 ` [PULL 3/9] ide: rename cmd_write to ctrl_write John Snow
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Alexander Bulekov, John Snow, Philippe Mathieu-Daudé,
	qemu-block, qemu-stable

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

libFuzzer triggered the following assertion:

  cat << EOF | qemu-system-i386 -M pc-q35-5.0 \
    -nographic -monitor none -serial none -qtest stdio
  outl 0xcf8 0x8000fa24
  outl 0xcfc 0xe1068000
  outl 0xcf8 0x8000fa04
  outw 0xcfc 0x7
  outl 0xcf8 0x8000fb20
  write 0xe1068304 0x1 0x21
  write 0xe1068318 0x1 0x21
  write 0xe1068384 0x1 0x21
  write 0xe1068398 0x2 0x21
  EOF
  qemu-system-i386: exec.c:3621: address_space_unmap: Assertion `mr != NULL' failed.
  Aborted (core dumped)

This is because we don't check the return value from dma_memory_map()
which can return NULL, then we call dma_memory_unmap(NULL) which is
illegal. Fix by only unmap if the value is not NULL (and the size is
not the expected one).

Cc: qemu-stable@nongnu.org
Reported-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20200718072854.7001-1-f4bug@amsat.org
Fixes: f6ad2e32f8 ("ahci: add ahci emulation")
BugLink: https://bugs.launchpad.net/qemu/+bug/1884693
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
---
 hw/ide/ahci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index ee1d47ff756..680304a24c3 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -250,7 +250,7 @@ static void map_page(AddressSpace *as, uint8_t **ptr, uint64_t addr,
     }
 
     *ptr = dma_memory_map(as, addr, &len, DMA_DIRECTION_FROM_DEVICE);
-    if (len < wanted) {
+    if (len < wanted && *ptr) {
         dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len);
         *ptr = NULL;
     }
-- 
2.26.2



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

* [PULL 3/9] ide: rename cmd_write to ctrl_write
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
  2020-10-01 17:46 ` [PULL 1/9] MAINTAINERS: Update my git address John Snow
  2020-10-01 17:46 ` [PULL 2/9] hw/ide/ahci: Do not dma_memory_unmap(NULL) John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 17:46 ` [PULL 4/9] ide: don't tamper with the device register John Snow
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Philippe Mathieu-Daudé, John Snow, qemu-block

It's the Control register, part of the Control block -- Command is
misleading here. Rename all related functions and constants.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 include/hw/ide/internal.h |  9 +++++----
 hw/ide/core.c             | 12 ++++++------
 hw/ide/ioport.c           |  2 +-
 hw/ide/macio.c            |  2 +-
 hw/ide/mmio.c             |  8 ++++----
 hw/ide/pci.c              | 12 ++++++------
 hw/ide/trace-events       |  2 +-
 7 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index 8a95ad8c4d3..a23bb2f3481 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -57,8 +57,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS)
 #define REL			0x04
 #define TAG_MASK		0xf8
 
-#define IDE_CMD_RESET           0x04
-#define IDE_CMD_DISABLE_IRQ     0x02
+/* Bits of Device Control register */
+#define IDE_CTRL_RESET          0x04
+#define IDE_CTRL_DISABLE_IRQ    0x02
 
 /* ACS-2 T13/2015-D Table B.2 Command codes */
 #define WIN_NOP				0x00
@@ -559,7 +560,7 @@ static inline IDEState *idebus_active_if(IDEBus *bus)
 
 static inline void ide_set_irq(IDEBus *bus)
 {
-    if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
+    if (!(bus->cmd & IDE_CTRL_DISABLE_IRQ)) {
         qemu_irq_raise(bus->irq);
     }
 }
@@ -598,7 +599,7 @@ void ide_atapi_io_error(IDEState *s, int ret);
 void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_ioport_read(void *opaque, uint32_t addr1);
 uint32_t ide_status_read(void *opaque, uint32_t addr);
-void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val);
+void ide_ctrl_write(void *opaque, uint32_t addr, uint32_t val);
 void ide_data_writew(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_data_readw(void *opaque, uint32_t addr);
 void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index f76f7e5234b..84499e2241c 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2235,25 +2235,25 @@ uint32_t ide_status_read(void *opaque, uint32_t addr)
     return ret;
 }
 
-void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
+void ide_ctrl_write(void *opaque, uint32_t addr, uint32_t val)
 {
     IDEBus *bus = opaque;
     IDEState *s;
     int i;
 
-    trace_ide_cmd_write(addr, val, bus);
+    trace_ide_ctrl_write(addr, val, bus);
 
     /* common for both drives */
-    if (!(bus->cmd & IDE_CMD_RESET) &&
-        (val & IDE_CMD_RESET)) {
+    if (!(bus->cmd & IDE_CTRL_RESET) &&
+        (val & IDE_CTRL_RESET)) {
         /* reset low to high */
         for(i = 0;i < 2; i++) {
             s = &bus->ifs[i];
             s->status = BUSY_STAT | SEEK_STAT;
             s->error = 0x01;
         }
-    } else if ((bus->cmd & IDE_CMD_RESET) &&
-               !(val & IDE_CMD_RESET)) {
+    } else if ((bus->cmd & IDE_CTRL_RESET) &&
+               !(val & IDE_CTRL_RESET)) {
         /* high to low */
         for(i = 0;i < 2; i++) {
             s = &bus->ifs[i];
diff --git a/hw/ide/ioport.c b/hw/ide/ioport.c
index ab1f4e5d9c0..b613ff3bbaf 100644
--- a/hw/ide/ioport.c
+++ b/hw/ide/ioport.c
@@ -46,7 +46,7 @@ static const MemoryRegionPortio ide_portio_list[] = {
 };
 
 static const MemoryRegionPortio ide_portio2_list[] = {
-    { 0, 1, 1, .read = ide_status_read, .write = ide_cmd_write },
+    { 0, 1, 1, .read = ide_status_read, .write = ide_ctrl_write },
     PORTIO_END_OF_LIST(),
 };
 
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 62a599a0751..b270a101632 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -329,7 +329,7 @@ static void pmac_ide_write(void *opaque, hwaddr addr, uint64_t val,
     case 0x8:
     case 0x16:
         if (size == 1) {
-            ide_cmd_write(&d->bus, 0, val);
+            ide_ctrl_write(&d->bus, 0, val);
         }
         break;
     case 0x20:
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 4bf6e3a8b76..36e2f4790ab 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -98,16 +98,16 @@ static uint64_t mmio_ide_status_read(void *opaque, hwaddr addr,
     return ide_status_read(&s->bus, 0);
 }
 
-static void mmio_ide_cmd_write(void *opaque, hwaddr addr,
-                               uint64_t val, unsigned size)
+static void mmio_ide_ctrl_write(void *opaque, hwaddr addr,
+                                uint64_t val, unsigned size)
 {
     MMIOState *s = opaque;
-    ide_cmd_write(&s->bus, 0, val);
+    ide_ctrl_write(&s->bus, 0, val);
 }
 
 static const MemoryRegionOps mmio_ide_cs_ops = {
     .read = mmio_ide_status_read,
-    .write = mmio_ide_cmd_write,
+    .write = mmio_ide_ctrl_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index b50091b615c..84ba733548e 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -38,7 +38,7 @@
         (IDE_RETRY_DMA | IDE_RETRY_PIO | \
         IDE_RETRY_READ | IDE_RETRY_FLUSH)
 
-static uint64_t pci_ide_cmd_read(void *opaque, hwaddr addr, unsigned size)
+static uint64_t pci_ide_status_read(void *opaque, hwaddr addr, unsigned size)
 {
     IDEBus *bus = opaque;
 
@@ -48,20 +48,20 @@ static uint64_t pci_ide_cmd_read(void *opaque, hwaddr addr, unsigned size)
     return ide_status_read(bus, addr + 2);
 }
 
-static void pci_ide_cmd_write(void *opaque, hwaddr addr,
-                              uint64_t data, unsigned size)
+static void pci_ide_ctrl_write(void *opaque, hwaddr addr,
+                               uint64_t data, unsigned size)
 {
     IDEBus *bus = opaque;
 
     if (addr != 2 || size != 1) {
         return;
     }
-    ide_cmd_write(bus, addr + 2, data);
+    ide_ctrl_write(bus, addr + 2, data);
 }
 
 const MemoryRegionOps pci_ide_cmd_le_ops = {
-    .read = pci_ide_cmd_read,
-    .write = pci_ide_cmd_write,
+    .read = pci_ide_status_read,
+    .write = pci_ide_ctrl_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
diff --git a/hw/ide/trace-events b/hw/ide/trace-events
index 2e4162629f4..6e357685f9b 100644
--- a/hw/ide/trace-events
+++ b/hw/ide/trace-events
@@ -5,7 +5,7 @@
 ide_ioport_read(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s)  "IDE PIO rd @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p"
 ide_ioport_write(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p"
 ide_status_read(uint32_t addr, uint32_t val, void *bus, void *s)                   "IDE PIO rd @ 0x%"PRIx32" (Alt Status); val 0x%02"PRIx32"; bus %p; IDEState %p"
-ide_cmd_write(uint32_t addr, uint32_t val, void *bus)                              "IDE PIO wr @ 0x%"PRIx32" (Device Control); val 0x%02"PRIx32"; bus %p"
+ide_ctrl_write(uint32_t addr, uint32_t val, void *bus)                             "IDE PIO wr @ 0x%"PRIx32" (Device Control); val 0x%02"PRIx32"; bus %p"
 # Warning: verbose
 ide_data_readw(uint32_t addr, uint32_t val, void *bus, void *s)                    "IDE PIO rd @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p"
 ide_data_writew(uint32_t addr, uint32_t val, void *bus, void *s)                   "IDE PIO wr @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p"
-- 
2.26.2



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

* [PULL 4/9] ide: don't tamper with the device register
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
                   ` (2 preceding siblings ...)
  2020-10-01 17:46 ` [PULL 3/9] ide: rename cmd_write to ctrl_write John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 17:46 ` [PULL 5/9] ide: model HOB correctly John Snow
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: John Snow, qemu-block

In real ISA operation, register writes go out to an entire bus channel
and all listening devices receive the write. The devices do not toggle
the DEV bit based on their own configuration, nor does the HBA
intermediate or tamper with that value.

The reality of the matter is that DEV0/DEV1 accordingly will react to
command register writes based on whether or not the device was selected.

This does not fix a known bug, but it makes the code slightly simpler
and more obvious.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 hw/ide/core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 84499e2241c..29dc5dc4b45 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1297,8 +1297,8 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         break;
     case ATA_IOPORT_WR_DEVICE_HEAD:
         /* FIXME: HOB readback uses bit 7 */
-        bus->ifs[0].select = (val & ~0x10) | 0xa0;
-        bus->ifs[1].select = (val | 0x10) | 0xa0;
+        bus->ifs[0].select = val | 0xa0;
+        bus->ifs[1].select = val | 0xa0;
         /* select drive */
         bus->unit = (val >> 4) & 1;
         break;
-- 
2.26.2



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

* [PULL 5/9] ide: model HOB correctly
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
                   ` (3 preceding siblings ...)
  2020-10-01 17:46 ` [PULL 4/9] ide: don't tamper with the device register John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 17:46 ` [PULL 6/9] ide: reorder set/get sector functions John Snow
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: John Snow, qemu-block

I have been staring at this FIXME for years and I never knew what it
meant. I finally stumbled across it!

When writing to the command registers, the old value is shifted into a
HOB copy of the register and the new value is written into the primary
register. When reading registers, the value retrieved is dependent on
the HOB bit in the CONTROL register.

By setting bit 7 (0x80) in CONTROL, any register read will, if it has
one, yield the HOB value for that register instead.

Our code has a problem: We were using bit 7 of the DEVICE register to
model this. We use bus->cmd roughly as the control register already, as
it stores the value from ide_ctrl_write.

Lastly, all command register writes reset the HOB, so fix that, too.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 include/hw/ide/internal.h |  1 +
 hw/ide/core.c             | 15 +++++++--------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index a23bb2f3481..5b7b0e47e60 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -58,6 +58,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS)
 #define TAG_MASK		0xf8
 
 /* Bits of Device Control register */
+#define IDE_CTRL_HOB            0x80
 #define IDE_CTRL_RESET          0x04
 #define IDE_CTRL_DISABLE_IRQ    0x02
 
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 29dc5dc4b45..6ececa5dfee 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1215,8 +1215,7 @@ static void ide_cmd_lba48_transform(IDEState *s, int lba48)
 static void ide_clear_hob(IDEBus *bus)
 {
     /* any write clears HOB high bit of device control register */
-    bus->ifs[0].select &= ~(1 << 7);
-    bus->ifs[1].select &= ~(1 << 7);
+    bus->cmd &= ~(IDE_CTRL_HOB);
 }
 
 /* IOport [W]rite [R]egisters */
@@ -1256,12 +1255,14 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         return;
     }
 
+    /* NOTE: Device0 and Device1 both receive incoming register writes.
+     * (They're on the same bus! They have to!) */
+
     switch (reg_num) {
     case 0:
         break;
     case ATA_IOPORT_WR_FEATURES:
         ide_clear_hob(bus);
-        /* NOTE: data is written to the two drives */
         bus->ifs[0].hob_feature = bus->ifs[0].feature;
         bus->ifs[1].hob_feature = bus->ifs[1].feature;
         bus->ifs[0].feature = val;
@@ -1296,7 +1297,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         bus->ifs[1].hcyl = val;
         break;
     case ATA_IOPORT_WR_DEVICE_HEAD:
-        /* FIXME: HOB readback uses bit 7 */
+        ide_clear_hob(bus);
         bus->ifs[0].select = val | 0xa0;
         bus->ifs[1].select = val | 0xa0;
         /* select drive */
@@ -1304,7 +1305,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         break;
     default:
     case ATA_IOPORT_WR_COMMAND:
-        /* command */
+        ide_clear_hob(bus);
         ide_exec_cmd(bus, val);
         break;
     }
@@ -2142,9 +2143,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr)
     int ret, hob;
 
     reg_num = addr & 7;
-    /* FIXME: HOB readback uses bit 7, but it's always set right now */
-    //hob = s->select & (1 << 7);
-    hob = 0;
+    hob = bus->cmd & (IDE_CTRL_HOB);
     switch (reg_num) {
     case ATA_IOPORT_RR_DATA:
         ret = 0xff;
-- 
2.26.2



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

* [PULL 6/9] ide: reorder set/get sector functions
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
                   ` (4 preceding siblings ...)
  2020-10-01 17:46 ` [PULL 5/9] ide: model HOB correctly John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 17:46 ` [PULL 7/9] ide: remove magic constants from the device register John Snow
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Philippe Mathieu-Daudé, John Snow, qemu-block

Reorder these just a pinch to make them more obvious at a glance what
the addressing mode is.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/ide/core.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 6ececa5dfee..afff355e5c6 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -587,21 +587,23 @@ int64_t ide_get_sector(IDEState *s)
 {
     int64_t sector_num;
     if (s->select & 0x40) {
-        /* lba */
-        if (!s->lba48) {
-            sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
-                (s->lcyl << 8) | s->sector;
-        } else {
+        if (s->lba48) {
             sector_num = ((int64_t)s->hob_hcyl << 40) |
                 ((int64_t) s->hob_lcyl << 32) |
                 ((int64_t) s->hob_sector << 24) |
                 ((int64_t) s->hcyl << 16) |
                 ((int64_t) s->lcyl << 8) | s->sector;
+        } else {
+            /* LBA28 */
+            sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
+                (s->lcyl << 8) | s->sector;
         }
     } else {
+        /* CHS */
         sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
             (s->select & 0x0f) * s->sectors + (s->sector - 1);
     }
+
     return sector_num;
 }
 
@@ -609,20 +611,22 @@ void ide_set_sector(IDEState *s, int64_t sector_num)
 {
     unsigned int cyl, r;
     if (s->select & 0x40) {
-        if (!s->lba48) {
-            s->select = (s->select & 0xf0) | (sector_num >> 24);
-            s->hcyl = (sector_num >> 16);
-            s->lcyl = (sector_num >> 8);
-            s->sector = (sector_num);
-        } else {
+        if (s->lba48) {
             s->sector = sector_num;
             s->lcyl = sector_num >> 8;
             s->hcyl = sector_num >> 16;
             s->hob_sector = sector_num >> 24;
             s->hob_lcyl = sector_num >> 32;
             s->hob_hcyl = sector_num >> 40;
+        } else {
+            /* LBA28 */
+            s->select = (s->select & 0xf0) | (sector_num >> 24);
+            s->hcyl = (sector_num >> 16);
+            s->lcyl = (sector_num >> 8);
+            s->sector = (sector_num);
         }
     } else {
+        /* CHS */
         cyl = sector_num / (s->heads * s->sectors);
         r = sector_num % (s->heads * s->sectors);
         s->hcyl = cyl >> 8;
-- 
2.26.2



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

* [PULL 7/9] ide: remove magic constants from the device register
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
                   ` (5 preceding siblings ...)
  2020-10-01 17:46 ` [PULL 6/9] ide: reorder set/get sector functions John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 17:46 ` [PULL 8/9] ide: clear interrupt on command write John Snow
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: John Snow, qemu-block

(In QEMU, we call this the "select" register.)

My memory isn't good enough to memorize what these magic runes
do. Label them to prevent mixups from happening in the future.

Side note: I assume it's safe to always set 0xA0 even though ATA2 claims
these bits are reserved, because ATA3 immediately reinstated that these
bits should be always on. ATA4 and subsequent specs only claim that the
fields are obsolete, so I assume it's safe to leave these set and that
it should work with the widest array of guests.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 include/hw/ide/internal.h | 11 +++++++++++
 hw/ide/core.c             | 26 ++++++++++++++------------
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index 5b7b0e47e60..2d09162eeb7 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -29,6 +29,17 @@ OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS)
 
 #define MAX_IDE_DEVS 2
 
+/* Device/Head ("select") Register */
+#define ATA_DEV_SELECT          0x10
+/* ATA1,3: Defined as '1'.
+ * ATA2:   Reserved.
+ * ATA3-7: obsolete. */
+#define ATA_DEV_ALWAYS_ON       0xA0
+#define ATA_DEV_LBA             0x40
+#define ATA_DEV_LBA_MSB         0x0F  /* LBA 24:27 */
+#define ATA_DEV_HS              0x0F  /* HS 3:0 */
+
+
 /* Bits of HD_STATUS */
 #define ERR_STAT		0x01
 #define INDEX_STAT		0x02
diff --git a/hw/ide/core.c b/hw/ide/core.c
index afff355e5c6..8a55352e4b2 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -367,7 +367,7 @@ fill_buffer:
 
 static void ide_set_signature(IDEState *s)
 {
-    s->select &= 0xf0; /* clear head */
+    s->select &= ~(ATA_DEV_HS); /* clear head */
     /* put signature */
     s->nsector = 1;
     s->sector = 1;
@@ -586,7 +586,7 @@ void ide_transfer_stop(IDEState *s)
 int64_t ide_get_sector(IDEState *s)
 {
     int64_t sector_num;
-    if (s->select & 0x40) {
+    if (s->select & (ATA_DEV_LBA)) {
         if (s->lba48) {
             sector_num = ((int64_t)s->hob_hcyl << 40) |
                 ((int64_t) s->hob_lcyl << 32) |
@@ -595,13 +595,13 @@ int64_t ide_get_sector(IDEState *s)
                 ((int64_t) s->lcyl << 8) | s->sector;
         } else {
             /* LBA28 */
-            sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
-                (s->lcyl << 8) | s->sector;
+            sector_num = ((s->select & (ATA_DEV_LBA_MSB)) << 24) |
+                (s->hcyl << 16) | (s->lcyl << 8) | s->sector;
         }
     } else {
         /* CHS */
         sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
-            (s->select & 0x0f) * s->sectors + (s->sector - 1);
+            (s->select & (ATA_DEV_HS)) * s->sectors + (s->sector - 1);
     }
 
     return sector_num;
@@ -610,7 +610,7 @@ int64_t ide_get_sector(IDEState *s)
 void ide_set_sector(IDEState *s, int64_t sector_num)
 {
     unsigned int cyl, r;
-    if (s->select & 0x40) {
+    if (s->select & (ATA_DEV_LBA)) {
         if (s->lba48) {
             s->sector = sector_num;
             s->lcyl = sector_num >> 8;
@@ -620,7 +620,8 @@ void ide_set_sector(IDEState *s, int64_t sector_num)
             s->hob_hcyl = sector_num >> 40;
         } else {
             /* LBA28 */
-            s->select = (s->select & 0xf0) | (sector_num >> 24);
+            s->select = (s->select & ~(ATA_DEV_LBA_MSB)) |
+                ((sector_num >> 24) & (ATA_DEV_LBA_MSB));
             s->hcyl = (sector_num >> 16);
             s->lcyl = (sector_num >> 8);
             s->sector = (sector_num);
@@ -631,7 +632,8 @@ void ide_set_sector(IDEState *s, int64_t sector_num)
         r = sector_num % (s->heads * s->sectors);
         s->hcyl = cyl >> 8;
         s->lcyl = cyl;
-        s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
+        s->select = (s->select & ~(ATA_DEV_HS)) |
+            ((r / s->sectors) & (ATA_DEV_HS));
         s->sector = (r % s->sectors) + 1;
     }
 }
@@ -1302,10 +1304,10 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         break;
     case ATA_IOPORT_WR_DEVICE_HEAD:
         ide_clear_hob(bus);
-        bus->ifs[0].select = val | 0xa0;
-        bus->ifs[1].select = val | 0xa0;
+        bus->ifs[0].select = val | (ATA_DEV_ALWAYS_ON);
+        bus->ifs[1].select = val | (ATA_DEV_ALWAYS_ON);
         /* select drive */
-        bus->unit = (val >> 4) & 1;
+        bus->unit = (val & (ATA_DEV_SELECT)) ? 1 : 0;
         break;
     default:
     case ATA_IOPORT_WR_COMMAND:
@@ -1343,7 +1345,7 @@ static void ide_reset(IDEState *s)
     s->hob_lcyl = 0;
     s->hob_hcyl = 0;
 
-    s->select = 0xa0;
+    s->select = (ATA_DEV_ALWAYS_ON);
     s->status = READY_STAT | SEEK_STAT;
 
     s->lba48 = 0;
-- 
2.26.2



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

* [PULL 8/9] ide: clear interrupt on command write
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
                   ` (6 preceding siblings ...)
  2020-10-01 17:46 ` [PULL 7/9] ide: remove magic constants from the device register John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 17:46 ` [PULL 9/9] ide: cancel pending callbacks on SRST John Snow
  2020-10-01 20:43 ` [PULL 0/9] Ide patches Peter Maydell
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: John Snow, qemu-block

Not known to fix any bug, but I couldn't help but notice that ATA
specifies that writing to this register should clear an interrupt.

ATA7: Section 5.3.3 (Command register - Effect)
ATA6: Section 7.4.4 (Command register - Effect)
ATA5: Section 7.4.4 (Command register - Effect)
ATA4: Section 7.4.4 (Command register - Effect)
ATA3: Section 5.2.2 (Command register)

Other editions: try searching for the phrase "Writing this register".

Signed-off-by: John Snow <jsnow@redhat.com>
---
 hw/ide/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 8a55352e4b2..0d745d63a18 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1312,6 +1312,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     default:
     case ATA_IOPORT_WR_COMMAND:
         ide_clear_hob(bus);
+        qemu_irq_lower(bus->irq);
         ide_exec_cmd(bus, val);
         break;
     }
-- 
2.26.2



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

* [PULL 9/9] ide: cancel pending callbacks on SRST
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
                   ` (7 preceding siblings ...)
  2020-10-01 17:46 ` [PULL 8/9] ide: clear interrupt on command write John Snow
@ 2020-10-01 17:46 ` John Snow
  2020-10-01 20:43 ` [PULL 0/9] Ide patches Peter Maydell
  9 siblings, 0 replies; 11+ messages in thread
From: John Snow @ 2020-10-01 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: Alexander Bulekov, John Snow, qemu-block

The SRST implementation did not keep up with the rest of IDE; it is
possible to perform a weak reset on an IDE device to remove the BSY/DRQ
bits, and then issue writes to the control/device registers which can
cause chaos with the state machine.

Fix that by actually performing a real reset.

Reported-by: Alexander Bulekov <alxndr@bu.edu>
Fixes: https://bugs.launchpad.net/qemu/+bug/1878253
Fixes: https://bugs.launchpad.net/qemu/+bug/1887303
Fixes: https://bugs.launchpad.net/qemu/+bug/1887309
Signed-off-by: John Snow <jsnow@redhat.com>
---
 hw/ide/core.c | 58 +++++++++++++++++++++++++++++++++++----------------
 1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 0d745d63a18..0e32abd7796 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2241,6 +2241,37 @@ uint32_t ide_status_read(void *opaque, uint32_t addr)
     return ret;
 }
 
+static void ide_perform_srst(IDEState *s)
+{
+    s->status |= BUSY_STAT;
+
+    /* Halt PIO (Via register state); PIO BH remains scheduled. */
+    ide_transfer_halt(s);
+
+    /* Cancel DMA -- may drain block device and invoke callbacks */
+    ide_cancel_dma_sync(s);
+
+    /* Cancel PIO callback, reset registers/signature, etc */
+    ide_reset(s);
+
+    if (s->drive_kind == IDE_CD) {
+        /* ATAPI drives do not set READY or SEEK */
+        s->status = 0x00;
+    }
+}
+
+static void ide_bus_perform_srst(void *opaque)
+{
+    IDEBus *bus = opaque;
+    IDEState *s;
+    int i;
+
+    for (i = 0; i < 2; i++) {
+        s = &bus->ifs[i];
+        ide_perform_srst(s);
+    }
+}
+
 void ide_ctrl_write(void *opaque, uint32_t addr, uint32_t val)
 {
     IDEBus *bus = opaque;
@@ -2249,26 +2280,17 @@ void ide_ctrl_write(void *opaque, uint32_t addr, uint32_t val)
 
     trace_ide_ctrl_write(addr, val, bus);
 
-    /* common for both drives */
-    if (!(bus->cmd & IDE_CTRL_RESET) &&
-        (val & IDE_CTRL_RESET)) {
-        /* reset low to high */
-        for(i = 0;i < 2; i++) {
+    /* Device0 and Device1 each have their own control register,
+     * but QEMU models it as just one register in the controller. */
+    if ((bus->cmd & IDE_CTRL_RESET) &&
+        !(val & IDE_CTRL_RESET)) {
+        /* SRST triggers on falling edge */
+        for (i = 0; i < 2; i++) {
             s = &bus->ifs[i];
-            s->status = BUSY_STAT | SEEK_STAT;
-            s->error = 0x01;
-        }
-    } else if ((bus->cmd & IDE_CTRL_RESET) &&
-               !(val & IDE_CTRL_RESET)) {
-        /* high to low */
-        for(i = 0;i < 2; i++) {
-            s = &bus->ifs[i];
-            if (s->drive_kind == IDE_CD)
-                s->status = 0x00; /* NOTE: READY is _not_ set */
-            else
-                s->status = READY_STAT | SEEK_STAT;
-            ide_set_signature(s);
+            s->status |= BUSY_STAT;
         }
+        aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                ide_bus_perform_srst, bus);
     }
 
     bus->cmd = val;
-- 
2.26.2



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

* Re: [PULL 0/9] Ide patches
  2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
                   ` (8 preceding siblings ...)
  2020-10-01 17:46 ` [PULL 9/9] ide: cancel pending callbacks on SRST John Snow
@ 2020-10-01 20:43 ` Peter Maydell
  9 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2020-10-01 20:43 UTC (permalink / raw)
  To: John Snow; +Cc: QEMU Developers, Qemu-block

On Thu, 1 Oct 2020 at 18:46, John Snow <jsnow@redhat.com> wrote:
>
> The following changes since commit 37a712a0f969ca2df7f01182409a6c4825cebfb5:
>
>   Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2020-10-01 12:23:19 +0100)
>
> are available in the Git repository at:
>
>   https://gitlab.com/jsnow/qemu.git tags/ide-pull-request
>
> for you to fetch changes up to 55adb3c45620c31f29978f209e2a44a08d34e2da:
>
>   ide: cancel pending callbacks on SRST (2020-10-01 13:04:16 -0400)
>
> ----------------------------------------------------------------
> Pull request
>
> ----------------------------------------------------------------


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/5.2
for any user-visible changes.

-- PMM


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

end of thread, other threads:[~2020-10-01 20:47 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-01 17:46 [PULL 0/9] Ide patches John Snow
2020-10-01 17:46 ` [PULL 1/9] MAINTAINERS: Update my git address John Snow
2020-10-01 17:46 ` [PULL 2/9] hw/ide/ahci: Do not dma_memory_unmap(NULL) John Snow
2020-10-01 17:46 ` [PULL 3/9] ide: rename cmd_write to ctrl_write John Snow
2020-10-01 17:46 ` [PULL 4/9] ide: don't tamper with the device register John Snow
2020-10-01 17:46 ` [PULL 5/9] ide: model HOB correctly John Snow
2020-10-01 17:46 ` [PULL 6/9] ide: reorder set/get sector functions John Snow
2020-10-01 17:46 ` [PULL 7/9] ide: remove magic constants from the device register John Snow
2020-10-01 17:46 ` [PULL 8/9] ide: clear interrupt on command write John Snow
2020-10-01 17:46 ` [PULL 9/9] ide: cancel pending callbacks on SRST John Snow
2020-10-01 20:43 ` [PULL 0/9] Ide patches Peter Maydell

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.