> On 8 Oct 2026, at 1:18 PM, Eric Auger <[email protected]> wrote:
> 
> !-------------------------------------------------------------------|
>  CAUTION: External Email
> 
> |-------------------------------------------------------------------!
> 
> Hi Khushit,
> 
> On 9/30/26 9:34 AM, Khushit Shah wrote:
>> 
>>> On 16 Sep 2026, at 8:15 PM, Eric Auger <[email protected]> wrote:
>>> 
>>> !-------------------------------------------------------------------|
>>> CAUTION: External Email
>>> 
>>> |-------------------------------------------------------------------!
>>> 
>>> Since legacy composite options (such as SVE, virtualization, ...)
>>> and new SYSREG props coexist, add some basic consistency checks.
>>> 
>>> Those checks are performed both in kvm_arch_init_vcpu() before
>>> applying the SYSREG props at the end of the initialization chain.
>>> 
>>> Some ID reg fields corresponding to legacy composite option scope
>>> are not writable. In that case we just check that the field has
>>> not become writable.
>>> 
>>> Signed-off-by: Eric Auger <[email protected]>
>> Hi Eric,
>> 
>> Gave this another look. I suggest moving this to 
>> kvm_arm_expose_idreg_properties().
>> What I suggest specifically is:
>> - Have a list of ID register fields which conflicts with legacy props.
> this depends on the definition of "conflict". For instance does 
> 
> PMUVer conflicts with has_pmu?
> 

Yes, PMUVer = 0 is inconsistent with has_pmu=true 

> Nevertheless your suggested approach could work for props below which in case 
> they show up would trigger
>        error_setg(errp, "%s is now exposed but qemu is not ready to support 
> it",
>                   propname);

I was thinking of not exposing these props because we know it conflicts. So 
instead of checking the set props in kvm_arm_vcpu_validate_sysreg, we never 
expose conflicts in kvm_arm_expose_idreg_properties

I am suggesting this way because for named CPU models, we will have to handle 
this conflicts differently.


I hope this makes sense.


Thanks,
Khushit

> 
> Thanks
> 
> Eric
> 
>> - in kvm_arm_expose_idreg_properties() (the new field based approach) never 
>> expose fields
>>  which are part of the above list.
>> 
>> This way the same consistency logic you have will carry over to named models 
>> by just adding different
>> setters for the above field.
>> 
>> What are your thoughts on this?
>> 
>> Thanks,
>> Khushit
>>> — 
>>> target/arm/kvm.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 105 insertions(+)
>>> 
>>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>>> index ddf320d0e6..f52c03745e 100644
>>> --- a/target/arm/kvm.c
>>> +++ b/target/arm/kvm.c
>>> @@ -340,6 +340,107 @@ static ARM64SysRegField *get_field(int i, ARM64SysReg 
>>> *reg)
>>>    return NULL;
>>> }
>>> 
>>> +
>>> +/**
>>> + * kvm_arm_vcpu_validate_sysreg:
>>> + *
>>> + * Validate a SYSREG field value is consistent with legacy composite 
>>> options
>>> + * Some checks are not implemented because the corresponding sysreg field
>>> + * is not currently writable. In that case we make sure the field has not
>>> + * become writable, which would mean the user had the capability to set the
>>> + * corresponding property.
>>> + *
>>> + * return true if consistent. false if it is not, along with an error 
>>> handle
>>> + */
>>> +static bool kvm_arm_vcpu_validate_sysreg(ARMCPU *cpu, ARM64SysRegField 
>>> *field,
>>> +                                         uint64_t value, Error **errp)
>>> +{
>>> +    const char *fieldname = field->name;
>>> +    ARM64SysReg *sysregdesc = &arm64_id_regs[field->index];
>>> +    const char *regname = sysregdesc->name;
>>> +    g_autofree char *propname = g_strdup_printf("SYSREG_%s_%s", regname, 
>>> fieldname);
>>> +
>>> +    /* virtualization */
>>> +    if (!strcmp(propname, "SYSREG_ID_AA64PFR0_EL1_EL2")) {
>>> +        /* consistency with machine virtualization property */
>>> +        if (cpu->has_el2 && value == 0) {
>>> +            error_setg(errp,
>>> +                "Inconsistent -machine virtualization=on and "
>>> +                "%s=0", propname);
>>> +            return false;
>>> +        } else if (!cpu->has_el2 && value > 0) {
>>> +            error_setg(errp,
>>> +                "Inconsistent -machine virtualization=off and "
>>> +                "%s > 0", propname);
>>> +            return false;
>>> +        }
>>> +    /* secure */
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64PFR0_EL1_EL3") && value > 
>>> 0) {
>>> +        /* consistency with machine secure property */
>>> +        error_setg(errp, "%s is set but qemu is not ready to support it",
>>> +                   propname);
>>> +        return false;
>>> +    /* MTE */
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64PFR1_EL1_MTE")) {
>>> +        error_setg(errp, "%s is now exposed but qemu is not ready to 
>>> support it",
>>> +                   propname);
>>> +        return false;
>>> +    /* SVE */
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64PFR0_EL1_SVE")) {
>>> +        error_setg(errp, "%s is now exposed but qemu is not ready to 
>>> support it",
>>> +                   propname);
>>> +        return false;
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64ZFR0_EL1_SVEver")) {
>>> +        if (cpu_isar_feature(aa64_sve, cpu) && value == 0) {
>>> +            error_setg(errp, "sve is set but %s is set to 0", propname);
>>> +            return false;
>>> +        } else if (!cpu_isar_feature(aa64_sve, cpu) && value > 0) {
>>> +            error_setg(errp, "sve is not set but %s is greater than 0",
>>> +                       propname);
>>> +            return false;
>>> +        }
>>> +    /* PAUTH */
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64ISAR1_EL1_APA")) {
>>> +        /* PAUTH QARMA5 address authentification */
>>> +        error_setg(errp, "%s is now exposed but qemu is not ready to 
>>> support it",
>>> +                   propname);
>>> +        return false;
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64ISAR1_EL1_API")) {
>>> +        /* PAUTH Impl Defined address authentification */
>>> +        error_setg(errp, "%s is now exposed but qemu is not ready to 
>>> support it",
>>> +                   propname);
>>> +        return false;
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64ISAR1_EL1_GPA")) {
>>> +        /* QARMA5 generic code authentification */
>>> +        error_setg(errp, "%s is now exposed but qemu is not ready to 
>>> support it",
>>> +                   propname);
>>> +        return false;
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64ISAR1_EL1_GPI")) {
>>> +        /* QARMA5 generic code authentification */
>>> +        error_setg(errp, "%s is now exposed but qemu is not ready to 
>>> support it",
>>> +                   propname);
>>> +        return false;
>>> +    /* PMU */
>>> +    } else if (!strcmp(propname, "SYSREG_ID_AA64DFR0_EL1_PMUVer")) {
>>> +        if (cpu->has_pmu && value == 0) {
>>> +            error_setg(errp, "%s is 0 whereas pmu is set", propname);
>>> +            return false;
>>> +        } else if (!cpu->has_pmu && value) {
>>> +            error_setg(errp, "%s is non null whereas pmu is unset", 
>>> propname);
>>> +            return false;
>>> +        }
>>> +    /* aarch64 false */
>>> +    } else if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
>>> +        if ((!strcmp(propname, "SYSREG_ID_AA64PFR0_EL1_EL0") ||
>>> +             !strcmp(propname, "SYSREG_ID_AA64PFR0_EL1_EL1") ||
>>> +             !strcmp(propname, "SYSREG_ID_AA64PFR0_EL1_EL2")) && value < 2)
>>> +            error_setg(errp, "%s is < 2 while aarch64 is set to off",
>>> +                       propname);
>>> +            return false;
>>> +    }
>>> +    return true;
>>> +}
>>> +
>>> #define MAKE_IDREG_KEY(reg_idx, field_shift) \
>>>    (((uint64_t)(reg_idx) << 8) | ((uint64_t)(field_shift) & 0xFF))
>>> 
>>> @@ -2241,6 +2342,10 @@ static int kvm_arm_apply_sysreg_props(ARMCPU *cpu, 
>>> Error **errp)
>>>        uint64_t oldfv;
>>>        int ret;
>>> 
>>> +        if (!kvm_arm_vcpu_validate_sysreg(cpu, field, value, errp)) {
>>> +            return -1;
>>> +        }
>>> +
>>>        mask = MAKE_64BIT_MASK(lower, length);
>>>        value = value << lower;
>>> 
>>> -- 
>>> 2.53.0


Reply via email to