Hi Dave,

The below looks like a nice kvm selftest. Care to fit it into that
framework (tools/testing/selftests/kvm/) and post it?

Thanks,
drew

> [1]
> 
> #include <assert.h>
> #include <errno.h>
> #include <limits.h>
> #include <stddef.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <stdint.h>
> #include <string.h>
> #include <fcntl.h>
> #include <sys/ioctl.h>
> #include <linux/kvm.h>
> 
> #define KVM_PATH "/dev/kvm"
> 
> #define ARRAY_SIZE(array) (sizeof (array) / sizeof *(array))
> 
> static int get_reg_list(int vcpu, struct kvm_reg_list **pregs, size_t *psize)
> {
>       struct kvm_reg_list *regs = *pregs;
>       size_t num_needed = 0;
>       const size_t reg_offset = (char *)&regs->reg - (char *)regs;
> 
>       while (1) {
>               size_t size_needed = num_needed * sizeof regs->reg[0]
>                                       + reg_offset;
>               if (size_needed > *psize) {
>                       regs = realloc(regs, size_needed);
>                       if (!regs)
>                               goto nomem;
> 
>                       *pregs = regs;
>                       *psize = size_needed;
>               }
> 
>               regs->n = (*psize - reg_offset) / sizeof regs->reg[0];
>               if (!ioctl(vcpu, KVM_GET_REG_LIST, regs))
>                       break;
> 
>               if (errno != E2BIG) {
>                       perror("KVM_GET_REG_LIST");
>                       goto error;
>               }
> 
>               num_needed = regs->n;
>       }
> 
>       return 0;       
> 
> nomem:
>       errno = ENOMEM;
>       perror(NULL);
> error:
>       return -1;
> }
> 
> int main(void)
> {
>       int fail = 0;
>       int kvm_fd, vm, vcpu;
>       struct kvm_vcpu_init init;
>       size_t i;
>       struct kvm_reg_list *regs = NULL;
>       size_t regs_size = 0;
>       uint64_t regdata[2];
>       struct kvm_one_reg reg;
> 
>       kvm_fd = open(KVM_PATH, O_RDWR);
>       if (kvm_fd == -1) {
>               perror(KVM_PATH);
>               goto error;
>       }
> 
>       vm = ioctl(kvm_fd, KVM_CREATE_VM, 0);
>       if (vm == -1) {
>               perror("KVM_CREATE_VM");
>               goto error;
>       }
> 
>       if (ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init)) {
>               perror("KVM_ARM_PREFERRED_TARGET");
>               goto error;
>       }
> 
>       printf("KVM_ARM_PREFERRED_TARGET:\n"
>              "\ttarget = %lu\n",
>              (unsigned long)init.target);
>       for (i = 0; i < ARRAY_SIZE(init.features); ++i)
>               printf("\tfeatures[0] = 0x%.8lx\n",
>                      (unsigned long)init.features[i]);
>       
>       vcpu = ioctl(vm, KVM_CREATE_VCPU, 0);
>       if (vcpu == -1) {
>               perror("KVM_CREATE_VCPU");
>               goto error;
>       }
> 
>       if (!get_reg_list(vcpu, &regs, &regs_size)) {
>               fputs("Strange, KVM_GET_REG_LIST succeeded before 
> KVM_VCPU_INIT!\n",
>                     stderr);
>                       
>               goto error;
>       }
> 
>       if (ioctl(vcpu, KVM_ARM_VCPU_INIT, &init)) {
>               perror("KVM_ARM_VCPU_INIT");
>               goto error;
>       }
> 
>       if (get_reg_list(vcpu, &regs, &regs_size))
>               goto error;
> 
>       assert(1 <= -1ULL >> 32);
>       assert(ULONG_MAX >= (1ULL << 32) - 1);
>       for (i = 0; i < regs->n; ++i) {
>               size_t size;
>               char const *s1 = "OK", *s2 = "", *s3 = "";;
> 
>               size = (size_t)1 << ((regs->reg[i] & KVM_REG_SIZE_MASK) >>
>                                    KVM_REG_SIZE_SHIFT);
>               if (size < 4 || size > 16) {
>                       s1 = "BADSIZE";
>                       fail = 1;
>               } else {
>                       memset(&reg, 0, sizeof reg);
> 
>                       reg.id = regs->reg[i];
>                       reg.addr = (__u64)&regdata;
>                       if (ioctl(vcpu, KVM_GET_ONE_REG, &reg)) {
>                               s1 = "FAIL (";
>                               s2 = strerror(errno);
>                               s3 = ")";
>                               fail = 1;
>                       }
>               }
> 
>               printf("\t0x%.16lx\t%s%s%s\n",
>                      (unsigned long)reg.id, s1, s2, s3);
>       
>       }
> 
>       if (ferror(stdout) || fflush(stdout))
>               goto stdout_error;
>       
>       if (fail) {
>               puts("FAIL");
>               goto error;
>       }
> 
>       if (puts("\nPASS") == EOF || fclose(stdout))
>               goto stdout_error;
> 
>       return EXIT_SUCCESS;
> 
> stdout_error:
>       fputs("I/O error", stderr);
> error:
>       return EXIT_FAILURE;
> }
> _______________________________________________
> kvmarm mailing list
> [email protected]
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to