diff mbox series

[v5,12/28] hw/block/pflash_cfi02: Fix command address comparison

Message ID 20190627202719.17739-13-philmd@redhat.com
State New
Headers show
Series block/pflash_cfi02: Implement missing AMD pflash functionality | expand

Commit Message

Philippe Mathieu-Daudé June 27, 2019, 8:27 p.m. UTC
From: Stephen Checkoway <stephen.checkoway@oberlin.edu>

Most AMD commands only examine 11 bits of the address. This masks the
addresses used in the comparison to 11 bits. The exceptions are word or
sector addresses which use offset directly rather than the shifted
offset, boff.

Signed-off-by: Stephen Checkoway <stephen.checkoway@oberlin.edu>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20190426162624.55977-4-stephen.checkoway@oberlin.edu>
[PMD: Prepend 'hw/' in patch subject]
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/block/pflash_cfi02.c   |  8 +++++++-
 tests/pflash-cfi02-test.c | 12 ++++++++++--
 2 files changed, 17 insertions(+), 3 deletions(-)

Comments

Alistair Francis June 28, 2019, 4:28 p.m. UTC | #1
On Thu, Jun 27, 2019 at 1:42 PM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> From: Stephen Checkoway <stephen.checkoway@oberlin.edu>
>
> Most AMD commands only examine 11 bits of the address. This masks the
> addresses used in the comparison to 11 bits. The exceptions are word or
> sector addresses which use offset directly rather than the shifted
> offset, boff.
>
> Signed-off-by: Stephen Checkoway <stephen.checkoway@oberlin.edu>
> Acked-by: Thomas Huth <thuth@redhat.com>
> Message-Id: <20190426162624.55977-4-stephen.checkoway@oberlin.edu>
> [PMD: Prepend 'hw/' in patch subject]
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/block/pflash_cfi02.c   |  8 +++++++-
>  tests/pflash-cfi02-test.c | 12 ++++++++++--
>  2 files changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
> index e64dc69c6c..4be3837be5 100644
> --- a/hw/block/pflash_cfi02.c
> +++ b/hw/block/pflash_cfi02.c
> @@ -281,11 +281,13 @@ static void pflash_write(void *opaque, hwaddr offset, uint64_t value,
>      }
>      offset &= pfl->chip_len - 1;
>
> -    boff = offset & (pfl->sector_len - 1);
> +    boff = offset;
>      if (pfl->width == 2)
>          boff = boff >> 1;
>      else if (pfl->width == 4)
>          boff = boff >> 2;
> +    /* Only the least-significant 11 bits are used in most cases. */
> +    boff &= 0x7FF;
>      switch (pfl->wcycle) {
>      case 0:
>          /* Set the device in I/O access mode if required */
> @@ -538,6 +540,10 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
>          }
>      }
>
> +    /* Only 11 bits are used in the comparison. */
> +    pfl->unlock_addr0 &= 0x7FF;
> +    pfl->unlock_addr1 &= 0x7FF;
> +
>      pflash_setup_mappings(pfl);
>      pfl->rom_mode = 1;
>      sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
> diff --git a/tests/pflash-cfi02-test.c b/tests/pflash-cfi02-test.c
> index e7e16a8dd8..e090b2e3a0 100644
> --- a/tests/pflash-cfi02-test.c
> +++ b/tests/pflash-cfi02-test.c
> @@ -21,8 +21,8 @@
>
>  #define FLASH_WIDTH 2
>  #define CFI_ADDR (FLASH_WIDTH * 0x55)
> -#define UNLOCK0_ADDR (FLASH_WIDTH * 0x5555)
> -#define UNLOCK1_ADDR (FLASH_WIDTH * 0x2AAA)
> +#define UNLOCK0_ADDR (FLASH_WIDTH * 0x555)
> +#define UNLOCK1_ADDR (FLASH_WIDTH * 0x2AA)
>
>  #define CFI_CMD 0x98
>  #define UNLOCK0_CMD 0xAA
> @@ -190,6 +190,14 @@ static void test_flash(void)
>      g_assert_cmphex(flash_read(6), ==, 0xCDEF);
>      g_assert_cmphex(flash_read(8), ==, 0xFFFF);
>
> +    /* Test ignored high order bits of address. */
> +    flash_write(FLASH_WIDTH * 0x5555, UNLOCK0_CMD);
> +    flash_write(FLASH_WIDTH * 0x2AAA, UNLOCK1_CMD);
> +    flash_write(FLASH_WIDTH * 0x5555, AUTOSELECT_CMD);
> +    g_assert_cmpint(flash_read(FLASH_WIDTH * 0x0000), ==, 0x00BF);
> +    g_assert_cmpint(flash_read(FLASH_WIDTH * 0x0001), ==, 0x236D);
> +    reset();
> +
>      qtest_quit(global_qtest);
>  }
>
> --
> 2.20.1
>
>
diff mbox series

Patch

diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index e64dc69c6c..4be3837be5 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -281,11 +281,13 @@  static void pflash_write(void *opaque, hwaddr offset, uint64_t value,
     }
     offset &= pfl->chip_len - 1;
 
-    boff = offset & (pfl->sector_len - 1);
+    boff = offset;
     if (pfl->width == 2)
         boff = boff >> 1;
     else if (pfl->width == 4)
         boff = boff >> 2;
+    /* Only the least-significant 11 bits are used in most cases. */
+    boff &= 0x7FF;
     switch (pfl->wcycle) {
     case 0:
         /* Set the device in I/O access mode if required */
@@ -538,6 +540,10 @@  static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
         }
     }
 
+    /* Only 11 bits are used in the comparison. */
+    pfl->unlock_addr0 &= 0x7FF;
+    pfl->unlock_addr1 &= 0x7FF;
+
     pflash_setup_mappings(pfl);
     pfl->rom_mode = 1;
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
diff --git a/tests/pflash-cfi02-test.c b/tests/pflash-cfi02-test.c
index e7e16a8dd8..e090b2e3a0 100644
--- a/tests/pflash-cfi02-test.c
+++ b/tests/pflash-cfi02-test.c
@@ -21,8 +21,8 @@ 
 
 #define FLASH_WIDTH 2
 #define CFI_ADDR (FLASH_WIDTH * 0x55)
-#define UNLOCK0_ADDR (FLASH_WIDTH * 0x5555)
-#define UNLOCK1_ADDR (FLASH_WIDTH * 0x2AAA)
+#define UNLOCK0_ADDR (FLASH_WIDTH * 0x555)
+#define UNLOCK1_ADDR (FLASH_WIDTH * 0x2AA)
 
 #define CFI_CMD 0x98
 #define UNLOCK0_CMD 0xAA
@@ -190,6 +190,14 @@  static void test_flash(void)
     g_assert_cmphex(flash_read(6), ==, 0xCDEF);
     g_assert_cmphex(flash_read(8), ==, 0xFFFF);
 
+    /* Test ignored high order bits of address. */
+    flash_write(FLASH_WIDTH * 0x5555, UNLOCK0_CMD);
+    flash_write(FLASH_WIDTH * 0x2AAA, UNLOCK1_CMD);
+    flash_write(FLASH_WIDTH * 0x5555, AUTOSELECT_CMD);
+    g_assert_cmpint(flash_read(FLASH_WIDTH * 0x0000), ==, 0x00BF);
+    g_assert_cmpint(flash_read(FLASH_WIDTH * 0x0001), ==, 0x236D);
+    reset();
+
     qtest_quit(global_qtest);
 }