* [Qemu-devel] [PATCH-for-4.1 v4 0/5] hw/block/pflash_cfi01: Add DeviceReset() handler
@ 2019-07-11 15:56 Philippe Mathieu-Daudé
2019-07-11 15:56 ` [Qemu-devel] [PATCH-for-4.1 v4 1/5] hw/block/pflash_cfi01: Removed an unused timer Philippe Mathieu-Daudé
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-11 15:56 UTC (permalink / raw)
To: Dr . David Alan Gilbert, qemu-devel
Cc: Kevin Wolf, Philippe Mathieu-Daudé, qemu-block, Max Reitz
The pflash device lacks a reset() function.
When a machine is resetted, the flash might be in an
inconsistent state, leading to unexpected behavior:
https://bugzilla.redhat.com/show_bug.cgi?id=1678713
Resolve this issue by adding a DeviceReset() handler.
Fix also two minor issues, and clean a bit the codebase.
Since v1: https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg00962.html
- addressed Laszlo review comments
Since v2:
- consider migration (Laszlo, Peter)
Since v3:
- more reliable migration (Dave)
- dropped patches 6-9 not required for next release
$ git backport-diff -u v3
Key:
[----] : patches are identical
[####] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively
001/5:[----] [--] 'hw/block/pflash_cfi01: Removed an unused timer'
002/5:[0048] [FC] 'hw/block/pflash_cfi01: Use the correct READ_ARRAY value'
003/5:[----] [--] 'hw/block/pflash_cfi01: Extract pflash_mode_read_array()'
004/5:[----] [--] 'hw/block/pflash_cfi01: Start state machine as READY to accept commands'
005/5:[----] [--] 'hw/block/pflash_cfi01: Add the DeviceReset() handler'
Regards,
Phil.
Philippe Mathieu-Daudé (5):
hw/block/pflash_cfi01: Removed an unused timer
hw/block/pflash_cfi01: Use the correct READ_ARRAY value
hw/block/pflash_cfi01: Extract pflash_mode_read_array()
hw/block/pflash_cfi01: Start state machine as READY to accept commands
hw/block/pflash_cfi01: Add the DeviceReset() handler
hw/block/pflash_cfi01.c | 109 +++++++++++++++++++++++++++-------------
hw/block/trace-events | 1 +
2 files changed, 75 insertions(+), 35 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH-for-4.1 v4 1/5] hw/block/pflash_cfi01: Removed an unused timer
2019-07-11 15:56 [Qemu-devel] [PATCH-for-4.1 v4 0/5] hw/block/pflash_cfi01: Add DeviceReset() handler Philippe Mathieu-Daudé
@ 2019-07-11 15:56 ` Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value Philippe Mathieu-Daudé
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-11 15:56 UTC (permalink / raw)
To: Dr . David Alan Gilbert, qemu-devel
Cc: Kevin Wolf, qemu-block, Philippe Mathieu-Daudé, Max Reitz,
Alistair Francis, Wei Yang, Laszlo Ersek
The 'CFI02' NOR flash was introduced in commit 29133e9a0fff, with
timing modelled. One year later, the CFI01 model was introduced
(commit 05ee37ebf630) based on the CFI02 model. As noted in the
header, "It does not support timings". 12 years later, we never
had to model the device timings. Time to remove the unused timer,
we can still add it back if required.
Suggested-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Wei Yang <richardw.yang@linux.intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
v2: Fixed commit description (Laszlo)
---
hw/block/pflash_cfi01.c | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index db4a246b22..9e34fd4e82 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -42,7 +42,6 @@
#include "hw/block/flash.h"
#include "sysemu/block-backend.h"
#include "qapi/error.h"
-#include "qemu/timer.h"
#include "qemu/bitops.h"
#include "qemu/error-report.h"
#include "qemu/host-utils.h"
@@ -90,7 +89,6 @@ struct PFlashCFI01 {
uint8_t cfi_table[0x52];
uint64_t counter;
unsigned int writeblock_size;
- QEMUTimer *timer;
MemoryRegion mem;
char *name;
void *storage;
@@ -114,18 +112,6 @@ static const VMStateDescription vmstate_pflash = {
}
};
-static void pflash_timer (void *opaque)
-{
- PFlashCFI01 *pfl = opaque;
-
- trace_pflash_timer_expired(pfl->cmd);
- /* Reset flash */
- pfl->status ^= 0x80;
- memory_region_rom_device_set_romd(&pfl->mem, true);
- pfl->wcycle = 0;
- pfl->cmd = 0;
-}
-
/* Perform a CFI query based on the bank width of the flash.
* If this code is called we know we have a device_width set for
* this flash.
@@ -774,7 +760,6 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
pfl->max_device_width = pfl->device_width;
}
- pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
--
2.20.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value
2019-07-11 15:56 [Qemu-devel] [PATCH-for-4.1 v4 0/5] hw/block/pflash_cfi01: Add DeviceReset() handler Philippe Mathieu-Daudé
2019-07-11 15:56 ` [Qemu-devel] [PATCH-for-4.1 v4 1/5] hw/block/pflash_cfi01: Removed an unused timer Philippe Mathieu-Daudé
@ 2019-07-11 15:57 ` Philippe Mathieu-Daudé
2019-07-11 16:38 ` Dr. David Alan Gilbert
2019-07-12 15:15 ` Peter Maydell
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 3/5] hw/block/pflash_cfi01: Extract pflash_mode_read_array() Philippe Mathieu-Daudé
` (2 subsequent siblings)
4 siblings, 2 replies; 9+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-11 15:57 UTC (permalink / raw)
To: Dr . David Alan Gilbert, qemu-devel
Cc: Kevin Wolf, qemu-block, Philippe Mathieu-Daudé, Laszlo Ersek,
Max Reitz, Alistair Francis, John Snow
In the "Read Array Flowchart" the command has a value of 0xFF.
In the document [*] the "Read Array Flowchart", the READ_ARRAY
command has a value of 0xff.
Use the correct value in the pflash model.
There is no change of behavior in the guest, because:
- when the guest were sending 0xFF, the reset_flash label
was setting the command value as 0x00
- 0x00 was used internally for READ_ARRAY
To keep migration with older versions behaving correctly, we
decide to always migrate the READ_ARRAY as 0x00.
[*] "Common Flash Interface (CFI) and Command Sets"
(Intel Application Note 646)
Appendix B "Basic Command Set"
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
v3: Handle migrating the 'cmd' field.
v4: Handle migrating to older QEMU (Dave)
Since Laszlo stated he did not test migration [*], I'm keeping his
test tag, because the change with v2 has no impact in the tests
he ran.
Likewise I'm keeping John and Alistair tags, but I'd like an extra
review for the migration change, thanks!
[*] https://lists.gnu.org/archive/html/qemu-devel/2019-07/msg00679.html
---
hw/block/pflash_cfi01.c | 57 ++++++++++++++++++++++++++++++++++-------
1 file changed, 48 insertions(+), 9 deletions(-)
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 9e34fd4e82..85bb2132c0 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -96,6 +96,37 @@ struct PFlashCFI01 {
bool old_multiple_chip_handling;
};
+static int pflash_pre_save(void *opaque)
+{
+ PFlashCFI01 *s = opaque;
+
+ /*
+ * Previous to QEMU v4.1 an incorrect value of 0x00 was used for the
+ * READ_ARRAY command. To preserve migrating to these older version,
+ * always migrate the READ_ARRAY command as 0x00.
+ */
+ if (s->cmd == 0xff) {
+ s->cmd = 0x00;
+ }
+
+ return 0;
+}
+
+static int pflash_post_save(void *opaque)
+{
+ PFlashCFI01 *s = opaque;
+
+ /*
+ * If migration failed, the guest will continue to run.
+ * Restore the correct READ_ARRAY value.
+ */
+ if (s->cmd == 0x00) {
+ s->cmd = 0xff;
+ }
+
+ return 0;
+}
+
static int pflash_post_load(void *opaque, int version_id);
static const VMStateDescription vmstate_pflash = {
@@ -103,6 +134,8 @@ static const VMStateDescription vmstate_pflash = {
.version_id = 1,
.minimum_version_id = 1,
.post_load = pflash_post_load,
+ .pre_save = pflash_pre_save,
+ .post_save = pflash_post_save,
.fields = (VMStateField[]) {
VMSTATE_UINT8(wcycle, PFlashCFI01),
VMSTATE_UINT8(cmd, PFlashCFI01),
@@ -277,10 +310,9 @@ static uint32_t pflash_read(PFlashCFI01 *pfl, hwaddr offset,
/* This should never happen : reset state & treat it as a read */
DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
pfl->wcycle = 0;
- pfl->cmd = 0;
+ pfl->cmd = 0xff;
/* fall through to read code */
- case 0x00:
- /* Flash area read */
+ case 0xff: /* Read Array */
ret = pflash_data_read(pfl, offset, width, be);
break;
case 0x10: /* Single byte program */
@@ -448,8 +480,6 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
case 0:
/* read mode */
switch (cmd) {
- case 0x00: /* ??? */
- goto reset_flash;
case 0x10: /* Single Byte Program */
case 0x40: /* Single Byte Program */
DPRINTF("%s: Single Byte Program\n", __func__);
@@ -526,7 +556,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
if (cmd == 0xd0) { /* confirm */
pfl->wcycle = 0;
pfl->status |= 0x80;
- } else if (cmd == 0xff) { /* read array mode */
+ } else if (cmd == 0xff) { /* Read Array */
goto reset_flash;
} else
goto error_flash;
@@ -553,7 +583,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
} else if (cmd == 0x01) {
pfl->wcycle = 0;
pfl->status |= 0x80;
- } else if (cmd == 0xff) {
+ } else if (cmd == 0xff) { /* read array mode */
goto reset_flash;
} else {
DPRINTF("%s: Unknown (un)locking command\n", __func__);
@@ -645,7 +675,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
trace_pflash_reset();
memory_region_rom_device_set_romd(&pfl->mem, true);
pfl->wcycle = 0;
- pfl->cmd = 0;
+ pfl->cmd = 0xff;
}
@@ -761,7 +791,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
}
pfl->wcycle = 0;
- pfl->cmd = 0;
+ pfl->cmd = 0xff;
pfl->status = 0;
/* Hardcoded CFI table */
/* Standard "QRY" string */
@@ -1001,5 +1031,14 @@ static int pflash_post_load(void *opaque, int version_id)
pfl->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
pfl);
}
+
+ /*
+ * Previous to QEMU v4.1 an incorrect value of 0x00 was used for the
+ * READ_ARRAY command.
+ */
+ if (pfl->cmd == 0x00) {
+ pfl->cmd = 0xff;
+ }
+
return 0;
}
--
2.20.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH-for-4.1 v4 3/5] hw/block/pflash_cfi01: Extract pflash_mode_read_array()
2019-07-11 15:56 [Qemu-devel] [PATCH-for-4.1 v4 0/5] hw/block/pflash_cfi01: Add DeviceReset() handler Philippe Mathieu-Daudé
2019-07-11 15:56 ` [Qemu-devel] [PATCH-for-4.1 v4 1/5] hw/block/pflash_cfi01: Removed an unused timer Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value Philippe Mathieu-Daudé
@ 2019-07-11 15:57 ` Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 4/5] hw/block/pflash_cfi01: Start state machine as READY to accept commands Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 5/5] hw/block/pflash_cfi01: Add the DeviceReset() handler Philippe Mathieu-Daudé
4 siblings, 0 replies; 9+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-11 15:57 UTC (permalink / raw)
To: Dr . David Alan Gilbert, qemu-devel
Cc: Kevin Wolf, qemu-block, Philippe Mathieu-Daudé, Laszlo Ersek,
Max Reitz, Alistair Francis, John Snow
The same pattern is used when setting the flash in READ_ARRAY mode:
- Set the state machine command to READ_ARRAY
- Reset the write_cycle counter
- Reset the memory region in ROMD
Refactor the current code by extracting this pattern.
It is used twice:
- On a write access (on command failure, error, or explicitly asked)
- When the device is initialized. Here the ROMD mode is hidden
by the memory_region_init_rom_device() call.
Rename the 'reset_flash' as 'mode_read_array' to make explicit we
do not reset the device, we simply set its internal state machine
in the READ_ARRAY mode. We do not reset the status register error
bits, as a device reset would do.
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/block/pflash_cfi01.c | 36 ++++++++++++++++++++----------------
hw/block/trace-events | 1 +
2 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 85bb2132c0..6c3fefcd2d 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -145,6 +145,14 @@ static const VMStateDescription vmstate_pflash = {
}
};
+static void pflash_mode_read_array(PFlashCFI01 *pfl)
+{
+ trace_pflash_mode_read_array();
+ pfl->cmd = 0xff; /* Read Array */
+ pfl->wcycle = 0;
+ memory_region_rom_device_set_romd(&pfl->mem, true);
+}
+
/* Perform a CFI query based on the bank width of the flash.
* If this code is called we know we have a device_width set for
* this flash.
@@ -502,7 +510,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
case 0x50: /* Clear status bits */
DPRINTF("%s: Clear status bits\n", __func__);
pfl->status = 0x0;
- goto reset_flash;
+ goto mode_read_array;
case 0x60: /* Block (un)lock */
DPRINTF("%s: Block unlock\n", __func__);
break;
@@ -527,10 +535,10 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
break;
case 0xf0: /* Probe for AMD flash */
DPRINTF("%s: Probe for AMD flash\n", __func__);
- goto reset_flash;
+ goto mode_read_array;
case 0xff: /* Read array mode */
DPRINTF("%s: Read array mode\n", __func__);
- goto reset_flash;
+ goto mode_read_array;
default:
goto error_flash;
}
@@ -557,7 +565,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
pfl->wcycle = 0;
pfl->status |= 0x80;
} else if (cmd == 0xff) { /* Read Array */
- goto reset_flash;
+ goto mode_read_array;
} else
goto error_flash;
@@ -584,15 +592,15 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
pfl->wcycle = 0;
pfl->status |= 0x80;
} else if (cmd == 0xff) { /* read array mode */
- goto reset_flash;
+ goto mode_read_array;
} else {
DPRINTF("%s: Unknown (un)locking command\n", __func__);
- goto reset_flash;
+ goto mode_read_array;
}
break;
case 0x98:
if (cmd == 0xff) {
- goto reset_flash;
+ goto mode_read_array;
} else {
DPRINTF("%s: leaving query mode\n", __func__);
}
@@ -652,7 +660,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
" the data is already written to storage!\n"
"Flash device reset into READ mode.\n",
__func__);
- goto reset_flash;
+ goto mode_read_array;
}
break;
default:
@@ -662,7 +670,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
default:
/* Should never happen */
DPRINTF("%s: invalid write state\n", __func__);
- goto reset_flash;
+ goto mode_read_array;
}
return;
@@ -671,11 +679,8 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
"(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)"
"\n", __func__, offset, pfl->wcycle, pfl->cmd, value);
- reset_flash:
- trace_pflash_reset();
- memory_region_rom_device_set_romd(&pfl->mem, true);
- pfl->wcycle = 0;
- pfl->cmd = 0xff;
+ mode_read_array:
+ pflash_mode_read_array(pfl);
}
@@ -790,8 +795,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
pfl->max_device_width = pfl->device_width;
}
- pfl->wcycle = 0;
- pfl->cmd = 0xff;
+ pflash_mode_read_array(pfl);
pfl->status = 0;
/* Hardcoded CFI table */
/* Standard "QRY" string */
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 13d1b21dd4..91a8a106c0 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -7,6 +7,7 @@ fdc_ioport_write(uint8_t reg, uint8_t value) "write reg 0x%02x val 0x%02x"
# pflash_cfi02.c
# pflash_cfi01.c
pflash_reset(void) "reset"
+pflash_mode_read_array(void) "mode: read array"
pflash_timer_expired(uint8_t cmd) "command 0x%02x done"
pflash_io_read(uint64_t offset, int width, int fmt_width, uint32_t value, uint8_t cmd, uint8_t wcycle) "offset:0x%04"PRIx64" width:%d value:0x%0*x cmd:0x%02x wcycle:%u"
pflash_io_write(uint64_t offset, int width, int fmt_width, uint32_t value, uint8_t wcycle) "offset:0x%04"PRIx64" width:%d value:0x%0*x wcycle:%u"
--
2.20.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH-for-4.1 v4 4/5] hw/block/pflash_cfi01: Start state machine as READY to accept commands
2019-07-11 15:56 [Qemu-devel] [PATCH-for-4.1 v4 0/5] hw/block/pflash_cfi01: Add DeviceReset() handler Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 3/5] hw/block/pflash_cfi01: Extract pflash_mode_read_array() Philippe Mathieu-Daudé
@ 2019-07-11 15:57 ` Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 5/5] hw/block/pflash_cfi01: Add the DeviceReset() handler Philippe Mathieu-Daudé
4 siblings, 0 replies; 9+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-11 15:57 UTC (permalink / raw)
To: Dr . David Alan Gilbert, qemu-devel
Cc: Kevin Wolf, qemu-block, Philippe Mathieu-Daudé, Laszlo Ersek,
Max Reitz, Alistair Francis, John Snow
When the state machine is ready to accept command, the bit 7 of
the status register (SR) is set to 1.
The guest polls the status register and check this bit before
writting command to the internal 'Write State Machine' (WSM).
Set SR.7 bit to 1 when the device is created.
There is no migration impact by this change.
Reference: Read Array Flowchart
"Common Flash Interface (CFI) and Command Sets"
(Intel Application Note 646)
Appendix B "Basic Command Set"
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
v3: Added migration comment.
---
hw/block/pflash_cfi01.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 6c3fefcd2d..aa2126f6dc 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -796,7 +796,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
}
pflash_mode_read_array(pfl);
- pfl->status = 0;
+ pfl->status = 0x80; /* WSM ready */
/* Hardcoded CFI table */
/* Standard "QRY" string */
pfl->cfi_table[0x10] = 'Q';
--
2.20.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH-for-4.1 v4 5/5] hw/block/pflash_cfi01: Add the DeviceReset() handler
2019-07-11 15:56 [Qemu-devel] [PATCH-for-4.1 v4 0/5] hw/block/pflash_cfi01: Add DeviceReset() handler Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 4/5] hw/block/pflash_cfi01: Start state machine as READY to accept commands Philippe Mathieu-Daudé
@ 2019-07-11 15:57 ` Philippe Mathieu-Daudé
4 siblings, 0 replies; 9+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-11 15:57 UTC (permalink / raw)
To: Dr . David Alan Gilbert, qemu-devel
Cc: Kevin Wolf, qemu-block, John Snow, Philippe Mathieu-Daudé,
Alistair Francis, Max Reitz, Laszlo Ersek
A "system reset" sets the device state machine in READ_ARRAY mode
and, after some delay, set the SR.7 READY bit.
We do not model timings, so we set the SR.7 bit directly.
The TYPE_DEVICE interface provides a DeviceReset handler.
This pflash device is a subclass of TYPE_SYS_BUS_DEVICE (which
is a subclass of TYPE_DEVICE).
SYS_BUS devices are automatically plugged into the 'main system
bus', which is the root of the qbus tree.
Devices in the qbus tree are guaranteed to have their reset()
handler called after realize() and before we try to run the guest.
To avoid incoherent states when the machine resets (see but report
below), factor out the reset code into pflash_cfi01_system_reset,
and register the method as a device reset callback.
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1678713
Reported-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
v3: reword description
---
hw/block/pflash_cfi01.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index aa2126f6dc..dd2ace92a8 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -795,8 +795,6 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
pfl->max_device_width = pfl->device_width;
}
- pflash_mode_read_array(pfl);
- pfl->status = 0x80; /* WSM ready */
/* Hardcoded CFI table */
/* Standard "QRY" string */
pfl->cfi_table[0x10] = 'Q';
@@ -884,6 +882,18 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */
}
+static void pflash_cfi01_system_reset(DeviceState *dev)
+{
+ PFlashCFI01 *pfl = PFLASH_CFI01(dev);
+
+ pflash_mode_read_array(pfl);
+ /*
+ * The WSM ready timer occurs at most 150ns after system reset.
+ * This model deliberately ignores this delay.
+ */
+ pfl->status = 0x80;
+}
+
static Property pflash_cfi01_properties[] = {
DEFINE_PROP_DRIVE("drive", PFlashCFI01, blk),
/* num-blocks is the number of blocks actually visible to the guest,
@@ -928,6 +938,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->reset = pflash_cfi01_system_reset;
dc->realize = pflash_cfi01_realize;
dc->props = pflash_cfi01_properties;
dc->vmsd = &vmstate_pflash;
--
2.20.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value Philippe Mathieu-Daudé
@ 2019-07-11 16:38 ` Dr. David Alan Gilbert
2019-07-12 15:15 ` Peter Maydell
1 sibling, 0 replies; 9+ messages in thread
From: Dr. David Alan Gilbert @ 2019-07-11 16:38 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Kevin Wolf, qemu-block, Laszlo Ersek, qemu-devel, Max Reitz,
Alistair Francis, John Snow
* Philippe Mathieu-Daudé (philmd@redhat.com) wrote:
> In the "Read Array Flowchart" the command has a value of 0xFF.
>
> In the document [*] the "Read Array Flowchart", the READ_ARRAY
> command has a value of 0xff.
>
> Use the correct value in the pflash model.
>
> There is no change of behavior in the guest, because:
> - when the guest were sending 0xFF, the reset_flash label
> was setting the command value as 0x00
> - 0x00 was used internally for READ_ARRAY
>
> To keep migration with older versions behaving correctly, we
> decide to always migrate the READ_ARRAY as 0x00.
>
> [*] "Common Flash Interface (CFI) and Command Sets"
> (Intel Application Note 646)
> Appendix B "Basic Command Set"
>
> Reviewed-by: John Snow <jsnow@redhat.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> v3: Handle migrating the 'cmd' field.
> v4: Handle migrating to older QEMU (Dave)
>
> Since Laszlo stated he did not test migration [*], I'm keeping his
> test tag, because the change with v2 has no impact in the tests
> he ran.
>
> Likewise I'm keeping John and Alistair tags, but I'd like an extra
> review for the migration change, thanks!
>
> [*] https://lists.gnu.org/archive/html/qemu-devel/2019-07/msg00679.html
> ---
> hw/block/pflash_cfi01.c | 57 ++++++++++++++++++++++++++++++++++-------
> 1 file changed, 48 insertions(+), 9 deletions(-)
>
> diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
> index 9e34fd4e82..85bb2132c0 100644
> --- a/hw/block/pflash_cfi01.c
> +++ b/hw/block/pflash_cfi01.c
> @@ -96,6 +96,37 @@ struct PFlashCFI01 {
> bool old_multiple_chip_handling;
> };
>
> +static int pflash_pre_save(void *opaque)
> +{
> + PFlashCFI01 *s = opaque;
> +
> + /*
> + * Previous to QEMU v4.1 an incorrect value of 0x00 was used for the
> + * READ_ARRAY command. To preserve migrating to these older version,
> + * always migrate the READ_ARRAY command as 0x00.
> + */
> + if (s->cmd == 0xff) {
> + s->cmd = 0x00;
> + }
> +
> + return 0;
> +}
> +
> +static int pflash_post_save(void *opaque)
> +{
> + PFlashCFI01 *s = opaque;
> +
> + /*
> + * If migration failed, the guest will continue to run.
> + * Restore the correct READ_ARRAY value.
> + */
> + if (s->cmd == 0x00) {
> + s->cmd = 0xff;
> + }
OK, from a migration point of view I think we're OK, as long
as you never have a valid situation where cmd was 0x00 and
it's now suddenly going to become 0xff.
Dave
> + return 0;
> +}
> +
> static int pflash_post_load(void *opaque, int version_id);
>
> static const VMStateDescription vmstate_pflash = {
> @@ -103,6 +134,8 @@ static const VMStateDescription vmstate_pflash = {
> .version_id = 1,
> .minimum_version_id = 1,
> .post_load = pflash_post_load,
> + .pre_save = pflash_pre_save,
> + .post_save = pflash_post_save,
> .fields = (VMStateField[]) {
> VMSTATE_UINT8(wcycle, PFlashCFI01),
> VMSTATE_UINT8(cmd, PFlashCFI01),
> @@ -277,10 +310,9 @@ static uint32_t pflash_read(PFlashCFI01 *pfl, hwaddr offset,
> /* This should never happen : reset state & treat it as a read */
> DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
> pfl->wcycle = 0;
> - pfl->cmd = 0;
> + pfl->cmd = 0xff;
> /* fall through to read code */
> - case 0x00:
> - /* Flash area read */
> + case 0xff: /* Read Array */
> ret = pflash_data_read(pfl, offset, width, be);
> break;
> case 0x10: /* Single byte program */
> @@ -448,8 +480,6 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
> case 0:
> /* read mode */
> switch (cmd) {
> - case 0x00: /* ??? */
> - goto reset_flash;
> case 0x10: /* Single Byte Program */
> case 0x40: /* Single Byte Program */
> DPRINTF("%s: Single Byte Program\n", __func__);
> @@ -526,7 +556,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
> if (cmd == 0xd0) { /* confirm */
> pfl->wcycle = 0;
> pfl->status |= 0x80;
> - } else if (cmd == 0xff) { /* read array mode */
> + } else if (cmd == 0xff) { /* Read Array */
> goto reset_flash;
> } else
> goto error_flash;
> @@ -553,7 +583,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
> } else if (cmd == 0x01) {
> pfl->wcycle = 0;
> pfl->status |= 0x80;
> - } else if (cmd == 0xff) {
> + } else if (cmd == 0xff) { /* read array mode */
> goto reset_flash;
> } else {
> DPRINTF("%s: Unknown (un)locking command\n", __func__);
> @@ -645,7 +675,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
> trace_pflash_reset();
> memory_region_rom_device_set_romd(&pfl->mem, true);
> pfl->wcycle = 0;
> - pfl->cmd = 0;
> + pfl->cmd = 0xff;
> }
>
>
> @@ -761,7 +791,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
> }
>
> pfl->wcycle = 0;
> - pfl->cmd = 0;
> + pfl->cmd = 0xff;
> pfl->status = 0;
> /* Hardcoded CFI table */
> /* Standard "QRY" string */
> @@ -1001,5 +1031,14 @@ static int pflash_post_load(void *opaque, int version_id)
> pfl->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
> pfl);
> }
> +
> + /*
> + * Previous to QEMU v4.1 an incorrect value of 0x00 was used for the
> + * READ_ARRAY command.
> + */
> + if (pfl->cmd == 0x00) {
> + pfl->cmd = 0xff;
> + }
> +
> return 0;
> }
> --
> 2.20.1
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value Philippe Mathieu-Daudé
2019-07-11 16:38 ` Dr. David Alan Gilbert
@ 2019-07-12 15:15 ` Peter Maydell
2019-07-12 16:53 ` Philippe Mathieu-Daudé
1 sibling, 1 reply; 9+ messages in thread
From: Peter Maydell @ 2019-07-12 15:15 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Kevin Wolf, Qemu-block, QEMU Developers, John Snow,
Dr . David Alan Gilbert, Max Reitz, Alistair Francis,
Laszlo Ersek
On Thu, 11 Jul 2019 at 16:58, Philippe Mathieu-Daudé <philmd@redhat.com> wrote:
>
> In the "Read Array Flowchart" the command has a value of 0xFF.
>
> In the document [*] the "Read Array Flowchart", the READ_ARRAY
> command has a value of 0xff.
>
> Use the correct value in the pflash model.
>
> There is no change of behavior in the guest, because:
> - when the guest were sending 0xFF, the reset_flash label
> was setting the command value as 0x00
> - 0x00 was used internally for READ_ARRAY
>
> To keep migration with older versions behaving correctly, we
> decide to always migrate the READ_ARRAY as 0x00.
>
> [*] "Common Flash Interface (CFI) and Command Sets"
> (Intel Application Note 646)
> Appendix B "Basic Command Set"
>
> Reviewed-by: John Snow <jsnow@redhat.com>
> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
These changes look correct as far as they go, but are
we sure that command value 0x00 will never be a valid
command in some future version? If it ever does, then we
have a problem because we can't distinguish "0xff with
a silly encoding" from "really 0x00" in the incoming
migration data stream.
If we're 100% confident that there will never be a true
command 0x00 then this approach is OK.
thanks
-- PMM
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value
2019-07-12 15:15 ` Peter Maydell
@ 2019-07-12 16:53 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 9+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-07-12 16:53 UTC (permalink / raw)
To: Peter Maydell
Cc: Kevin Wolf, Qemu-block, QEMU Developers, John Snow,
Dr . David Alan Gilbert, Max Reitz, Alistair Francis,
Laszlo Ersek
On 7/12/19 5:15 PM, Peter Maydell wrote:
> On Thu, 11 Jul 2019 at 16:58, Philippe Mathieu-Daudé <philmd@redhat.com> wrote:
>>
>> In the "Read Array Flowchart" the command has a value of 0xFF.
>>
>> In the document [*] the "Read Array Flowchart", the READ_ARRAY
>> command has a value of 0xff.
>>
>> Use the correct value in the pflash model.
>>
>> There is no change of behavior in the guest, because:
>> - when the guest were sending 0xFF, the reset_flash label
>> was setting the command value as 0x00
>> - 0x00 was used internally for READ_ARRAY
>>
>> To keep migration with older versions behaving correctly, we
>> decide to always migrate the READ_ARRAY as 0x00.
>>
>> [*] "Common Flash Interface (CFI) and Command Sets"
>> (Intel Application Note 646)
>> Appendix B "Basic Command Set"
>>
>> Reviewed-by: John Snow <jsnow@redhat.com>
>> Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
>> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
>> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>> ---
>
> These changes look correct as far as they go, but are
> we sure that command value 0x00 will never be a valid
> command in some future version? If it ever does, then we
> have a problem because we can't distinguish "0xff with
> a silly encoding" from "really 0x00" in the incoming
> migration data stream.
>
> If we're 100% confident that there will never be a true
> command 0x00 then this approach is OK.
I am not confident, the industry can surprise us.
If a CFI command of value 0x00 is ever published, then this device will
be in troubles because it can not support it (due to back-migration).
Neither in its current state, neither after this patch.
So if this ever happens, this device will never be able to announce it
supports features with a such command. And if guests require we model
this feature, then we'll increase the migration version and the device
won't be backward-migratable.
I'll try to explain that in the commit description.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2019-07-12 16:54 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-07-11 15:56 [Qemu-devel] [PATCH-for-4.1 v4 0/5] hw/block/pflash_cfi01: Add DeviceReset() handler Philippe Mathieu-Daudé
2019-07-11 15:56 ` [Qemu-devel] [PATCH-for-4.1 v4 1/5] hw/block/pflash_cfi01: Removed an unused timer Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 2/5] hw/block/pflash_cfi01: Use the correct READ_ARRAY value Philippe Mathieu-Daudé
2019-07-11 16:38 ` Dr. David Alan Gilbert
2019-07-12 15:15 ` Peter Maydell
2019-07-12 16:53 ` Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 3/5] hw/block/pflash_cfi01: Extract pflash_mode_read_array() Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 4/5] hw/block/pflash_cfi01: Start state machine as READY to accept commands Philippe Mathieu-Daudé
2019-07-11 15:57 ` [Qemu-devel] [PATCH-for-4.1 v4 5/5] hw/block/pflash_cfi01: Add the DeviceReset() handler Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).