[PATCH] KVM: LoongArch: selftests: Add steal time test case

Bibo Mao posted 1 patch 1 week, 3 days ago
tools/testing/selftests/kvm/Makefile.kvm |  1 +
tools/testing/selftests/kvm/steal_time.c | 85 ++++++++++++++++++++++++
2 files changed, 86 insertions(+)
[PATCH] KVM: LoongArch: selftests: Add steal time test case
Posted by Bibo Mao 1 week, 3 days ago
LoongArch KVM supports steal time accounting now, here add steal time
test case on LoongArch.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 tools/testing/selftests/kvm/Makefile.kvm |  1 +
 tools/testing/selftests/kvm/steal_time.c | 85 ++++++++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index ba5c2b643efa..a18c00f1a4fa 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -228,6 +228,7 @@ TEST_GEN_PROGS_loongarch += kvm_page_table_test
 TEST_GEN_PROGS_loongarch += memslot_modification_stress_test
 TEST_GEN_PROGS_loongarch += memslot_perf_test
 TEST_GEN_PROGS_loongarch += set_memory_region_test
+TEST_GEN_PROGS_loongarch += steal_time
 
 SPLIT_TESTS += arch_timer
 SPLIT_TESTS += get-reg-list
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index 8edc1fca345b..ee13e8973c45 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -301,6 +301,91 @@ static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
 	pr_info("\n");
 }
 
+#elif defined(__loongarch__)
+/* steal_time must have 64-byte alignment */
+#define STEAL_TIME_SIZE		((sizeof(struct kvm_steal_time) + 63) & ~63)
+#define KVM_STEAL_PHYS_VALID	BIT_ULL(0)
+
+struct kvm_steal_time {
+	__u64 steal;
+	__u32 version;
+	__u32 flags;
+	__u32 pad[12];
+};
+
+static bool is_steal_time_supported(struct kvm_vcpu *vcpu)
+{
+	int err;
+	uint64_t val;
+	struct kvm_device_attr attr = {
+		.group = KVM_LOONGARCH_VCPU_CPUCFG,
+		.attr = CPUCFG_KVM_FEATURE,
+		.addr = (uint64_t)&val,
+	};
+
+	err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
+	if (err)
+		return false;
+
+	err = __vcpu_ioctl(vcpu, KVM_GET_DEVICE_ATTR, &attr);
+	if (err)
+		return false;
+
+	return val & BIT(KVM_FEATURE_STEAL_TIME);
+}
+
+static void steal_time_init(struct kvm_vcpu *vcpu, uint32_t i)
+{
+	struct kvm_vm *vm = vcpu->vm;
+	uint64_t st_gpa;
+	int err;
+	struct kvm_device_attr attr = {
+		.group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
+		.attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
+		.addr = (uint64_t)&st_gpa,
+	};
+
+	/* 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]);
+
+	err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
+	TEST_ASSERT(err == 0, "No PV stealtime Feature");
+
+	st_gpa = (unsigned long)st_gva[i] | KVM_STEAL_PHYS_VALID;
+	err = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &attr);
+	TEST_ASSERT(err == 0, "Fail to set PV stealtime GPA");
+}
+
+static void guest_code(int cpu)
+{
+	struct kvm_steal_time *st = st_gva[cpu];
+	uint32_t version;
+
+	memset(st, 0, sizeof(*st));
+	GUEST_SYNC(0);
+
+	GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
+	WRITE_ONCE(guest_stolen_time[cpu], st->steal);
+	version = READ_ONCE(st->version);
+	GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
+	GUEST_SYNC(1);
+
+	GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
+	GUEST_ASSERT(version < READ_ONCE(st->version));
+	WRITE_ONCE(guest_stolen_time[cpu], st->steal);
+	GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
+	GUEST_DONE();
+}
+
+static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
+{
+	struct kvm_steal_time *st = addr_gva2hva(vm, (ulong)st_gva[vcpu_idx]);
+
+	ksft_print_msg("VCPU%d:\n", vcpu_idx);
+	ksft_print_msg("    steal:     %lld\n", st->steal);
+	ksft_print_msg("    version:   %d\n", st->version);
+}
 #endif
 
 static void *do_steal_time(void *arg)

base-commit: 8dfce8991b95d8625d0a1d2896e42f93b9d7f68d
-- 
2.39.3
Re: [PATCH] KVM: LoongArch: selftests: Add steal time test case
Posted by Huacai Chen 1 week, 1 day ago
Since paravirt preempt is also applied, I applied this one with some
modifications, you can check whether it is correct.

https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git/commit/?h=loongarch-kvm&id=cf991b57ffc808d69cb1f911563b1d4658774ccf

Huacai

On Thu, Jan 29, 2026 at 10:18 AM Bibo Mao <maobibo@loongson.cn> wrote:
>
> LoongArch KVM supports steal time accounting now, here add steal time
> test case on LoongArch.
>
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>  tools/testing/selftests/kvm/Makefile.kvm |  1 +
>  tools/testing/selftests/kvm/steal_time.c | 85 ++++++++++++++++++++++++
>  2 files changed, 86 insertions(+)
>
> diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
> index ba5c2b643efa..a18c00f1a4fa 100644
> --- a/tools/testing/selftests/kvm/Makefile.kvm
> +++ b/tools/testing/selftests/kvm/Makefile.kvm
> @@ -228,6 +228,7 @@ TEST_GEN_PROGS_loongarch += kvm_page_table_test
>  TEST_GEN_PROGS_loongarch += memslot_modification_stress_test
>  TEST_GEN_PROGS_loongarch += memslot_perf_test
>  TEST_GEN_PROGS_loongarch += set_memory_region_test
> +TEST_GEN_PROGS_loongarch += steal_time
>
>  SPLIT_TESTS += arch_timer
>  SPLIT_TESTS += get-reg-list
> diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
> index 8edc1fca345b..ee13e8973c45 100644
> --- a/tools/testing/selftests/kvm/steal_time.c
> +++ b/tools/testing/selftests/kvm/steal_time.c
> @@ -301,6 +301,91 @@ static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
>         pr_info("\n");
>  }
>
> +#elif defined(__loongarch__)
> +/* steal_time must have 64-byte alignment */
> +#define STEAL_TIME_SIZE                ((sizeof(struct kvm_steal_time) + 63) & ~63)
> +#define KVM_STEAL_PHYS_VALID   BIT_ULL(0)
> +
> +struct kvm_steal_time {
> +       __u64 steal;
> +       __u32 version;
> +       __u32 flags;
> +       __u32 pad[12];
> +};
> +
> +static bool is_steal_time_supported(struct kvm_vcpu *vcpu)
> +{
> +       int err;
> +       uint64_t val;
> +       struct kvm_device_attr attr = {
> +               .group = KVM_LOONGARCH_VCPU_CPUCFG,
> +               .attr = CPUCFG_KVM_FEATURE,
> +               .addr = (uint64_t)&val,
> +       };
> +
> +       err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
> +       if (err)
> +               return false;
> +
> +       err = __vcpu_ioctl(vcpu, KVM_GET_DEVICE_ATTR, &attr);
> +       if (err)
> +               return false;
> +
> +       return val & BIT(KVM_FEATURE_STEAL_TIME);
> +}
> +
> +static void steal_time_init(struct kvm_vcpu *vcpu, uint32_t i)
> +{
> +       struct kvm_vm *vm = vcpu->vm;
> +       uint64_t st_gpa;
> +       int err;
> +       struct kvm_device_attr attr = {
> +               .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
> +               .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
> +               .addr = (uint64_t)&st_gpa,
> +       };
> +
> +       /* 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]);
> +
> +       err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
> +       TEST_ASSERT(err == 0, "No PV stealtime Feature");
> +
> +       st_gpa = (unsigned long)st_gva[i] | KVM_STEAL_PHYS_VALID;
> +       err = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &attr);
> +       TEST_ASSERT(err == 0, "Fail to set PV stealtime GPA");
> +}
> +
> +static void guest_code(int cpu)
> +{
> +       struct kvm_steal_time *st = st_gva[cpu];
> +       uint32_t version;
> +
> +       memset(st, 0, sizeof(*st));
> +       GUEST_SYNC(0);
> +
> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
> +       WRITE_ONCE(guest_stolen_time[cpu], st->steal);
> +       version = READ_ONCE(st->version);
> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
> +       GUEST_SYNC(1);
> +
> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
> +       GUEST_ASSERT(version < READ_ONCE(st->version));
> +       WRITE_ONCE(guest_stolen_time[cpu], st->steal);
> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
> +       GUEST_DONE();
> +}
> +
> +static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
> +{
> +       struct kvm_steal_time *st = addr_gva2hva(vm, (ulong)st_gva[vcpu_idx]);
> +
> +       ksft_print_msg("VCPU%d:\n", vcpu_idx);
> +       ksft_print_msg("    steal:     %lld\n", st->steal);
> +       ksft_print_msg("    version:   %d\n", st->version);
> +}
>  #endif
>
>  static void *do_steal_time(void *arg)
>
> base-commit: 8dfce8991b95d8625d0a1d2896e42f93b9d7f68d
> --
> 2.39.3
>
Re: [PATCH] KVM: LoongArch: selftests: Add steal time test case
Posted by Bibo Mao 6 days, 16 hours ago
Hi Huacai,

On 2026/1/31 下午9:47, Huacai Chen wrote:
> Since paravirt preempt is also applied, I applied this one with some
> modifications, you can check whether it is correct.
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git/commit/?h=loongarch-kvm&id=cf991b57ffc808d69cb1f911563b1d4658774ccf

I checked the pendning patches in loongarch-kvm branch, they all look 
good to me.

Thanks for doing this.

Regards
Bibo Mao
> 
> Huacai
> 
> On Thu, Jan 29, 2026 at 10:18 AM Bibo Mao <maobibo@loongson.cn> wrote:
>>
>> LoongArch KVM supports steal time accounting now, here add steal time
>> test case on LoongArch.
>>
>> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
>> ---
>>   tools/testing/selftests/kvm/Makefile.kvm |  1 +
>>   tools/testing/selftests/kvm/steal_time.c | 85 ++++++++++++++++++++++++
>>   2 files changed, 86 insertions(+)
>>
>> diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
>> index ba5c2b643efa..a18c00f1a4fa 100644
>> --- a/tools/testing/selftests/kvm/Makefile.kvm
>> +++ b/tools/testing/selftests/kvm/Makefile.kvm
>> @@ -228,6 +228,7 @@ TEST_GEN_PROGS_loongarch += kvm_page_table_test
>>   TEST_GEN_PROGS_loongarch += memslot_modification_stress_test
>>   TEST_GEN_PROGS_loongarch += memslot_perf_test
>>   TEST_GEN_PROGS_loongarch += set_memory_region_test
>> +TEST_GEN_PROGS_loongarch += steal_time
>>
>>   SPLIT_TESTS += arch_timer
>>   SPLIT_TESTS += get-reg-list
>> diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
>> index 8edc1fca345b..ee13e8973c45 100644
>> --- a/tools/testing/selftests/kvm/steal_time.c
>> +++ b/tools/testing/selftests/kvm/steal_time.c
>> @@ -301,6 +301,91 @@ static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
>>          pr_info("\n");
>>   }
>>
>> +#elif defined(__loongarch__)
>> +/* steal_time must have 64-byte alignment */
>> +#define STEAL_TIME_SIZE                ((sizeof(struct kvm_steal_time) + 63) & ~63)
>> +#define KVM_STEAL_PHYS_VALID   BIT_ULL(0)
>> +
>> +struct kvm_steal_time {
>> +       __u64 steal;
>> +       __u32 version;
>> +       __u32 flags;
>> +       __u32 pad[12];
>> +};
>> +
>> +static bool is_steal_time_supported(struct kvm_vcpu *vcpu)
>> +{
>> +       int err;
>> +       uint64_t val;
>> +       struct kvm_device_attr attr = {
>> +               .group = KVM_LOONGARCH_VCPU_CPUCFG,
>> +               .attr = CPUCFG_KVM_FEATURE,
>> +               .addr = (uint64_t)&val,
>> +       };
>> +
>> +       err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
>> +       if (err)
>> +               return false;
>> +
>> +       err = __vcpu_ioctl(vcpu, KVM_GET_DEVICE_ATTR, &attr);
>> +       if (err)
>> +               return false;
>> +
>> +       return val & BIT(KVM_FEATURE_STEAL_TIME);
>> +}
>> +
>> +static void steal_time_init(struct kvm_vcpu *vcpu, uint32_t i)
>> +{
>> +       struct kvm_vm *vm = vcpu->vm;
>> +       uint64_t st_gpa;
>> +       int err;
>> +       struct kvm_device_attr attr = {
>> +               .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
>> +               .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
>> +               .addr = (uint64_t)&st_gpa,
>> +       };
>> +
>> +       /* 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]);
>> +
>> +       err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
>> +       TEST_ASSERT(err == 0, "No PV stealtime Feature");
>> +
>> +       st_gpa = (unsigned long)st_gva[i] | KVM_STEAL_PHYS_VALID;
>> +       err = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &attr);
>> +       TEST_ASSERT(err == 0, "Fail to set PV stealtime GPA");
>> +}
>> +
>> +static void guest_code(int cpu)
>> +{
>> +       struct kvm_steal_time *st = st_gva[cpu];
>> +       uint32_t version;
>> +
>> +       memset(st, 0, sizeof(*st));
>> +       GUEST_SYNC(0);
>> +
>> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
>> +       WRITE_ONCE(guest_stolen_time[cpu], st->steal);
>> +       version = READ_ONCE(st->version);
>> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
>> +       GUEST_SYNC(1);
>> +
>> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
>> +       GUEST_ASSERT(version < READ_ONCE(st->version));
>> +       WRITE_ONCE(guest_stolen_time[cpu], st->steal);
>> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
>> +       GUEST_DONE();
>> +}
>> +
>> +static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
>> +{
>> +       struct kvm_steal_time *st = addr_gva2hva(vm, (ulong)st_gva[vcpu_idx]);
>> +
>> +       ksft_print_msg("VCPU%d:\n", vcpu_idx);
>> +       ksft_print_msg("    steal:     %lld\n", st->steal);
>> +       ksft_print_msg("    version:   %d\n", st->version);
>> +}
>>   #endif
>>
>>   static void *do_steal_time(void *arg)
>>
>> base-commit: 8dfce8991b95d8625d0a1d2896e42f93b9d7f68d
>> --
>> 2.39.3
>>

Re: [PATCH] KVM: LoongArch: selftests: Add steal time test case
Posted by Huacai Chen 6 days, 10 hours ago
On Mon, Feb 2, 2026 at 10:03 AM Bibo Mao <maobibo@loongson.cn> wrote:
>
> Hi Huacai,
>
> On 2026/1/31 下午9:47, Huacai Chen wrote:
> > Since paravirt preempt is also applied, I applied this one with some
> > modifications, you can check whether it is correct.
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git/commit/?h=loongarch-kvm&id=cf991b57ffc808d69cb1f911563b1d4658774ccf
>
> I checked the pendning patches in loongarch-kvm branch, they all look
> good to me.
OK, then are there any updates on this one?
https://lore.kernel.org/loongarch/CAAhV-H57b14qY+5jqe+Fd5FTQq6jrhurfNBCqBqwG6SUpKFhTw@mail.gmail.com/T/#t

Huacai
>
> Thanks for doing this.
>
> Regards
> Bibo Mao
> >
> > Huacai
> >
> > On Thu, Jan 29, 2026 at 10:18 AM Bibo Mao <maobibo@loongson.cn> wrote:
> >>
> >> LoongArch KVM supports steal time accounting now, here add steal time
> >> test case on LoongArch.
> >>
> >> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> >> ---
> >>   tools/testing/selftests/kvm/Makefile.kvm |  1 +
> >>   tools/testing/selftests/kvm/steal_time.c | 85 ++++++++++++++++++++++++
> >>   2 files changed, 86 insertions(+)
> >>
> >> diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
> >> index ba5c2b643efa..a18c00f1a4fa 100644
> >> --- a/tools/testing/selftests/kvm/Makefile.kvm
> >> +++ b/tools/testing/selftests/kvm/Makefile.kvm
> >> @@ -228,6 +228,7 @@ TEST_GEN_PROGS_loongarch += kvm_page_table_test
> >>   TEST_GEN_PROGS_loongarch += memslot_modification_stress_test
> >>   TEST_GEN_PROGS_loongarch += memslot_perf_test
> >>   TEST_GEN_PROGS_loongarch += set_memory_region_test
> >> +TEST_GEN_PROGS_loongarch += steal_time
> >>
> >>   SPLIT_TESTS += arch_timer
> >>   SPLIT_TESTS += get-reg-list
> >> diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
> >> index 8edc1fca345b..ee13e8973c45 100644
> >> --- a/tools/testing/selftests/kvm/steal_time.c
> >> +++ b/tools/testing/selftests/kvm/steal_time.c
> >> @@ -301,6 +301,91 @@ static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
> >>          pr_info("\n");
> >>   }
> >>
> >> +#elif defined(__loongarch__)
> >> +/* steal_time must have 64-byte alignment */
> >> +#define STEAL_TIME_SIZE                ((sizeof(struct kvm_steal_time) + 63) & ~63)
> >> +#define KVM_STEAL_PHYS_VALID   BIT_ULL(0)
> >> +
> >> +struct kvm_steal_time {
> >> +       __u64 steal;
> >> +       __u32 version;
> >> +       __u32 flags;
> >> +       __u32 pad[12];
> >> +};
> >> +
> >> +static bool is_steal_time_supported(struct kvm_vcpu *vcpu)
> >> +{
> >> +       int err;
> >> +       uint64_t val;
> >> +       struct kvm_device_attr attr = {
> >> +               .group = KVM_LOONGARCH_VCPU_CPUCFG,
> >> +               .attr = CPUCFG_KVM_FEATURE,
> >> +               .addr = (uint64_t)&val,
> >> +       };
> >> +
> >> +       err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
> >> +       if (err)
> >> +               return false;
> >> +
> >> +       err = __vcpu_ioctl(vcpu, KVM_GET_DEVICE_ATTR, &attr);
> >> +       if (err)
> >> +               return false;
> >> +
> >> +       return val & BIT(KVM_FEATURE_STEAL_TIME);
> >> +}
> >> +
> >> +static void steal_time_init(struct kvm_vcpu *vcpu, uint32_t i)
> >> +{
> >> +       struct kvm_vm *vm = vcpu->vm;
> >> +       uint64_t st_gpa;
> >> +       int err;
> >> +       struct kvm_device_attr attr = {
> >> +               .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
> >> +               .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
> >> +               .addr = (uint64_t)&st_gpa,
> >> +       };
> >> +
> >> +       /* 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]);
> >> +
> >> +       err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
> >> +       TEST_ASSERT(err == 0, "No PV stealtime Feature");
> >> +
> >> +       st_gpa = (unsigned long)st_gva[i] | KVM_STEAL_PHYS_VALID;
> >> +       err = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &attr);
> >> +       TEST_ASSERT(err == 0, "Fail to set PV stealtime GPA");
> >> +}
> >> +
> >> +static void guest_code(int cpu)
> >> +{
> >> +       struct kvm_steal_time *st = st_gva[cpu];
> >> +       uint32_t version;
> >> +
> >> +       memset(st, 0, sizeof(*st));
> >> +       GUEST_SYNC(0);
> >> +
> >> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
> >> +       WRITE_ONCE(guest_stolen_time[cpu], st->steal);
> >> +       version = READ_ONCE(st->version);
> >> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
> >> +       GUEST_SYNC(1);
> >> +
> >> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
> >> +       GUEST_ASSERT(version < READ_ONCE(st->version));
> >> +       WRITE_ONCE(guest_stolen_time[cpu], st->steal);
> >> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
> >> +       GUEST_DONE();
> >> +}
> >> +
> >> +static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
> >> +{
> >> +       struct kvm_steal_time *st = addr_gva2hva(vm, (ulong)st_gva[vcpu_idx]);
> >> +
> >> +       ksft_print_msg("VCPU%d:\n", vcpu_idx);
> >> +       ksft_print_msg("    steal:     %lld\n", st->steal);
> >> +       ksft_print_msg("    version:   %d\n", st->version);
> >> +}
> >>   #endif
> >>
> >>   static void *do_steal_time(void *arg)
> >>
> >> base-commit: 8dfce8991b95d8625d0a1d2896e42f93b9d7f68d
> >> --
> >> 2.39.3
> >>
>
>
Re: [PATCH] KVM: LoongArch: selftests: Add steal time test case
Posted by Bibo Mao 6 days, 10 hours ago

On 2026/2/2 下午3:31, Huacai Chen wrote:
> On Mon, Feb 2, 2026 at 10:03 AM Bibo Mao <maobibo@loongson.cn> wrote:
>>
>> Hi Huacai,
>>
>> On 2026/1/31 下午9:47, Huacai Chen wrote:
>>> Since paravirt preempt is also applied, I applied this one with some
>>> modifications, you can check whether it is correct.
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git/commit/?h=loongarch-kvm&id=cf991b57ffc808d69cb1f911563b1d4658774ccf
>>
>> I checked the pendning patches in loongarch-kvm branch, they all look
>> good to me.
> OK, then are there any updates on this one?
> https://lore.kernel.org/loongarch/CAAhV-H57b14qY+5jqe+Fd5FTQq6jrhurfNBCqBqwG6SUpKFhTw@mail.gmail.com/T/#t
there is an update version and I am testing the patch.
Will post the patch soon.

Regards
Bibo Mao
> 
> Huacai
>>
>> Thanks for doing this.
>>
>> Regards
>> Bibo Mao
>>>
>>> Huacai
>>>
>>> On Thu, Jan 29, 2026 at 10:18 AM Bibo Mao <maobibo@loongson.cn> wrote:
>>>>
>>>> LoongArch KVM supports steal time accounting now, here add steal time
>>>> test case on LoongArch.
>>>>
>>>> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
>>>> ---
>>>>    tools/testing/selftests/kvm/Makefile.kvm |  1 +
>>>>    tools/testing/selftests/kvm/steal_time.c | 85 ++++++++++++++++++++++++
>>>>    2 files changed, 86 insertions(+)
>>>>
>>>> diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
>>>> index ba5c2b643efa..a18c00f1a4fa 100644
>>>> --- a/tools/testing/selftests/kvm/Makefile.kvm
>>>> +++ b/tools/testing/selftests/kvm/Makefile.kvm
>>>> @@ -228,6 +228,7 @@ TEST_GEN_PROGS_loongarch += kvm_page_table_test
>>>>    TEST_GEN_PROGS_loongarch += memslot_modification_stress_test
>>>>    TEST_GEN_PROGS_loongarch += memslot_perf_test
>>>>    TEST_GEN_PROGS_loongarch += set_memory_region_test
>>>> +TEST_GEN_PROGS_loongarch += steal_time
>>>>
>>>>    SPLIT_TESTS += arch_timer
>>>>    SPLIT_TESTS += get-reg-list
>>>> diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
>>>> index 8edc1fca345b..ee13e8973c45 100644
>>>> --- a/tools/testing/selftests/kvm/steal_time.c
>>>> +++ b/tools/testing/selftests/kvm/steal_time.c
>>>> @@ -301,6 +301,91 @@ static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
>>>>           pr_info("\n");
>>>>    }
>>>>
>>>> +#elif defined(__loongarch__)
>>>> +/* steal_time must have 64-byte alignment */
>>>> +#define STEAL_TIME_SIZE                ((sizeof(struct kvm_steal_time) + 63) & ~63)
>>>> +#define KVM_STEAL_PHYS_VALID   BIT_ULL(0)
>>>> +
>>>> +struct kvm_steal_time {
>>>> +       __u64 steal;
>>>> +       __u32 version;
>>>> +       __u32 flags;
>>>> +       __u32 pad[12];
>>>> +};
>>>> +
>>>> +static bool is_steal_time_supported(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +       int err;
>>>> +       uint64_t val;
>>>> +       struct kvm_device_attr attr = {
>>>> +               .group = KVM_LOONGARCH_VCPU_CPUCFG,
>>>> +               .attr = CPUCFG_KVM_FEATURE,
>>>> +               .addr = (uint64_t)&val,
>>>> +       };
>>>> +
>>>> +       err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
>>>> +       if (err)
>>>> +               return false;
>>>> +
>>>> +       err = __vcpu_ioctl(vcpu, KVM_GET_DEVICE_ATTR, &attr);
>>>> +       if (err)
>>>> +               return false;
>>>> +
>>>> +       return val & BIT(KVM_FEATURE_STEAL_TIME);
>>>> +}
>>>> +
>>>> +static void steal_time_init(struct kvm_vcpu *vcpu, uint32_t i)
>>>> +{
>>>> +       struct kvm_vm *vm = vcpu->vm;
>>>> +       uint64_t st_gpa;
>>>> +       int err;
>>>> +       struct kvm_device_attr attr = {
>>>> +               .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
>>>> +               .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
>>>> +               .addr = (uint64_t)&st_gpa,
>>>> +       };
>>>> +
>>>> +       /* 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]);
>>>> +
>>>> +       err = __vcpu_ioctl(vcpu, KVM_HAS_DEVICE_ATTR, &attr);
>>>> +       TEST_ASSERT(err == 0, "No PV stealtime Feature");
>>>> +
>>>> +       st_gpa = (unsigned long)st_gva[i] | KVM_STEAL_PHYS_VALID;
>>>> +       err = __vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &attr);
>>>> +       TEST_ASSERT(err == 0, "Fail to set PV stealtime GPA");
>>>> +}
>>>> +
>>>> +static void guest_code(int cpu)
>>>> +{
>>>> +       struct kvm_steal_time *st = st_gva[cpu];
>>>> +       uint32_t version;
>>>> +
>>>> +       memset(st, 0, sizeof(*st));
>>>> +       GUEST_SYNC(0);
>>>> +
>>>> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
>>>> +       WRITE_ONCE(guest_stolen_time[cpu], st->steal);
>>>> +       version = READ_ONCE(st->version);
>>>> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
>>>> +       GUEST_SYNC(1);
>>>> +
>>>> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
>>>> +       GUEST_ASSERT(version < READ_ONCE(st->version));
>>>> +       WRITE_ONCE(guest_stolen_time[cpu], st->steal);
>>>> +       GUEST_ASSERT(!(READ_ONCE(st->version) & 1));
>>>> +       GUEST_DONE();
>>>> +}
>>>> +
>>>> +static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx)
>>>> +{
>>>> +       struct kvm_steal_time *st = addr_gva2hva(vm, (ulong)st_gva[vcpu_idx]);
>>>> +
>>>> +       ksft_print_msg("VCPU%d:\n", vcpu_idx);
>>>> +       ksft_print_msg("    steal:     %lld\n", st->steal);
>>>> +       ksft_print_msg("    version:   %d\n", st->version);
>>>> +}
>>>>    #endif
>>>>
>>>>    static void *do_steal_time(void *arg)
>>>>
>>>> base-commit: 8dfce8991b95d8625d0a1d2896e42f93b9d7f68d
>>>> --
>>>> 2.39.3
>>>>
>>
>>