From patchwork Thu Oct 24 16:27:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 177583 Delivered-To: patch@linaro.org Received: by 2002:a92:409a:0:0:0:0:0 with SMTP id d26csp2479967ill; Thu, 24 Oct 2019 10:14:06 -0700 (PDT) X-Google-Smtp-Source: APXvYqxXe9u3ME2SiST1hYBhyI7k14E3U5QnH2WpPpCBLF0zsllRiFd0oju3KS7lkFibu7qGrfrV X-Received: by 2002:a50:e445:: with SMTP id e5mr44132453edm.257.1571937246085; Thu, 24 Oct 2019 10:14:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571937246; cv=none; d=google.com; s=arc-20160816; b=EMQ9peBofZ4CKijPkRrqAB/7qexb1Mex7AGIpT9lQWoyH7wy7ct1yWh6DiV82saKdF 4SVXs29Yk+p8tPK1SZOnWN6mMe8UzE5+BFcHngncMKhHk5LgyeO/DgPouCcbANnLgpuQ 9vS4SxvOFAcrnhIwAG4IjU9d3iZ4fDezn/dGW2lwMGNHe7UM/g9G1UxjbCqCnlrdBf/Z qtYQ1VNKzELXyg4SjnQ7h8Fcum9avCThs/trtCvE/6t82XHWflTINLRUb4TFUYlRTqDW NgZssOitKBjIS0Sf4ipoMYJl/MHhfuOhgqbnuqS8lrtxPH+8KWxTDvZqlgb1PjyOJOlU 7Kpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature; bh=hCsDjq3BTh1CFQ3xfAyc1h9/b/i1zEMVd9NMkBRbhe0=; b=xNgxkyoSi3Dr09GAWKzhwZ+wH+amtieajSIAA8etJhvEYDE/FNfLJrparWVATdnGHY 4CssgnuHEbMUyprxI7uLO9SYqwONR3aM8VM9vW/SVlLtk1XLVw2NXUKmmAnk9oxhaVRP EAIWM1zT2ylWuQK0uGxbPJUYdbvNHHbC60rNMQuRj71up1G98Sn8ANpQTgKLgER1h699 pQWZzDouzSHWcC0O/bZM/ek7fdfzK4y1p0W+yAcxsDCBd1YCCq2RZ6oJECAi0Vqb0LiC sYB8U/GrSBk/RicLkX7WB/q6fq1Pf3kSF/mN50Mv2qbfJmddb9RUHuTjAbLavA7N8xU9 qvUg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=urvci2Ek; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id h22si6726290edb.346.2019.10.24.10.14.05 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 24 Oct 2019 10:14:06 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=urvci2Ek; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:48432 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNggW-0000tY-G5 for patch@linaro.org; Thu, 24 Oct 2019 13:14:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58240) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNfyH-0008GL-U6 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 12:28:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNfyE-00011r-CZ for qemu-devel@nongnu.org; Thu, 24 Oct 2019 12:28:21 -0400 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]:35538) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iNfyE-00011K-5a for qemu-devel@nongnu.org; Thu, 24 Oct 2019 12:28:18 -0400 Received: by mail-wm1-x32d.google.com with SMTP id v6so3232377wmj.0 for ; Thu, 24 Oct 2019 09:28:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=hCsDjq3BTh1CFQ3xfAyc1h9/b/i1zEMVd9NMkBRbhe0=; b=urvci2Ek75Us14Ux8a0Fel60EcvAW/I50Da19obMkQH+Zyq+SjsIR0gIvOW4h7Voot veCLi53Dv/eKHn9z9tYExVcTF/eorhHeAsYNlZgjYpmATnA9CMIylrFooeAiiXzPfaa4 h4ridaGV6W6dTBac1tm+xVVx19K2AKi0iHlsrRKGWj7viQU/fWAegP9QPtYWT6draRDQ qV3Ppqvm9fu64vJ2q2ZVDst7NCLE+8We8Ld9D3tQHwF1c+Lab/Gq6ZWjWiKRszstjeHA Jry9ObaaXOa+CwWV36deWFLxteFYKb7ZoodGJmAjdwZ1KpQV5ZH5UU/BemdE5irOrnFS 2ADQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hCsDjq3BTh1CFQ3xfAyc1h9/b/i1zEMVd9NMkBRbhe0=; b=fO8aIFKBhmzzgMAfffsUvmw7oUgEjl1UPiXHGV9fGpcncWdfNJu5DuDzlLU4D4CwAx 7cohtLWF8GMFg0GVA7AZCAMidCCPSFrn93QYX8a62Y6o73LMj4D8akljYCPwR1MQ5cF+ e5QBvow+lK7cy/17o4UXquUlt6yvs92r6fT2YBa+NNUt7sAd/eSoIy3W2NnWqSshhpju ymEyahuvKAYlQoY4zeFGa0eGVrghCjxlj0H64F2hKyma9J75icfHQGGq4k0tKGxbBC4n tckb1hS6H6qMmDk45+0XarnZiQ3cwTP1Rq8u1sNcHWblfC0jQlDrhrdkNQWq0lVklkj5 mnGQ== X-Gm-Message-State: APjAAAV9AqeH46QggRFOfrQyJmLhMwtMpKTPqHtg+4vKbLWOnq21VxJm A7oEzSnhWwc0Xw5mBi87TqyzBVdYvTE= X-Received: by 2002:a1c:9d07:: with SMTP id g7mr5740556wme.53.1571934495721; Thu, 24 Oct 2019 09:28:15 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [81.2.115.148]) by smtp.gmail.com with ESMTPSA id r27sm42606124wrc.55.2019.10.24.09.28.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 09:28:15 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 39/51] target/arm/kvm64: Add kvm_arch_get/put_sve Date: Thu, 24 Oct 2019 17:27:12 +0100 Message-Id: <20191024162724.31675-40-peter.maydell@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191024162724.31675-1-peter.maydell@linaro.org> References: <20191024162724.31675-1-peter.maydell@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::32d X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Andrew Jones These are the SVE equivalents to kvm_arch_get/put_fpsimd. Note, the swabbing is different than it is for fpsmid because the vector format is a little-endian stream of words. Signed-off-by: Andrew Jones Reviewed-by: Richard Henderson Reviewed-by: Eric Auger Tested-by: Masayoshi Mizuma Message-id: 20191024121808.9612-6-drjones@redhat.com Signed-off-by: Peter Maydell --- target/arm/kvm64.c | 185 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 156 insertions(+), 29 deletions(-) -- 2.20.1 diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 28f6db57d5e..4c0b11d105a 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -671,11 +671,12 @@ int kvm_arch_destroy_vcpu(CPUState *cs) bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) { /* Return true if the regidx is a register we should synchronize - * via the cpreg_tuples array (ie is not a core reg we sync by - * hand in kvm_arch_get/put_registers()) + * via the cpreg_tuples array (ie is not a core or sve reg that + * we sync by hand in kvm_arch_get/put_registers()) */ switch (regidx & KVM_REG_ARM_COPROC_MASK) { case KVM_REG_ARM_CORE: + case KVM_REG_ARM64_SVE: return false; default: return true; @@ -721,10 +722,8 @@ int kvm_arm_cpreg_level(uint64_t regidx) static int kvm_arch_put_fpsimd(CPUState *cs) { - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; + CPUARMState *env = &ARM_CPU(cs)->env; struct kvm_one_reg reg; - uint32_t fpr; int i, ret; for (i = 0; i < 32; i++) { @@ -742,17 +741,73 @@ static int kvm_arch_put_fpsimd(CPUState *cs) } } - reg.addr = (uintptr_t)(&fpr); - fpr = vfp_get_fpsr(env); - reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr); - ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); - if (ret) { - return ret; + return 0; +} + +/* + * SVE registers are encoded in KVM's memory in an endianness-invariant format. + * The byte at offset i from the start of the in-memory representation contains + * the bits [(7 + 8 * i) : (8 * i)] of the register value. As this means the + * lowest offsets are stored in the lowest memory addresses, then that nearly + * matches QEMU's representation, which is to use an array of host-endian + * uint64_t's, where the lower offsets are at the lower indices. To complete + * the translation we just need to byte swap the uint64_t's on big-endian hosts. + */ +static uint64_t *sve_bswap64(uint64_t *dst, uint64_t *src, int nr) +{ +#ifdef HOST_WORDS_BIGENDIAN + int i; + + for (i = 0; i < nr; ++i) { + dst[i] = bswap64(src[i]); } - reg.addr = (uintptr_t)(&fpr); - fpr = vfp_get_fpcr(env); - reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr); + return dst; +#else + return src; +#endif +} + +/* + * KVM SVE registers come in slices where ZREGs have a slice size of 2048 bits + * and PREGS and the FFR have a slice size of 256 bits. However we simply hard + * code the slice index to zero for now as it's unlikely we'll need more than + * one slice for quite some time. + */ +static int kvm_arch_put_sve(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + uint64_t tmp[ARM_MAX_VQ * 2]; + uint64_t *r; + struct kvm_one_reg reg; + int n, ret; + + for (n = 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) { + r = sve_bswap64(tmp, &env->vfp.zregs[n].d[0], cpu->sve_max_vq * 2); + reg.addr = (uintptr_t)r; + reg.id = KVM_REG_ARM64_SVE_ZREG(n, 0); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + } + + for (n = 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) { + r = sve_bswap64(tmp, r = &env->vfp.pregs[n].p[0], + DIV_ROUND_UP(cpu->sve_max_vq * 2, 8)); + reg.addr = (uintptr_t)r; + reg.id = KVM_REG_ARM64_SVE_PREG(n, 0); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + } + + r = sve_bswap64(tmp, &env->vfp.pregs[FFR_PRED_NUM].p[0], + DIV_ROUND_UP(cpu->sve_max_vq * 2, 8)); + reg.addr = (uintptr_t)r; + reg.id = KVM_REG_ARM64_SVE_FFR(0); ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); if (ret) { return ret; @@ -765,6 +820,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) { struct kvm_one_reg reg; uint64_t val; + uint32_t fpr; int i, ret; unsigned int el; @@ -855,7 +911,27 @@ int kvm_arch_put_registers(CPUState *cs, int level) } } - ret = kvm_arch_put_fpsimd(cs); + if (cpu_isar_feature(aa64_sve, cpu)) { + ret = kvm_arch_put_sve(cs); + } else { + ret = kvm_arch_put_fpsimd(cs); + } + if (ret) { + return ret; + } + + reg.addr = (uintptr_t)(&fpr); + fpr = vfp_get_fpsr(env); + reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + + reg.addr = (uintptr_t)(&fpr); + fpr = vfp_get_fpcr(env); + reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); if (ret) { return ret; } @@ -878,10 +954,8 @@ int kvm_arch_put_registers(CPUState *cs, int level) static int kvm_arch_get_fpsimd(CPUState *cs) { - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; + CPUARMState *env = &ARM_CPU(cs)->env; struct kvm_one_reg reg; - uint32_t fpr; int i, ret; for (i = 0; i < 32; i++) { @@ -899,21 +973,53 @@ static int kvm_arch_get_fpsimd(CPUState *cs) } } - reg.addr = (uintptr_t)(&fpr); - reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr); - ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); - if (ret) { - return ret; - } - vfp_set_fpsr(env, fpr); + return 0; +} - reg.addr = (uintptr_t)(&fpr); - reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr); +/* + * KVM SVE registers come in slices where ZREGs have a slice size of 2048 bits + * and PREGS and the FFR have a slice size of 256 bits. However we simply hard + * code the slice index to zero for now as it's unlikely we'll need more than + * one slice for quite some time. + */ +static int kvm_arch_get_sve(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + struct kvm_one_reg reg; + uint64_t *r; + int n, ret; + + for (n = 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) { + r = &env->vfp.zregs[n].d[0]; + reg.addr = (uintptr_t)r; + reg.id = KVM_REG_ARM64_SVE_ZREG(n, 0); + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + sve_bswap64(r, r, cpu->sve_max_vq * 2); + } + + for (n = 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) { + r = &env->vfp.pregs[n].p[0]; + reg.addr = (uintptr_t)r; + reg.id = KVM_REG_ARM64_SVE_PREG(n, 0); + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + sve_bswap64(r, r, DIV_ROUND_UP(cpu->sve_max_vq * 2, 8)); + } + + r = &env->vfp.pregs[FFR_PRED_NUM].p[0]; + reg.addr = (uintptr_t)r; + reg.id = KVM_REG_ARM64_SVE_FFR(0); ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); if (ret) { return ret; } - vfp_set_fpcr(env, fpr); + sve_bswap64(r, r, DIV_ROUND_UP(cpu->sve_max_vq * 2, 8)); return 0; } @@ -923,6 +1029,7 @@ int kvm_arch_get_registers(CPUState *cs) struct kvm_one_reg reg; uint64_t val; unsigned int el; + uint32_t fpr; int i, ret; ARMCPU *cpu = ARM_CPU(cs); @@ -1012,11 +1119,31 @@ int kvm_arch_get_registers(CPUState *cs) env->spsr = env->banked_spsr[i]; } - ret = kvm_arch_get_fpsimd(cs); + if (cpu_isar_feature(aa64_sve, cpu)) { + ret = kvm_arch_get_sve(cs); + } else { + ret = kvm_arch_get_fpsimd(cs); + } if (ret) { return ret; } + reg.addr = (uintptr_t)(&fpr); + reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr); + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + vfp_set_fpsr(env, fpr); + + reg.addr = (uintptr_t)(&fpr); + reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr); + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + vfp_set_fpcr(env, fpr); + ret = kvm_get_vcpu_events(cpu); if (ret) { return ret;