From: Gavin Shan <gshan@redhat.com>
To: qemu-arm@nongnu.org
Cc: peter.maydell@linaro.org, drjones@redhat.com,
richard.henderson@linaro.org, qemu-devel@nongnu.org,
eric.auger@redhat.com, agraf@csgraf.de, shan.gavin@gmail.com,
pbonzini@redhat.com
Subject: [PATCH 1/5] target/arm/tcg: Indirect addressing for coprocessor register storage
Date: Mon, 11 Apr 2022 14:58:38 +0800 [thread overview]
Message-ID: <20220411065842.63880-2-gshan@redhat.com> (raw)
In-Reply-To: <20220411065842.63880-1-gshan@redhat.com>
Currently, there is an array used as the storage for the coprocessor
registers. Each element in the array occupies for 8 bytes. It means
we have the assumption that the size of coprocessor can't exceed
8 bytes. The storage mechanism is used by KVM either. Unfortunately,
the assumption is conflicting with KVM's pseudo firmware registers,
whose sizes can be variable and exceeding 8 bytes. So the storage
scheme isn't working for KVM's pseudo firmware registers.
This introduces another array (@cpreg_value_indexes) to track the
storage location in @cpreg_values for the corresponding coprocessor
register. @cpreg_value_array_len is also added to track the total
storage size for all coprocessor registers. After that, the storage
is addressed indirectly by @cpreg_values[cpreg_value_indexes[i]].
For TCG case, each coprocessor register still has fixed 8 bytes
storage space. So the old direct addressing mechanism and new
indirect addressing mechanism can co-exist and interchangeable,
even in migration circumstance.
Signed-off-by: Gavin Shan <gshan@redhat.com>
---
target/arm/cpu.h | 12 ++++++++++--
target/arm/helper.c | 27 +++++++++++++++++++--------
2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 23879de5fa..0129791b3f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -795,17 +795,25 @@ struct ArchCPU {
* 64 bit indexes, not CPRegInfo 32 bit indexes)
*/
uint64_t *cpreg_indexes;
- /* Values of the registers (cpreg_indexes[i]'s value is cpreg_values[i]) */
+ /*
+ * Values of the registers
+ * (cpreg_indexes[i]'s value is cpreg_values[cpreg_value_indexes[i]])
+ */
+ uint32_t *cpreg_value_indexes;
uint64_t *cpreg_values;
- /* Length of the indexes, values, reset_values arrays */
+ /* Length of the indexes, value indexes and values arrays */
int32_t cpreg_array_len;
+ int32_t cpreg_value_array_len;
+
/* These are used only for migration: incoming data arrives in
* these fields and is sanity checked in post_load before copying
* to the working data structures above.
*/
uint64_t *cpreg_vmstate_indexes;
+ uint32_t *cpreg_vmstate_value_indexes;
uint64_t *cpreg_vmstate_values;
int32_t cpreg_vmstate_array_len;
+ int32_t cpreg_vmstate_value_array_len;
DynamicGDBXMLInfo dyn_sysreg_xml;
DynamicGDBXMLInfo dyn_svereg_xml;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7d14650615..e8cb4a9edb 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -163,7 +163,7 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
* item in the list, we just recheck "does the raw write we must
* have made in write_list_to_cpustate() read back OK" here.
*/
- uint64_t oldval = cpu->cpreg_values[i];
+ uint64_t oldval = cpu->cpreg_values[cpu->cpreg_value_indexes[i]];
if (oldval == newval) {
continue;
@@ -176,7 +176,7 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
write_raw_cp_reg(&cpu->env, ri, newval);
}
- cpu->cpreg_values[i] = newval;
+ cpu->cpreg_values[cpu->cpreg_value_indexes[i]] = newval;
}
return ok;
}
@@ -188,7 +188,7 @@ bool write_list_to_cpustate(ARMCPU *cpu)
for (i = 0; i < cpu->cpreg_array_len; i++) {
uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
- uint64_t v = cpu->cpreg_values[i];
+ uint64_t v = cpu->cpreg_values[cpu->cpreg_value_indexes[i]];
const ARMCPRegInfo *ri;
ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
@@ -222,8 +222,12 @@ static void add_cpreg_to_list(gpointer key, gpointer opaque)
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
+ cpu->cpreg_value_indexes[cpu->cpreg_array_len] =
+ cpu->cpreg_value_array_len;
+
/* The value array need not be initialized at this point */
cpu->cpreg_array_len++;
+ cpu->cpreg_value_array_len++;
}
}
@@ -238,6 +242,7 @@ static void count_cpreg(gpointer key, gpointer opaque)
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
cpu->cpreg_array_len++;
+ cpu->cpreg_value_array_len++;
}
}
@@ -261,26 +266,32 @@ void init_cpreg_list(ARMCPU *cpu)
* Note that we require cpreg_tuples[] to be sorted by key ID.
*/
GList *keys;
- int arraylen;
+ int arraylen, value_arraylen;
keys = g_hash_table_get_keys(cpu->cp_regs);
keys = g_list_sort(keys, cpreg_key_compare);
cpu->cpreg_array_len = 0;
-
+ cpu->cpreg_value_array_len = 0;
g_list_foreach(keys, count_cpreg, cpu);
arraylen = cpu->cpreg_array_len;
+ value_arraylen = cpu->cpreg_value_array_len;
cpu->cpreg_indexes = g_new(uint64_t, arraylen);
- cpu->cpreg_values = g_new(uint64_t, arraylen);
+ cpu->cpreg_value_indexes = g_new(uint32_t, arraylen);
+ cpu->cpreg_values = g_new(uint64_t, value_arraylen);
cpu->cpreg_vmstate_indexes = g_new(uint64_t, arraylen);
- cpu->cpreg_vmstate_values = g_new(uint64_t, arraylen);
+ cpu->cpreg_vmstate_value_indexes = g_new(uint32_t, arraylen);
+ cpu->cpreg_vmstate_values = g_new(uint64_t, value_arraylen);
cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len;
- cpu->cpreg_array_len = 0;
+ cpu->cpreg_vmstate_value_array_len = cpu->cpreg_value_array_len;
+ cpu->cpreg_array_len = 0;
+ cpu->cpreg_value_array_len = 0;
g_list_foreach(keys, add_cpreg_to_list, cpu);
assert(cpu->cpreg_array_len == arraylen);
+ assert(cpu->cpreg_value_array_len == value_arraylen);
g_list_free(keys);
}
--
2.23.0
next prev parent reply other threads:[~2022-04-11 7:04 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-11 6:58 [PATCH 0/5] target/arm: Support variable sized coprocessor registers Gavin Shan
2022-04-11 6:58 ` Gavin Shan [this message]
2022-04-11 6:58 ` [PATCH 2/5] target/arm/hvf: Indirect addressing for coprocessor register storage Gavin Shan
2022-04-11 6:58 ` [PATCH 3/5] target/arm/kvm: " Gavin Shan
2022-04-11 6:58 ` [PATCH 4/5] target/arm: Migrate coprocessor register indirect addressing information Gavin Shan
2022-04-11 6:58 ` [PATCH 5/5] target/arm/kvm: Support coprocessor register with variable size Gavin Shan
2022-04-11 9:22 ` [PATCH 0/5] target/arm: Support variable sized coprocessor registers Peter Maydell
2022-04-11 9:49 ` Gavin Shan
2022-04-11 10:05 ` Peter Maydell
2022-04-12 1:54 ` Gavin Shan
2022-04-11 12:02 ` Andrew Jones
2022-04-11 12:10 ` Peter Maydell
2022-04-13 2:55 ` Gavin Shan
2022-04-12 2:08 ` Gavin Shan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220411065842.63880-2-gshan@redhat.com \
--to=gshan@redhat.com \
--cc=agraf@csgraf.de \
--cc=drjones@redhat.com \
--cc=eric.auger@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=shan.gavin@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).