From nobody Mon Apr 7 18:16:38 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1571937191; cv=none; d=zoho.com; s=zohoarc; b=gpRUL/4S44k/YL+SecIiLEIgg20ugFmsqhTCXhITICeuCQRg3d3f1hKCxE41UjN3VkfQupzeDPxg7rJy0NeUCR7zlA+n/rq6zIikEY41mxef523U3D0OvBD+zqAJrYuqG874yOfr3MIv64OG2mV9rIk57vUByFsc71LAl2+F0zc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571937191; h=Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=hCsDjq3BTh1CFQ3xfAyc1h9/b/i1zEMVd9NMkBRbhe0=; b=i8Vlk9pwMQxlr6hk36Iy0vWO+PafiHfQpeU0zB/aiuMvsiQvgUuqaSqJ8L525JshUuo8uRUuC35cRPxBkTjKcosO5/My7P2tjv7uqmK6j9JpjXVXOCt89/fHdBT0r/HWMhaBBVm9NeyX8cOoLKGZ56EXH7YfFHLmJ2rtJHcOk4Q= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571937191549195.99520303756685; Thu, 24 Oct 2019 10:13:11 -0700 (PDT) Received: from localhost ([::1]:48412 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNgfa-000676-Pc for importer@patchew.org; Thu, 24 Oct 2019 13:13:06 -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) 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) 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-Google-Smtp-Source: APXvYqxr6P3RJgLYPjEzexq3KGYytDLGSs/zDf/emXawPeFwJa9NIW6+0mTFJgHdD8scnH3iJRUS1A== X-Received: by 2002:a1c:9d07:: with SMTP id g7mr5740556wme.53.1571934495721; 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 Content-Transfer-Encoding: quoted-printable 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+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @linaro.org) Content-Type: text/plain; charset="utf-8" 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(-) 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) =20 static int kvm_arch_put_fpsimd(CPUState *cs) { - ARMCPU *cpu =3D ARM_CPU(cs); - CPUARMState *env =3D &cpu->env; + CPUARMState *env =3D &ARM_CPU(cs)->env; struct kvm_one_reg reg; - uint32_t fpr; int i, ret; =20 for (i =3D 0; i < 32; i++) { @@ -742,17 +741,73 @@ static int kvm_arch_put_fpsimd(CPUState *cs) } } =20 - reg.addr =3D (uintptr_t)(&fpr); - fpr =3D vfp_get_fpsr(env); - reg.id =3D AARCH64_SIMD_CTRL_REG(fp_regs.fpsr); - ret =3D 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 fo= rmat. + * The byte at offset i from the start of the in-memory representation con= tains + * the bits [(7 + 8 * i) : (8 * i)] of the register value. As this means t= he + * lowest offsets are stored in the lowest memory addresses, then that nea= rly + * 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 comple= te + * 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 =3D 0; i < nr; ++i) { + dst[i] =3D bswap64(src[i]); } =20 - reg.addr =3D (uintptr_t)(&fpr); - fpr =3D vfp_get_fpcr(env); - reg.id =3D 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 t= han + * one slice for quite some time. + */ +static int kvm_arch_put_sve(CPUState *cs) +{ + ARMCPU *cpu =3D ARM_CPU(cs); + CPUARMState *env =3D &cpu->env; + uint64_t tmp[ARM_MAX_VQ * 2]; + uint64_t *r; + struct kvm_one_reg reg; + int n, ret; + + for (n =3D 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) { + r =3D sve_bswap64(tmp, &env->vfp.zregs[n].d[0], cpu->sve_max_vq * = 2); + reg.addr =3D (uintptr_t)r; + reg.id =3D KVM_REG_ARM64_SVE_ZREG(n, 0); + ret =3D kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + } + + for (n =3D 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) { + r =3D sve_bswap64(tmp, r =3D &env->vfp.pregs[n].p[0], + DIV_ROUND_UP(cpu->sve_max_vq * 2, 8)); + reg.addr =3D (uintptr_t)r; + reg.id =3D KVM_REG_ARM64_SVE_PREG(n, 0); + ret =3D kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + } + + r =3D sve_bswap64(tmp, &env->vfp.pregs[FFR_PRED_NUM].p[0], + DIV_ROUND_UP(cpu->sve_max_vq * 2, 8)); + reg.addr =3D (uintptr_t)r; + reg.id =3D KVM_REG_ARM64_SVE_FFR(0); ret =3D 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; =20 @@ -855,7 +911,27 @@ int kvm_arch_put_registers(CPUState *cs, int level) } } =20 - ret =3D kvm_arch_put_fpsimd(cs); + if (cpu_isar_feature(aa64_sve, cpu)) { + ret =3D kvm_arch_put_sve(cs); + } else { + ret =3D kvm_arch_put_fpsimd(cs); + } + if (ret) { + return ret; + } + + reg.addr =3D (uintptr_t)(&fpr); + fpr =3D vfp_get_fpsr(env); + reg.id =3D AARCH64_SIMD_CTRL_REG(fp_regs.fpsr); + ret =3D kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + + reg.addr =3D (uintptr_t)(&fpr); + fpr =3D vfp_get_fpcr(env); + reg.id =3D AARCH64_SIMD_CTRL_REG(fp_regs.fpcr); + ret =3D 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) =20 static int kvm_arch_get_fpsimd(CPUState *cs) { - ARMCPU *cpu =3D ARM_CPU(cs); - CPUARMState *env =3D &cpu->env; + CPUARMState *env =3D &ARM_CPU(cs)->env; struct kvm_one_reg reg; - uint32_t fpr; int i, ret; =20 for (i =3D 0; i < 32; i++) { @@ -899,21 +973,53 @@ static int kvm_arch_get_fpsimd(CPUState *cs) } } =20 - reg.addr =3D (uintptr_t)(&fpr); - reg.id =3D AARCH64_SIMD_CTRL_REG(fp_regs.fpsr); - ret =3D kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); - if (ret) { - return ret; - } - vfp_set_fpsr(env, fpr); + return 0; +} =20 - reg.addr =3D (uintptr_t)(&fpr); - reg.id =3D 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 t= han + * one slice for quite some time. + */ +static int kvm_arch_get_sve(CPUState *cs) +{ + ARMCPU *cpu =3D ARM_CPU(cs); + CPUARMState *env =3D &cpu->env; + struct kvm_one_reg reg; + uint64_t *r; + int n, ret; + + for (n =3D 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) { + r =3D &env->vfp.zregs[n].d[0]; + reg.addr =3D (uintptr_t)r; + reg.id =3D KVM_REG_ARM64_SVE_ZREG(n, 0); + ret =3D kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + sve_bswap64(r, r, cpu->sve_max_vq * 2); + } + + for (n =3D 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) { + r =3D &env->vfp.pregs[n].p[0]; + reg.addr =3D (uintptr_t)r; + reg.id =3D KVM_REG_ARM64_SVE_PREG(n, 0); + ret =3D 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 =3D &env->vfp.pregs[FFR_PRED_NUM].p[0]; + reg.addr =3D (uintptr_t)r; + reg.id =3D KVM_REG_ARM64_SVE_FFR(0); ret =3D 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)); =20 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; =20 ARMCPU *cpu =3D ARM_CPU(cs); @@ -1012,11 +1119,31 @@ int kvm_arch_get_registers(CPUState *cs) env->spsr =3D env->banked_spsr[i]; } =20 - ret =3D kvm_arch_get_fpsimd(cs); + if (cpu_isar_feature(aa64_sve, cpu)) { + ret =3D kvm_arch_get_sve(cs); + } else { + ret =3D kvm_arch_get_fpsimd(cs); + } if (ret) { return ret; } =20 + reg.addr =3D (uintptr_t)(&fpr); + reg.id =3D AARCH64_SIMD_CTRL_REG(fp_regs.fpsr); + ret =3D kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + vfp_set_fpsr(env, fpr); + + reg.addr =3D (uintptr_t)(&fpr); + reg.id =3D AARCH64_SIMD_CTRL_REG(fp_regs.fpcr); + ret =3D kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + vfp_set_fpcr(env, fpr); + ret =3D kvm_get_vcpu_events(cpu); if (ret) { return ret; --=20 2.20.1