This patch prints out some information about the SVE configuration when --show-reg=list is passed. This is development hack only (as well as being an abuse of the purpose of that option). Signed-off-by: Dave Martin <Dave.Martin@xxxxxxx> --- arm/kvm-cpu.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c index 38a071b..80e7b79 100644 --- a/arm/kvm-cpu.c +++ b/arm/kvm-cpu.c @@ -1,3 +1,4 @@ +#include <assert.h> #include <errno.h> #include <stddef.h> #include <stdio.h> @@ -48,6 +49,112 @@ error: return ret; } +static int kvm_show_sve_info(struct kvm_cpu const *vcpu) +{ + int ret = 0; + u64 val; + struct kvm_one_reg r; + int have_sve; + u64 vls[9]; + unsigned int i; + + r.addr = (u64)&val; + + r.id = ARM64_SYS_REG(3, 0, 0, 4, 0); /* ID_AA64PFR0_EL1 */ + assert((r.id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64); + if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &r)) { + perror("KVM_GET_ONE_REG(ID_AA64PFR0_EL1)"); + goto error; + } + + printf("ID_AA64PFR0_EL1:\t0x%lx\n", (unsigned long)val); + + have_sve = !!((val >> 32) & 0xf); + + r.id = ARM64_SYS_REG(3, 0, 0, 4, 4); + if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &r)) { + if (errno != ENOENT || have_sve) { + perror("KVM_GET_ONE_REG(ID_AA64ZFR0_EL1)"); + ret = -1; + } + } else { + if (!have_sve) { + puts("ID_AA64ZFR0_EL1 unexpectedly present"); + ret = -1; + } + + printf("ID_AA64ZFR0_EL1:\t0x%lx\n", (unsigned long)val); + } + + r.id = ARM64_SYS_REG(3, 0, 1, 2, 0); + if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &r)) { + if (errno != ENOENT || have_sve) { + perror("KVM_GET_ONE_REG(ZCR_EL1)"); + ret = -1; + } + } else { + if (!have_sve) { + puts("ZCR_EL1 unexpectedly present"); + ret = -1; + } + + printf("ZCR_EL1:\t0x%lx\n", (unsigned long)val); + } + + r.addr = (u64)&vls; + r.id = KVM_REG_ARM64_SVE_VLS; + assert(8 * (sizeof(vls) - sizeof(*vls)) == 512 && + (r.id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U512); + + /* + * Write some canary data so we can see that the kernel writes + * the expected amount: + */ + for (i = 0; i < sizeof(vls) / sizeof(*vls); ++i) + vls[i] = -7; + + if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &r)) { + if (errno != ENOENT || have_sve) { + perror("KVM_GET_ONE_REG(KVM_REG_ARM64_SVE_VLS)"); + ret = -1; + } + } else { + char const *prefix = ""; + + if (!have_sve) { + puts("KVM_REG_ARM64_SVE_VLS unexpectedly present"); + ret = -1; + } + + if (vls[7] == (u64)-7) { + puts("KVM_REG_ARM64_SVE_VLS short read?"); + ret = -1; + } + + if (vls[8] != (u64)-7) { + puts("KVM_REG_ARM64_SVE_VLS overrun?"); + ret = -1; + } + + fputs("SVE VQs: ", stdout); + + for (i = 0; i < 512; ++i) + if ((vls[i / 64] >> (i % 64)) & 1) { + printf("%s%lu", prefix, (unsigned long)i + 1); + prefix = ","; + } + + putchar('\n'); + } + + fflush(stdout); + + return ret; + +error: + return -1; +} + static int debug_fd; void kvm_cpu__set_debug_fd(int fd) @@ -156,8 +263,10 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id) if (err || target->init(vcpu)) die("Unable to initialise vcpu"); - if (kvm->cfg.arch.show_reg_list) + if (kvm->cfg.arch.show_reg_list) { + kvm_show_sve_info(vcpu); kvm_show_reg_list(vcpu); + } coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO); -- 2.1.4 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm