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

RISC-V: KVM: selftests: Add steal_time test support

With the introduction of steal-time accounting support for
RISC-V KVM we can add RISC-V support to the steal_time test.

Reviewed-by: Anup Patel <anup@brainfault.org>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Anup Patel <anup@brainfault.org>

authored by

Andrew Jones and committed by
Anup Patel
60b6e31c 945d880d

+103 -2
+3 -2
tools/testing/selftests/kvm/Makefile
··· 184 184 185 185 TEST_GEN_PROGS_riscv += demand_paging_test 186 186 TEST_GEN_PROGS_riscv += dirty_log_test 187 - TEST_GEN_PROGS_riscv += guest_print_test 188 187 TEST_GEN_PROGS_riscv += get-reg-list 188 + TEST_GEN_PROGS_riscv += guest_print_test 189 + TEST_GEN_PROGS_riscv += kvm_binary_stats_test 189 190 TEST_GEN_PROGS_riscv += kvm_create_max_vcpus 190 191 TEST_GEN_PROGS_riscv += kvm_page_table_test 191 192 TEST_GEN_PROGS_riscv += set_memory_region_test 192 - TEST_GEN_PROGS_riscv += kvm_binary_stats_test 193 + TEST_GEN_PROGS_riscv += steal_time 193 194 194 195 SPLIT_TESTS += get-reg-list 195 196
+1
tools/testing/selftests/kvm/include/riscv/processor.h
··· 128 128 129 129 enum sbi_ext_id { 130 130 SBI_EXT_BASE = 0x10, 131 + SBI_EXT_STA = 0x535441, 131 132 }; 132 133 133 134 enum sbi_ext_base_fid {
+99
tools/testing/selftests/kvm/steal_time.c
··· 11 11 #include <pthread.h> 12 12 #include <linux/kernel.h> 13 13 #include <asm/kvm.h> 14 + #ifndef __riscv 14 15 #include <asm/kvm_para.h> 16 + #endif 15 17 16 18 #include "test_util.h" 17 19 #include "kvm_util.h" ··· 203 201 pr_info(" rev: %d\n", st->rev); 204 202 pr_info(" attr: %d\n", st->attr); 205 203 pr_info(" st_time: %ld\n", st->st_time); 204 + } 205 + 206 + #elif defined(__riscv) 207 + 208 + /* SBI STA shmem must have 64-byte alignment */ 209 + #define STEAL_TIME_SIZE ((sizeof(struct sta_struct) + 63) & ~63) 210 + 211 + static vm_paddr_t st_gpa[NR_VCPUS]; 212 + 213 + struct sta_struct { 214 + uint32_t sequence; 215 + uint32_t flags; 216 + uint64_t steal; 217 + uint8_t preempted; 218 + uint8_t pad[47]; 219 + } __packed; 220 + 221 + static void sta_set_shmem(vm_paddr_t gpa, unsigned long flags) 222 + { 223 + unsigned long lo = (unsigned long)gpa; 224 + #if __riscv_xlen == 32 225 + unsigned long hi = (unsigned long)(gpa >> 32); 226 + #else 227 + unsigned long hi = gpa == -1 ? -1 : 0; 228 + #endif 229 + struct sbiret ret = sbi_ecall(SBI_EXT_STA, 0, lo, hi, flags, 0, 0, 0); 230 + 231 + GUEST_ASSERT(ret.value == 0 && ret.error == 0); 232 + } 233 + 234 + static void check_status(struct sta_struct *st) 235 + { 236 + GUEST_ASSERT(!(READ_ONCE(st->sequence) & 1)); 237 + GUEST_ASSERT(READ_ONCE(st->flags) == 0); 238 + GUEST_ASSERT(READ_ONCE(st->preempted) == 0); 239 + } 240 + 241 + static void guest_code(int cpu) 242 + { 243 + struct sta_struct *st = st_gva[cpu]; 244 + uint32_t sequence; 245 + long out_val = 0; 246 + bool probe; 247 + 248 + probe = guest_sbi_probe_extension(SBI_EXT_STA, &out_val); 249 + GUEST_ASSERT(probe && out_val == 1); 250 + 251 + sta_set_shmem(st_gpa[cpu], 0); 252 + GUEST_SYNC(0); 253 + 254 + check_status(st); 255 + WRITE_ONCE(guest_stolen_time[cpu], st->steal); 256 + sequence = READ_ONCE(st->sequence); 257 + check_status(st); 258 + GUEST_SYNC(1); 259 + 260 + check_status(st); 261 + GUEST_ASSERT(sequence < READ_ONCE(st->sequence)); 262 + WRITE_ONCE(guest_stolen_time[cpu], st->steal); 263 + check_status(st); 264 + GUEST_DONE(); 265 + } 266 + 267 + static bool is_steal_time_supported(struct kvm_vcpu *vcpu) 268 + { 269 + uint64_t id = RISCV_SBI_EXT_REG(KVM_RISCV_SBI_EXT_STA); 270 + unsigned long enabled; 271 + 272 + vcpu_get_reg(vcpu, id, &enabled); 273 + TEST_ASSERT(enabled == 0 || enabled == 1, "Expected boolean result"); 274 + 275 + return enabled; 276 + } 277 + 278 + static void steal_time_init(struct kvm_vcpu *vcpu, uint32_t i) 279 + { 280 + /* ST_GPA_BASE is identity mapped */ 281 + st_gva[i] = (void *)(ST_GPA_BASE + i * STEAL_TIME_SIZE); 282 + st_gpa[i] = addr_gva2gpa(vcpu->vm, (vm_vaddr_t)st_gva[i]); 283 + sync_global_to_guest(vcpu->vm, st_gva[i]); 284 + sync_global_to_guest(vcpu->vm, st_gpa[i]); 285 + } 286 + 287 + static void steal_time_dump(struct kvm_vm *vm, uint32_t vcpu_idx) 288 + { 289 + struct sta_struct *st = addr_gva2hva(vm, (ulong)st_gva[vcpu_idx]); 290 + int i; 291 + 292 + pr_info("VCPU%d:\n", vcpu_idx); 293 + pr_info(" sequence: %d\n", st->sequence); 294 + pr_info(" flags: %d\n", st->flags); 295 + pr_info(" steal: %"PRIu64"\n", st->steal); 296 + pr_info(" preempted: %d\n", st->preempted); 297 + pr_info(" pad: "); 298 + for (i = 0; i < 47; ++i) 299 + pr_info("%d", st->pad[i]); 300 + pr_info("\n"); 206 301 } 207 302 208 303 #endif