aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Iakovlev <eiakovlev@linux.microsoft.com>2023-01-23 17:23:01 +0100
committerPeter Maydell <peter.maydell@linaro.org>2023-02-03 12:59:22 +0000
commit13ea96fa34bcb6076f42a41194ab363c945e4b07 (patch)
treec172454cc1ebd58928b72d6f3aa8261e5b884bcc
parent9d88935cb19f8f8e7291026efe23862316ff2510 (diff)
downloadqemu-13ea96fa34bcb6076f42a41194ab363c945e4b07.zip
qemu-13ea96fa34bcb6076f42a41194ab363c945e4b07.tar.gz
qemu-13ea96fa34bcb6076f42a41194ab363c945e4b07.tar.bz2
hw/char/pl011: add post_load hook for backwards-compatibility
Previous change slightly modified the way we handle data writes when FIFO is disabled. Previously we kept incrementing read_pos and were storing data at that position, although we only have a single-register-deep FIFO now. Then we changed it to always store data at pos 0. If guest disables FIFO and the proceeds to read data, it will work out fine, because we still read from current read_pos before setting it to 0. However, to make code less fragile, introduce a post_load hook for PL011State and move fixup read FIFO state when FIFO is disabled. Since we are introducing a post_load hook, also do some sanity checking on untrusted incoming input state. Signed-off-by: Evgeny Iakovlev <eiakovlev@linux.microsoft.com> Message-id: 20230123162304.26254-3-eiakovlev@linux.microsoft.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/char/pl011.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 3fa3b75..05e8bdc 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -352,10 +352,35 @@ static const VMStateDescription vmstate_pl011_clock = {
}
};
+static int pl011_post_load(void *opaque, int version_id)
+{
+ PL011State* s = opaque;
+
+ /* Sanity-check input state */
+ if (s->read_pos >= ARRAY_SIZE(s->read_fifo) ||
+ s->read_count > ARRAY_SIZE(s->read_fifo)) {
+ return -1;
+ }
+
+ if (!pl011_is_fifo_enabled(s) && s->read_count > 0 && s->read_pos > 0) {
+ /*
+ * Older versions of PL011 didn't ensure that the single
+ * character in the FIFO in FIFO-disabled mode is in
+ * element 0 of the array; convert to follow the current
+ * code's assumptions.
+ */
+ s->read_fifo[0] = s->read_fifo[s->read_pos];
+ s->read_pos = 0;
+ }
+
+ return 0;
+}
+
static const VMStateDescription vmstate_pl011 = {
.name = "pl011",
.version_id = 2,
.minimum_version_id = 2,
+ .post_load = pl011_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(readbuff, PL011State),
VMSTATE_UINT32(flags, PL011State),