Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm64: selftests: Handle feature fields with nonzero minimum value correctly

There are some feature fields with nonzero minimum valid value. Make
sure get_safe_value() won't return invalid field values for them.
Also fix a bug that wrongly uses the feature bits type as the feature
bits sign causing all fields as signed in the get_safe_value() and
get_invalid_value().

Fixes: 54a9ea73527d ("KVM: arm64: selftests: Test for setting ID register from usersapce")
Reported-by: Zenghui Yu <yuzenghui@huawei.com>
Reported-by: Itaru Kitayama <itaru.kitayama@linux.dev>
Tested-by: Itaru Kitayama <itaru.kitayama@fujitsu.com>
Signed-off-by: Jing Zhang <jingzhangos@google.com>
Link: https://lore.kernel.org/r/20240115220210.3966064-2-jingzhangos@google.com
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>

authored by

Jing Zhang and committed by
Oliver Upton
1cd2b08f 6613476e

+11 -7
+11 -7
tools/testing/selftests/kvm/aarch64/set_id_regs.c
··· 32 32 enum ftr_type type; 33 33 uint8_t shift; 34 34 uint64_t mask; 35 + /* 36 + * For FTR_EXACT, safe_val is used as the exact safe value. 37 + * For FTR_LOWER_SAFE, safe_val is used as the minimal safe value. 38 + */ 35 39 int64_t safe_val; 36 40 }; 37 41 ··· 69 65 70 66 static const struct reg_ftr_bits ftr_id_aa64dfr0_el1[] = { 71 67 S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, PMUVer, 0), 72 - REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, DebugVer, 0), 68 + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, DebugVer, ID_AA64DFR0_EL1_DebugVer_IMP), 73 69 REG_FTR_END, 74 70 }; 75 71 76 72 static const struct reg_ftr_bits ftr_id_dfr0_el1[] = { 77 - S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_DFR0_EL1, PerfMon, 0), 78 - REG_FTR_BITS(FTR_LOWER_SAFE, ID_DFR0_EL1, CopDbg, 0), 73 + S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_DFR0_EL1, PerfMon, ID_DFR0_EL1_PerfMon_PMUv3), 74 + REG_FTR_BITS(FTR_LOWER_SAFE, ID_DFR0_EL1, CopDbg, ID_DFR0_EL1_CopDbg_Armv8), 79 75 REG_FTR_END, 80 76 }; 81 77 ··· 228 224 { 229 225 uint64_t ftr_max = GENMASK_ULL(ARM64_FEATURE_FIELD_BITS - 1, 0); 230 226 231 - if (ftr_bits->type == FTR_UNSIGNED) { 227 + if (ftr_bits->sign == FTR_UNSIGNED) { 232 228 switch (ftr_bits->type) { 233 229 case FTR_EXACT: 234 230 ftr = ftr_bits->safe_val; 235 231 break; 236 232 case FTR_LOWER_SAFE: 237 - if (ftr > 0) 233 + if (ftr > ftr_bits->safe_val) 238 234 ftr--; 239 235 break; 240 236 case FTR_HIGHER_SAFE: ··· 256 252 ftr = ftr_bits->safe_val; 257 253 break; 258 254 case FTR_LOWER_SAFE: 259 - if (ftr > 0) 255 + if (ftr > ftr_bits->safe_val) 260 256 ftr--; 261 257 break; 262 258 case FTR_HIGHER_SAFE: ··· 280 276 { 281 277 uint64_t ftr_max = GENMASK_ULL(ARM64_FEATURE_FIELD_BITS - 1, 0); 282 278 283 - if (ftr_bits->type == FTR_UNSIGNED) { 279 + if (ftr_bits->sign == FTR_UNSIGNED) { 284 280 switch (ftr_bits->type) { 285 281 case FTR_EXACT: 286 282 ftr = max((uint64_t)ftr_bits->safe_val + 1, ftr + 1);