mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
target/arm: Add cpu properties for SME
Mirror the properties for SVE. The main difference is that any arbitrary set of powers of 2 may be supported, and not the stricter constraints that apply to SVE. Include a property to control FEAT_SME_FA64, as failing to restrict the runtime to the proper subset of insns could be a major point for bugs. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20220620175235.60881-18-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
70cc9ee19e
commit
e74c097638
5 changed files with 180 additions and 7 deletions
|
@ -589,10 +589,13 @@ static void cpu_arm_get_vq(Object *obj, Visitor *v, const char *name,
|
|||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
ARMVQMap *vq_map = opaque;
|
||||
uint32_t vq = atoi(&name[3]) / 128;
|
||||
bool sve = vq_map == &cpu->sve_vq;
|
||||
bool value;
|
||||
|
||||
/* All vector lengths are disabled when SVE is off. */
|
||||
if (!cpu_isar_feature(aa64_sve, cpu)) {
|
||||
/* All vector lengths are disabled when feature is off. */
|
||||
if (sve
|
||||
? !cpu_isar_feature(aa64_sve, cpu)
|
||||
: !cpu_isar_feature(aa64_sme, cpu)) {
|
||||
value = false;
|
||||
} else {
|
||||
value = extract32(vq_map->map, vq - 1, 1);
|
||||
|
@ -636,8 +639,80 @@ static void cpu_arm_set_sve(Object *obj, bool value, Error **errp)
|
|||
cpu->isar.id_aa64pfr0 = t;
|
||||
}
|
||||
|
||||
void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp)
|
||||
{
|
||||
uint32_t vq_map = cpu->sme_vq.map;
|
||||
uint32_t vq_init = cpu->sme_vq.init;
|
||||
uint32_t vq_supported = cpu->sme_vq.supported;
|
||||
uint32_t vq;
|
||||
|
||||
if (vq_map == 0) {
|
||||
if (!cpu_isar_feature(aa64_sme, cpu)) {
|
||||
cpu->isar.id_aa64smfr0 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: KVM will require limitations via SMCR_EL2. */
|
||||
vq_map = vq_supported & ~vq_init;
|
||||
|
||||
if (vq_map == 0) {
|
||||
vq = ctz32(vq_supported) + 1;
|
||||
error_setg(errp, "cannot disable sme%d", vq * 128);
|
||||
error_append_hint(errp, "All SME vector lengths are disabled.\n");
|
||||
error_append_hint(errp, "With SME enabled, at least one "
|
||||
"vector length must be enabled.\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!cpu_isar_feature(aa64_sme, cpu)) {
|
||||
vq = 32 - clz32(vq_map);
|
||||
error_setg(errp, "cannot enable sme%d", vq * 128);
|
||||
error_append_hint(errp, "SME must be enabled to enable "
|
||||
"vector lengths.\n");
|
||||
error_append_hint(errp, "Add sme=on to the CPU property list.\n");
|
||||
return;
|
||||
}
|
||||
/* TODO: KVM will require limitations via SMCR_EL2. */
|
||||
}
|
||||
|
||||
cpu->sme_vq.map = vq_map;
|
||||
}
|
||||
|
||||
static bool cpu_arm_get_sme(Object *obj, Error **errp)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
return cpu_isar_feature(aa64_sme, cpu);
|
||||
}
|
||||
|
||||
static void cpu_arm_set_sme(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
uint64_t t;
|
||||
|
||||
t = cpu->isar.id_aa64pfr1;
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, SME, value);
|
||||
cpu->isar.id_aa64pfr1 = t;
|
||||
}
|
||||
|
||||
static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
return cpu_isar_feature(aa64_sme, cpu) &&
|
||||
cpu_isar_feature(aa64_sme_fa64, cpu);
|
||||
}
|
||||
|
||||
static void cpu_arm_set_sme_fa64(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
uint64_t t;
|
||||
|
||||
t = cpu->isar.id_aa64smfr0;
|
||||
t = FIELD_DP64(t, ID_AA64SMFR0, FA64, value);
|
||||
cpu->isar.id_aa64smfr0 = t;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/* Mirror linux /proc/sys/abi/sve_default_vector_length. */
|
||||
/* Mirror linux /proc/sys/abi/{sve,sme}_default_vector_length. */
|
||||
static void cpu_arm_set_default_vec_len(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
|
@ -663,7 +738,11 @@ static void cpu_arm_set_default_vec_len(Object *obj, Visitor *v,
|
|||
* and is the maximum architectural width of ZCR_ELx.LEN.
|
||||
*/
|
||||
if (remainder || default_vq < 1 || default_vq > 512) {
|
||||
error_setg(errp, "cannot set sve-default-vector-length");
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
const char *which =
|
||||
(ptr_default_vq == &cpu->sve_default_vq ? "sve" : "sme");
|
||||
|
||||
error_setg(errp, "cannot set %s-default-vector-length", which);
|
||||
if (remainder) {
|
||||
error_append_hint(errp, "Vector length not a multiple of 16\n");
|
||||
} else if (default_vq < 1) {
|
||||
|
@ -712,6 +791,31 @@ static void aarch64_add_sve_properties(Object *obj)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void aarch64_add_sme_properties(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
uint32_t vq;
|
||||
|
||||
object_property_add_bool(obj, "sme", cpu_arm_get_sme, cpu_arm_set_sme);
|
||||
object_property_add_bool(obj, "sme_fa64", cpu_arm_get_sme_fa64,
|
||||
cpu_arm_set_sme_fa64);
|
||||
|
||||
for (vq = 1; vq <= ARM_MAX_VQ; vq <<= 1) {
|
||||
char name[8];
|
||||
sprintf(name, "sme%d", vq * 128);
|
||||
object_property_add(obj, name, "bool", cpu_arm_get_vq,
|
||||
cpu_arm_set_vq, NULL, &cpu->sme_vq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/* Mirror linux /proc/sys/abi/sme_default_vector_length. */
|
||||
object_property_add(obj, "sme-default-vector-length", "int32",
|
||||
cpu_arm_get_default_vec_len,
|
||||
cpu_arm_set_default_vec_len, NULL,
|
||||
&cpu->sme_default_vq);
|
||||
#endif
|
||||
}
|
||||
|
||||
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
|
||||
{
|
||||
int arch_val = 0, impdef_val = 0;
|
||||
|
@ -977,9 +1081,11 @@ static void aarch64_max_initfn(Object *obj)
|
|||
#endif
|
||||
|
||||
cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
|
||||
cpu->sme_vq.supported = SVE_VQ_POW2_MAP;
|
||||
|
||||
aarch64_add_pauth_properties(obj);
|
||||
aarch64_add_sve_properties(obj);
|
||||
aarch64_add_sme_properties(obj);
|
||||
object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
|
||||
cpu_max_set_sve_max_vq, NULL, NULL);
|
||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue