From: Peng Liang <liangpeng10@huawei.com>
To: Andrew Jones <drjones@redhat.com>
Cc: zhang.zhanghailiang@huawei.com, kvm@vger.kernel.org,
maz@kernel.org, will@kernel.org, kvmarm@lists.cs.columbia.edu
Subject: Re: [RFC v2 5/7] kvm: arm64: implement check_user for ID registers
Date: Fri, 18 Sep 2020 17:26:29 +0800 [thread overview]
Message-ID: <370b5645-edad-e233-0dbe-2459b5d50e1c@huawei.com> (raw)
In-Reply-To: <20200918074609.tet63j5x7i7n4wp7@kamzik.brq.redhat.com>
On 9/18/2020 3:46 PM, Andrew Jones wrote:
> On Thu, Sep 17, 2020 at 08:00:59PM +0800, Peng Liang wrote:
>> For most ID registers, only neeed to check each field defined by user
>> space is no more than that in host and only the fields we want to
>> exposed to guest is set. For some ID registers, the relationship
>> between some fields need to be check or we'd better to keep the same
>> value as host for some fields.
>>
>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
>> ---
>> arch/arm64/kvm/sys_regs.c | 425 +++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 424 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
>> index 86ebb8093c3c..a642ecfebe0a 100644
>> --- a/arch/arm64/kvm/sys_regs.c
>> +++ b/arch/arm64/kvm/sys_regs.c
>> @@ -1385,12 +1385,433 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> return true;
>> }
>>
>> +#define ID_CHECKER(reg) __check_ ##reg
>> +
>> +static int __general_id_checker(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> +
>> + return check_features(reg_id, val);
>> +}
>> +
>> +static int ID_CHECKER(ID_PFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_PFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_PFR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_DFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val, host_val;
>> + u64 mask = ((0xfUL << ID_DFR0_PERFMON_SHIFT) |
>> + (0xfUL << ID_DFR0_MMAPDBG_SHIFT) |
>> + (0xfUL << ID_DFR0_COPDBG_SHIFT) |
>> + (0xfUL << ID_DFR0_COPDBG_SHIFT));
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + host_val = read_sanitised_ftr_reg(reg_id);
>> + return (val & mask) == (host_val & mask) ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR3_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR4_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR5_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR3_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR4_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR5_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR6_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(MVFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>
> There has to be a better way to handle all these redundant functions...
>
>> +
>> +static int ID_CHECKER(MVFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> + unsigned int fphp, simdhp;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + fphp = cpuid_feature_extract_signed_field(val, MVFR1_FPHP_SHIFT);
>> + simdhp = cpuid_feature_extract_signed_field(val, MVFR1_SIMDHP_SHIFT);
>> + return ((fphp == 0 && simdhp == 0) || (fphp == 2 && simdhp == 1) ||
>> + (fphp == 3 && simdhp == 2)) ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(MVFR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64PFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> + unsigned int fp, asimd;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + fp = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_FP_SHIFT);
>> + asimd = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_ASIMD_SHIFT);
>> + return fp == asimd ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64PFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64DFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val, host_val;
>> + u64 mask = ((0xfUL << ID_AA64DFR0_PMUVER_SHIFT) |
>> + (0xfUL << ID_AA64DFR0_DEBUGVER_SHIFT) |
>> + (0xfUL << ID_AA64DFR0_CTX_CMPS_SHIFT) |
>> + (0xfUL << ID_AA64DFR0_WRPS_SHIFT) |
>> + (0xfUL << ID_AA64DFR0_BRPS_SHIFT));
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + host_val = read_sanitised_ftr_reg(reg_id);
>> + return (val & mask) == (host_val & mask) ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64DFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64ISAR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> + unsigned int sm3, sm4, sha1, sha2, sha3;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + sm3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM3_SHIFT);
>> + sm4 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM4_SHIFT);
>> + /*
>> + * ID_AA64ISAR0_EL1.SM3 and ID_AA64ISAR0_EL1.SM4 must have the same
>> + * value.
>> + */
>> + if (sm3 != sm4)
>> + return -EINVAL;
>> +
>> + sha1 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA1_SHIFT);
>> + sha2 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA2_SHIFT);
>> + sha3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA3_SHIFT);
>> + /*
>> + * 1. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then
>> + * ID_AA64ISAR0_EL1.SHA2 must have the value 0, and vice versa;
>> + * 2. If the value of ID_AA64ISAR0_EL1.SHA2 is 2, then
>> + * ID_AA64ISAR0_EL1.SHA3 must have the value 1, and vice versa;
>> + * 3. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then
>> + * ID_AA64ISAR0_EL1.SHA3 must have the value 0;
>> + */
>> + if ((sha1 ^ sha2) || ((sha2 == 2) ^ (sha3 == 1)) || (!sha1 && sha3))
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64ISAR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> + unsigned int gpi, gpa, api, apa;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + gpi = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPI_SHIFT);
>> + gpa = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPA_SHIFT);
>> + api = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_API_SHIFT);
>> + apa = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_APA_SHIFT);
>> + /*
>> + * 1. If the value of ID_AA64ISAR1_EL1.GPA is non-zero, then
>> + * ID_AA64ISAR1_EL1.GPI must have the value 0;
>> + * 2. If the value of ID_AA64ISAR1_EL1.GPI is non-zero, then
>> + * ID_AA64ISAR1_EL1.GPA must have the value 0;
>> + * 3. If the value of ID_AA64ISAR1_EL1.APA is non-zero, then
>> + * ID_AA64ISAR1_EL1.API must have the value 0;
>> + * 4. If the value of ID_AA64ISAR1_EL1.API is non-zero, then
>> + * ID_AA64ISAR1_EL1.APA must have the value 0;
>> + */
>> + if ((gpi && gpa) || (api && apa))
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64MMFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val, host_val;
>> + u64 mask = ((0xfUL << ID_AA64MMFR0_TGRAN4_2_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN64_2_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN16_2_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN4_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN64_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN16_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_ASID_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_PARANGE_SHIFT));
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + host_val = read_sanitised_ftr_reg(reg_id);
>> + return (val & mask) == (host_val & mask) ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64MMFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val, host_val;
>> + unsigned int vmidbits, host_vmidbits;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + vmidbits = cpuid_feature_extract_unsigned_field(val, ID_AA64MMFR1_VMIDBITS_SHIFT);
>> + host_val = read_sanitised_ftr_reg(reg_id);
>> + host_vmidbits = cpuid_feature_extract_signed_field(host_val, ID_AA64MMFR1_VMIDBITS_SHIFT);
>> + return vmidbits == host_vmidbits ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64MMFR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> /* sys_reg_desc initialiser for known cpufeature ID registers */
>> #define ID_SANITISED(name) { \
>> SYS_DESC(SYS_##name), \
>> .access = access_id_reg, \
>> .get_user = get_id_reg, \
>> .set_user = set_id_reg, \
>> + .check_user = ID_CHECKER(name), \
>
> This patch makes it clear that continuing to use ID_SANITISED() for all ID
> registers makes no sense.
>
>> }
>>
>> /*
>> @@ -1512,7 +1933,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>> ID_SANITISED(ID_AA64PFR1_EL1),
>> ID_UNALLOCATED(4,2),
>> ID_UNALLOCATED(4,3),
>> - { SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, .visibility = sve_id_visibility },
>> + { SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1,
>> + .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1,
>> + .check_user = __general_id_checker, .visibility = sve_id_visibility },
>> ID_UNALLOCATED(4,5),
>> ID_UNALLOCATED(4,6),
>> ID_UNALLOCATED(4,7),
>> --
>> 2.26.2
>>
>
> Thanks,
> drew
>
> .
>
I also think this patch is a little ugly. I will refactor the code to
remove the sharing set_user of ID registers in next version.
Thanks,
Peng
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
WARNING: multiple messages have this Message-ID (diff)
From: Peng Liang <liangpeng10@huawei.com>
To: Andrew Jones <drjones@redhat.com>
Cc: <kvmarm@lists.cs.columbia.edu>, <kvm@vger.kernel.org>,
<maz@kernel.org>, <will@kernel.org>,
<zhang.zhanghailiang@huawei.com>, <xiexiangyou@huawei.com>
Subject: Re: [RFC v2 5/7] kvm: arm64: implement check_user for ID registers
Date: Fri, 18 Sep 2020 17:26:29 +0800 [thread overview]
Message-ID: <370b5645-edad-e233-0dbe-2459b5d50e1c@huawei.com> (raw)
In-Reply-To: <20200918074609.tet63j5x7i7n4wp7@kamzik.brq.redhat.com>
On 9/18/2020 3:46 PM, Andrew Jones wrote:
> On Thu, Sep 17, 2020 at 08:00:59PM +0800, Peng Liang wrote:
>> For most ID registers, only neeed to check each field defined by user
>> space is no more than that in host and only the fields we want to
>> exposed to guest is set. For some ID registers, the relationship
>> between some fields need to be check or we'd better to keep the same
>> value as host for some fields.
>>
>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
>> ---
>> arch/arm64/kvm/sys_regs.c | 425 +++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 424 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
>> index 86ebb8093c3c..a642ecfebe0a 100644
>> --- a/arch/arm64/kvm/sys_regs.c
>> +++ b/arch/arm64/kvm/sys_regs.c
>> @@ -1385,12 +1385,433 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> return true;
>> }
>>
>> +#define ID_CHECKER(reg) __check_ ##reg
>> +
>> +static int __general_id_checker(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> +
>> + return check_features(reg_id, val);
>> +}
>> +
>> +static int ID_CHECKER(ID_PFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_PFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_PFR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_DFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val, host_val;
>> + u64 mask = ((0xfUL << ID_DFR0_PERFMON_SHIFT) |
>> + (0xfUL << ID_DFR0_MMAPDBG_SHIFT) |
>> + (0xfUL << ID_DFR0_COPDBG_SHIFT) |
>> + (0xfUL << ID_DFR0_COPDBG_SHIFT));
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + host_val = read_sanitised_ftr_reg(reg_id);
>> + return (val & mask) == (host_val & mask) ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR3_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR4_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_MMFR5_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR3_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR4_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR5_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_ISAR6_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(MVFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>
> There has to be a better way to handle all these redundant functions...
>
>> +
>> +static int ID_CHECKER(MVFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> + unsigned int fphp, simdhp;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + fphp = cpuid_feature_extract_signed_field(val, MVFR1_FPHP_SHIFT);
>> + simdhp = cpuid_feature_extract_signed_field(val, MVFR1_SIMDHP_SHIFT);
>> + return ((fphp == 0 && simdhp == 0) || (fphp == 2 && simdhp == 1) ||
>> + (fphp == 3 && simdhp == 2)) ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(MVFR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64PFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> + unsigned int fp, asimd;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + fp = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_FP_SHIFT);
>> + asimd = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_ASIMD_SHIFT);
>> + return fp == asimd ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64PFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64DFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val, host_val;
>> + u64 mask = ((0xfUL << ID_AA64DFR0_PMUVER_SHIFT) |
>> + (0xfUL << ID_AA64DFR0_DEBUGVER_SHIFT) |
>> + (0xfUL << ID_AA64DFR0_CTX_CMPS_SHIFT) |
>> + (0xfUL << ID_AA64DFR0_WRPS_SHIFT) |
>> + (0xfUL << ID_AA64DFR0_BRPS_SHIFT));
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + host_val = read_sanitised_ftr_reg(reg_id);
>> + return (val & mask) == (host_val & mask) ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64DFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64ISAR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> + unsigned int sm3, sm4, sha1, sha2, sha3;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + sm3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM3_SHIFT);
>> + sm4 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM4_SHIFT);
>> + /*
>> + * ID_AA64ISAR0_EL1.SM3 and ID_AA64ISAR0_EL1.SM4 must have the same
>> + * value.
>> + */
>> + if (sm3 != sm4)
>> + return -EINVAL;
>> +
>> + sha1 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA1_SHIFT);
>> + sha2 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA2_SHIFT);
>> + sha3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA3_SHIFT);
>> + /*
>> + * 1. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then
>> + * ID_AA64ISAR0_EL1.SHA2 must have the value 0, and vice versa;
>> + * 2. If the value of ID_AA64ISAR0_EL1.SHA2 is 2, then
>> + * ID_AA64ISAR0_EL1.SHA3 must have the value 1, and vice versa;
>> + * 3. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then
>> + * ID_AA64ISAR0_EL1.SHA3 must have the value 0;
>> + */
>> + if ((sha1 ^ sha2) || ((sha2 == 2) ^ (sha3 == 1)) || (!sha1 && sha3))
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64ISAR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val;
>> + unsigned int gpi, gpa, api, apa;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + gpi = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPI_SHIFT);
>> + gpa = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPA_SHIFT);
>> + api = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_API_SHIFT);
>> + apa = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_APA_SHIFT);
>> + /*
>> + * 1. If the value of ID_AA64ISAR1_EL1.GPA is non-zero, then
>> + * ID_AA64ISAR1_EL1.GPI must have the value 0;
>> + * 2. If the value of ID_AA64ISAR1_EL1.GPI is non-zero, then
>> + * ID_AA64ISAR1_EL1.GPA must have the value 0;
>> + * 3. If the value of ID_AA64ISAR1_EL1.APA is non-zero, then
>> + * ID_AA64ISAR1_EL1.API must have the value 0;
>> + * 4. If the value of ID_AA64ISAR1_EL1.API is non-zero, then
>> + * ID_AA64ISAR1_EL1.APA must have the value 0;
>> + */
>> + if ((gpi && gpa) || (api && apa))
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64MMFR0_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val, host_val;
>> + u64 mask = ((0xfUL << ID_AA64MMFR0_TGRAN4_2_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN64_2_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN16_2_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN4_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN64_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_TGRAN16_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_ASID_SHIFT) |
>> + (0xfUL << ID_AA64MMFR0_PARANGE_SHIFT));
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + host_val = read_sanitised_ftr_reg(reg_id);
>> + return (val & mask) == (host_val & mask) ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64MMFR1_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
>> + (u32)rd->CRm, (u32)rd->Op2);
>> + int err;
>> + u64 val, host_val;
>> + unsigned int vmidbits, host_vmidbits;
>> +
>> + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
>> + if (err)
>> + return err;
>> + err = check_features(reg_id, val);
>> + if (err)
>> + return err;
>> +
>> + vmidbits = cpuid_feature_extract_unsigned_field(val, ID_AA64MMFR1_VMIDBITS_SHIFT);
>> + host_val = read_sanitised_ftr_reg(reg_id);
>> + host_vmidbits = cpuid_feature_extract_signed_field(host_val, ID_AA64MMFR1_VMIDBITS_SHIFT);
>> + return vmidbits == host_vmidbits ? 0 : -EINVAL;
>> +}
>> +
>> +static int ID_CHECKER(ID_AA64MMFR2_EL1)(struct kvm_vcpu *vcpu,
>> + const struct sys_reg_desc *rd,
>> + const struct kvm_one_reg *reg,
>> + void __user *uaddr)
>> +{
>> + return __general_id_checker(vcpu, rd, reg, uaddr);
>> +}
>> +
>> /* sys_reg_desc initialiser for known cpufeature ID registers */
>> #define ID_SANITISED(name) { \
>> SYS_DESC(SYS_##name), \
>> .access = access_id_reg, \
>> .get_user = get_id_reg, \
>> .set_user = set_id_reg, \
>> + .check_user = ID_CHECKER(name), \
>
> This patch makes it clear that continuing to use ID_SANITISED() for all ID
> registers makes no sense.
>
>> }
>>
>> /*
>> @@ -1512,7 +1933,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>> ID_SANITISED(ID_AA64PFR1_EL1),
>> ID_UNALLOCATED(4,2),
>> ID_UNALLOCATED(4,3),
>> - { SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, .visibility = sve_id_visibility },
>> + { SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1,
>> + .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1,
>> + .check_user = __general_id_checker, .visibility = sve_id_visibility },
>> ID_UNALLOCATED(4,5),
>> ID_UNALLOCATED(4,6),
>> ID_UNALLOCATED(4,7),
>> --
>> 2.26.2
>>
>
> Thanks,
> drew
>
> .
>
I also think this patch is a little ugly. I will refactor the code to
remove the sharing set_user of ID registers in next version.
Thanks,
Peng
next prev parent reply other threads:[~2020-09-18 9:26 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-17 12:00 [RFC v2 0/7] kvm: arm64: emulate ID registers Peng Liang
2020-09-17 12:00 ` Peng Liang
2020-09-17 12:00 ` [RFC v2 1/7] arm64: add a helper function to traverse arm64_ftr_regs Peng Liang
2020-09-17 12:00 ` Peng Liang
2020-09-18 7:18 ` Andrew Jones
2020-09-18 7:18 ` Andrew Jones
2020-09-18 9:24 ` Peng Liang
2020-09-18 9:24 ` Peng Liang
2020-09-18 10:28 ` Andrew Jones
2020-09-18 10:28 ` Andrew Jones
2020-09-18 11:58 ` Peng Liang
2020-09-18 11:58 ` Peng Liang
2020-09-17 12:00 ` [RFC v2 2/7] arm64: introduce check_features Peng Liang
2020-09-17 12:00 ` Peng Liang
2020-09-18 7:30 ` Andrew Jones
2020-09-18 7:30 ` Andrew Jones
2020-09-18 9:25 ` Peng Liang
2020-09-18 9:25 ` Peng Liang
2020-09-17 12:00 ` [RFC v2 3/7] kvm: arm64: save ID registers to sys_regs file Peng Liang
2020-09-17 12:00 ` Peng Liang
2020-09-18 7:34 ` Andrew Jones
2020-09-18 7:34 ` Andrew Jones
2020-09-17 12:00 ` [RFC v2 4/7] kvm: arm64: introduce check_user Peng Liang
2020-09-17 12:00 ` Peng Liang
2020-09-18 7:41 ` Andrew Jones
2020-09-18 7:41 ` Andrew Jones
2020-09-18 9:25 ` Peng Liang
2020-09-18 9:25 ` Peng Liang
2020-09-17 12:00 ` [RFC v2 5/7] kvm: arm64: implement check_user for ID registers Peng Liang
2020-09-17 12:00 ` Peng Liang
2020-09-18 7:46 ` Andrew Jones
2020-09-18 7:46 ` Andrew Jones
2020-09-18 9:26 ` Peng Liang [this message]
2020-09-18 9:26 ` Peng Liang
2020-09-17 12:01 ` [RFC v2 6/7] kvm: arm64: make ID registers configurable Peng Liang
2020-09-17 12:01 ` Peng Liang
2020-09-18 7:50 ` Andrew Jones
2020-09-18 7:50 ` Andrew Jones
2020-09-18 9:26 ` Peng Liang
2020-09-18 9:26 ` Peng Liang
2020-09-17 12:01 ` [RFC v2 7/7] kvm: arm64: add KVM_CAP_ARM_CPU_FEATURE extension Peng Liang
2020-09-17 12:01 ` Peng Liang
2020-09-18 7:55 ` Andrew Jones
2020-09-18 7:55 ` Andrew Jones
2020-09-18 9:26 ` Peng Liang
2020-09-18 9:26 ` Peng Liang
2020-09-18 8:01 ` [RFC v2 0/7] kvm: arm64: emulate ID registers Andrew Jones
2020-09-18 8:01 ` Andrew Jones
2020-09-18 9:51 ` Peng Liang
2020-09-18 9:51 ` Peng Liang
2020-09-18 10:20 ` Andrew Jones
2020-09-18 10:20 ` Andrew Jones
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=370b5645-edad-e233-0dbe-2459b5d50e1c@huawei.com \
--to=liangpeng10@huawei.com \
--cc=drjones@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=maz@kernel.org \
--cc=will@kernel.org \
--cc=zhang.zhanghailiang@huawei.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.