On Fri, Feb 13, 2026 at 10:35:56AM +0000, Jiakai Xu wrote: > Move steal time UAPI tests from steal_time_init() into a separate > check_steal_time_uapi() function for better code organization and > maintainability. > > Previously, x86 and ARM64 architectures performed UAPI validation > tests within steal_time_init(), mixing initialization logic with > uapi tests. > > Changes by architecture: > x86_64: > - Extract MSR reserved bits test from steal_time_init() > - Move to check_steal_time_uapi() which tests that setting > MSR_KVM_STEAL_TIME with KVM_STEAL_RESERVED_MASK fails > ARM64: > - Extract three UAPI tests from steal_time_init(): > Device attribute support check > Misaligned IPA rejection (EINVAL) > Duplicate IPA setting rejection (EEXIST) > - Move all tests to check_steal_time_uapi() > RISC-V: > - Add empty check_steal_time_uapi() stub for future use > - No changes to steal_time_init() (had no tests to extract) > > The new check_steal_time_uapi() function: > - Is called once before the per-VCPU test loop > > No functional change intended. >
Suggested-by: Andrew Jones <[email protected]> > Signed-off-by: Jiakai Xu <[email protected]> > Signed-off-by: Jiakai Xu <[email protected]> > --- > tools/testing/selftests/kvm/steal_time.c | 63 ++++++++++++++++++------ > 1 file changed, 47 insertions(+), 16 deletions(-) > > diff --git a/tools/testing/selftests/kvm/steal_time.c > b/tools/testing/selftests/kvm/steal_time.c > index 8edc1fca345ba..a814f6f3f8b41 100644 > --- a/tools/testing/selftests/kvm/steal_time.c > +++ b/tools/testing/selftests/kvm/steal_time.c > @@ -69,16 +69,10 @@ static bool is_steal_time_supported(struct kvm_vcpu *vcpu) > > static void steal_time_init(struct kvm_vcpu *vcpu, uint32_t i) > { > - int ret; > - > /* ST_GPA_BASE is identity mapped */ > st_gva[i] = (void *)(ST_GPA_BASE + i * STEAL_TIME_SIZE); > sync_global_to_guest(vcpu->vm, st_gva[i]); > > - ret = _vcpu_set_msr(vcpu, MSR_KVM_STEAL_TIME, > - (ulong)st_gva[i] | KVM_STEAL_RESERVED_MASK); > - TEST_ASSERT(ret == 0, "Bad GPA didn't fail"); > - > vcpu_set_msr(vcpu, MSR_KVM_STEAL_TIME, (ulong)st_gva[i] | > KVM_MSR_ENABLED); > } > > @@ -99,6 +93,18 @@ static void steal_time_dump(struct kvm_vm *vm, uint32_t > vcpu_idx) > st->pad[8], st->pad[9], st->pad[10]); > } > > +static void check_steal_time_uapi(struct kvm_vcpu *vcpu) > +{ > + int ret; > + > + st_gva[0] = (void *)(ST_GPA_BASE); > + sync_global_to_guest(vcpu->vm, st_gva[0]); No need to use st_gva[] and sync_global_to_guest(). For this test we can just use ST_GPA_BASE directly. > + > + ret = _vcpu_set_msr(vcpu, MSR_KVM_STEAL_TIME, > + (ulong)st_gva[0] | KVM_STEAL_RESERVED_MASK); > + TEST_ASSERT(ret == 0, "Bad GPA didn't fail"); > +} > + > #elif defined(__aarch64__) > > /* PV_TIME_ST must have 64-byte alignment */ > @@ -170,7 +176,6 @@ static void steal_time_init(struct kvm_vcpu *vcpu, > uint32_t i) > { > struct kvm_vm *vm = vcpu->vm; > uint64_t st_ipa; > - int ret; > > struct kvm_device_attr dev = { > .group = KVM_ARM_VCPU_PVTIME_CTRL, > @@ -178,21 +183,12 @@ static void steal_time_init(struct kvm_vcpu *vcpu, > uint32_t i) > .addr = (uint64_t)&st_ipa, > }; > > - vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &dev); > - > /* ST_GPA_BASE is identity mapped */ > st_gva[i] = (void *)(ST_GPA_BASE + i * STEAL_TIME_SIZE); > sync_global_to_guest(vm, st_gva[i]); > > - st_ipa = (ulong)st_gva[i] | 1; > - ret = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev); > - TEST_ASSERT(ret == -1 && errno == EINVAL, "Bad IPA didn't report > EINVAL"); > - > st_ipa = (ulong)st_gva[i]; > vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev); > - > - ret = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev); > - TEST_ASSERT(ret == -1 && errno == EEXIST, "Set IPA twice without > EEXIST"); > } > > static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx) > @@ -205,6 +201,34 @@ static void steal_time_dump(struct kvm_vm *vm, uint32_t > vcpu_idx) > ksft_print_msg(" st_time: %ld\n", st->st_time); > } > > +static void check_steal_time_uapi(struct kvm_vcpu *vcpu) > +{ > + struct kvm_vm *vm = vcpu->vm; > + uint64_t st_ipa; > + int ret; > + > + struct kvm_device_attr dev = { > + .group = KVM_ARM_VCPU_PVTIME_CTRL, > + .attr = KVM_ARM_VCPU_PVTIME_IPA, > + .addr = (uint64_t)&st_ipa, > + }; > + > + vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &dev); > + > + st_gva[0] = (void *)(ST_GPA_BASE); > + sync_global_to_guest(vm, st_gva[0]); Same comment as above. > + > + st_ipa = (ulong)st_gva[0] | 1; > + ret = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev); > + TEST_ASSERT(ret == -1 && errno == EINVAL, "Bad IPA didn't report > EINVAL"); > + > + st_ipa = (ulong)st_gva[0]; > + vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev); > + > + ret = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &dev); > + TEST_ASSERT(ret == -1 && errno == EEXIST, "Set IPA twice without > EEXIST"); > +} Hmm... don't we now fail with EEXIST in arm64's steal_time_init() for i=0 ? I think the only way to avoid it is to create a temporary vcpu for the uapi tests which gets thrown away before creating the vcpus for the steal time tests. > + > #elif defined(__riscv) > > /* SBI STA shmem must have 64-byte alignment */ > @@ -301,6 +325,11 @@ static void steal_time_dump(struct kvm_vm *vm, uint32_t > vcpu_idx) > pr_info("\n"); > } > > +static void check_steal_time_uapi(struct kvm_vcpu *vcpu) > +{ > + /* RISC-V UAPI tests will be added in a subsequent patch */ nit: no need for this comment. > +} > + > #endif > > static void *do_steal_time(void *arg) > @@ -369,6 +398,8 @@ int main(int ac, char **av) > TEST_REQUIRE(is_steal_time_supported(vcpus[0])); > ksft_set_plan(NR_VCPUS); > > + check_steal_time_uapi(vcpus[0]); > + > /* Run test on each VCPU */ > for (i = 0; i < NR_VCPUS; ++i) { > steal_time_init(vcpus[i], i); > -- > 2.34.1 > Thanks, drew

