Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/742446/?format=api
{ "id": 742446, "url": "http://patchwork.ozlabs.org/api/1.2/patches/742446/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/1490243163-19566-3-git-send-email-paulus@ozlabs.org/", "project": { "id": 2, "url": "http://patchwork.ozlabs.org/api/1.2/projects/2/?format=api", "name": "Linux PPC development", "link_name": "linuxppc-dev", "list_id": "linuxppc-dev.lists.ozlabs.org", "list_email": "linuxppc-dev@lists.ozlabs.org", "web_url": "https://github.com/linuxppc/wiki/wiki", "scm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git", "webscm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/", "list_archive_url": "https://lore.kernel.org/linuxppc-dev/", "list_archive_url_format": "https://lore.kernel.org/linuxppc-dev/{}/", "commit_url_format": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?id={}" }, "msgid": "<1490243163-19566-3-git-send-email-paulus@ozlabs.org>", "list_archive_url": "https://lore.kernel.org/linuxppc-dev/1490243163-19566-3-git-send-email-paulus@ozlabs.org/", "date": "2017-03-23T04:26:00", "name": "[2/5] KVM: PPC: Book3S: Add MMIO emulation for FP and VSX instructions", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "59777f65f397e2860c1aa30d7c0944dcf6b44b0d", "submitter": { "id": 67079, "url": "http://patchwork.ozlabs.org/api/1.2/people/67079/?format=api", "name": "Paul Mackerras", "email": "paulus@ozlabs.org" }, "delegate": { "id": 13, "url": "http://patchwork.ozlabs.org/api/1.2/users/13/?format=api", "username": "paulus", "first_name": "Paul", "last_name": "Mackerras", "email": "paulus@samba.org" }, "mbox": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/1490243163-19566-3-git-send-email-paulus@ozlabs.org/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/742446/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/742446/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org>", "X-Original-To": [ "patchwork-incoming@ozlabs.org", "linuxppc-dev@lists.ozlabs.org" ], "Delivered-To": [ "patchwork-incoming@ozlabs.org", "linuxppc-dev@lists.ozlabs.org", "linuxppc-dev@ozlabs.org" ], "Received": [ "from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3vpYWr5SX2z9s7f\n\tfor <patchwork-incoming@ozlabs.org>;\n\tThu, 23 Mar 2017 15:30:48 +1100 (AEDT)", "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3vpYWr4dWnzDqqV\n\tfor <patchwork-incoming@ozlabs.org>;\n\tThu, 23 Mar 2017 15:30:48 +1100 (AEDT)", "from ozlabs.org (ozlabs.org [IPv6:2401:3900:2:1::2])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3vpYQZ3YShzDq93\n\tfor <linuxppc-dev@lists.ozlabs.org>;\n\tThu, 23 Mar 2017 15:26:14 +1100 (AEDT)", "by ozlabs.org (Postfix)\n\tid 3vpYQZ2dYcz9s88; Thu, 23 Mar 2017 15:26:14 +1100 (AEDT)", "from authenticated.ozlabs.org (localhost [127.0.0.1])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPSA id 3vpYQZ1ymRz9s85;\n\tThu, 23 Mar 2017 15:26:14 +1100 (AEDT)" ], "From": "Paul Mackerras <paulus@ozlabs.org>", "To": "kvm@vger.kernel.org,\n\tlinuxppc-dev@ozlabs.org,\n\tkvm-ppc@vger.kernel.org", "Subject": "[PATCH 2/5] KVM: PPC: Book3S: Add MMIO emulation for FP and VSX\n\tinstructions", "Date": "Thu, 23 Mar 2017 15:26:00 +1100", "Message-Id": "<1490243163-19566-3-git-send-email-paulus@ozlabs.org>", "X-Mailer": "git-send-email 2.7.4", "In-Reply-To": "<1490243163-19566-1-git-send-email-paulus@ozlabs.org>", "References": "<1490243163-19566-1-git-send-email-paulus@ozlabs.org>", "X-BeenThere": "linuxppc-dev@lists.ozlabs.org", "X-Mailman-Version": "2.1.23", "Precedence": "list", "List-Id": "Linux on PowerPC Developers Mail List\n\t<linuxppc-dev.lists.ozlabs.org>", "List-Unsubscribe": "<https://lists.ozlabs.org/options/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe>", "List-Archive": "<http://lists.ozlabs.org/pipermail/linuxppc-dev/>", "List-Post": "<mailto:linuxppc-dev@lists.ozlabs.org>", "List-Help": "<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help>", "List-Subscribe": "<https://lists.ozlabs.org/listinfo/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe>", "Errors-To": "linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org", "Sender": "\"Linuxppc-dev\"\n\t<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org>" }, "content": "From: Bin Lu <lblulb@linux.vnet.ibm.com>\n\nThis patch provides the MMIO load/store emulation for instructions\nof 'double & vector unsigned char & vector signed char & vector\nunsigned short & vector signed short & vector unsigned int & vector\nsigned int & vector double '.\n\nThe instructions that this adds emulation for are:\n\n- ldx, ldux, lwax,\n- lfs, lfsx, lfsu, lfsux, lfd, lfdx, lfdu, lfdux,\n- stfs, stfsx, stfsu, stfsux, stfd, stfdx, stfdu, stfdux, stfiwx,\n- lxsdx, lxsspx, lxsiwax, lxsiwzx, lxvd2x, lxvw4x, lxvdsx,\n- stxsdx, stxsspx, stxsiwx, stxvd2x, stxvw4x\n\n[paulus@ozlabs.org - some cleanups, fixes and rework, make it\n compile for Book E]\n\nSigned-off-by: Bin Lu <lblulb@linux.vnet.ibm.com>\nSigned-off-by: Paul Mackerras <paulus@ozlabs.org>\n---\n arch/powerpc/include/asm/disassemble.h | 5 +\n arch/powerpc/include/asm/kvm_host.h | 23 +++\n arch/powerpc/include/asm/kvm_ppc.h | 7 +\n arch/powerpc/include/asm/ppc-opcode.h | 50 +++++\n arch/powerpc/kvm/Makefile | 2 +-\n arch/powerpc/kvm/emulate_loadstore.c | 335 ++++++++++++++++++++++++++++++++-\n arch/powerpc/kvm/powerpc.c | 317 ++++++++++++++++++++++++++++++-\n 7 files changed, 731 insertions(+), 8 deletions(-)", "diff": "diff --git a/arch/powerpc/include/asm/disassemble.h b/arch/powerpc/include/asm/disassemble.h\nindex 4852e84..c0a5505 100644\n--- a/arch/powerpc/include/asm/disassemble.h\n+++ b/arch/powerpc/include/asm/disassemble.h\n@@ -87,6 +87,11 @@ static inline unsigned int get_oc(u32 inst)\n \treturn (inst >> 11) & 0x7fff;\n }\n \n+static inline unsigned int get_tx_or_sx(u32 inst)\n+{\n+\treturn (inst) & 0x1;\n+}\n+\n #define IS_XFORM(inst)\t(get_op(inst) == 31)\n #define IS_DSFORM(inst)\t(get_op(inst) >= 56)\n \ndiff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h\nindex 7bba8f4..201438b 100644\n--- a/arch/powerpc/include/asm/kvm_host.h\n+++ b/arch/powerpc/include/asm/kvm_host.h\n@@ -441,6 +441,11 @@ struct mmio_hpte_cache {\n \tunsigned int index;\n };\n \n+#define KVMPPC_VSX_COPY_NONE\t\t0\n+#define KVMPPC_VSX_COPY_WORD\t\t1\n+#define KVMPPC_VSX_COPY_DWORD\t\t2\n+#define KVMPPC_VSX_COPY_DWORD_LOAD_DUMP\t3\n+\n struct openpic;\n \n struct kvm_vcpu_arch {\n@@ -644,6 +649,21 @@ struct kvm_vcpu_arch {\n \tu8 io_gpr; /* GPR used as IO source/target */\n \tu8 mmio_host_swabbed;\n \tu8 mmio_sign_extend;\n+\t/* conversion between single and double precision */\n+\tu8 mmio_sp64_extend;\n+\t/*\n+\t * Number of simulations for vsx.\n+\t * If we use 2*8bytes to simulate 1*16bytes,\n+\t * then the number should be 2 and\n+\t * mmio_vsx_copy_type=KVMPPC_VSX_COPY_DWORD.\n+\t * If we use 4*4bytes to simulate 1*16bytes,\n+\t * the number should be 4 and\n+\t * mmio_vsx_copy_type=KVMPPC_VSX_COPY_WORD.\n+\t */\n+\tu8 mmio_vsx_copy_nums;\n+\tu8 mmio_vsx_offset;\n+\tu8 mmio_vsx_copy_type;\n+\tu8 mmio_vsx_tx_sx_enabled;\n \tu8 osi_needed;\n \tu8 osi_enabled;\n \tu8 papr_enabled;\n@@ -732,6 +752,8 @@ struct kvm_vcpu_arch {\n };\n \n #define VCPU_FPR(vcpu, i)\t(vcpu)->arch.fp.fpr[i][TS_FPROFFSET]\n+#define VCPU_VSX_FPR(vcpu, i, j)\t((vcpu)->arch.fp.fpr[i][j])\n+#define VCPU_VSX_VR(vcpu, i)\t\t((vcpu)->arch.vr.vr[i])\n \n /* Values for vcpu->arch.state */\n #define KVMPPC_VCPU_NOTREADY\t\t0\n@@ -745,6 +767,7 @@ struct kvm_vcpu_arch {\n #define KVM_MMIO_REG_FPR\t0x0020\n #define KVM_MMIO_REG_QPR\t0x0040\n #define KVM_MMIO_REG_FQPR\t0x0060\n+#define KVM_MMIO_REG_VSX\t0x0080\n \n #define __KVM_HAVE_ARCH_WQP\n #define __KVM_HAVE_CREATE_DEVICE\ndiff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h\nindex 4f1f22f..bbecec4 100644\n--- a/arch/powerpc/include/asm/kvm_ppc.h\n+++ b/arch/powerpc/include/asm/kvm_ppc.h\n@@ -78,9 +78,15 @@ extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,\n extern int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,\n unsigned int rt, unsigned int bytes,\n \t\t\t int is_default_endian);\n+extern int kvmppc_handle_vsx_load(struct kvm_run *run, struct kvm_vcpu *vcpu,\n+\t\t\t\tunsigned int rt, unsigned int bytes,\n+\t\t\tint is_default_endian, int mmio_sign_extend);\n extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,\n \t\t\t u64 val, unsigned int bytes,\n \t\t\t int is_default_endian);\n+extern int kvmppc_handle_vsx_store(struct kvm_run *run, struct kvm_vcpu *vcpu,\n+\t\t\t\tint rs, unsigned int bytes,\n+\t\t\t\tint is_default_endian);\n \n extern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,\n \t\t\t\t enum instruction_type type, u32 *inst);\n@@ -243,6 +249,7 @@ union kvmppc_one_reg {\n \tu64\tdval;\n \tvector128 vval;\n \tu64\tvsxval[2];\n+\tu32\tvsx32val[4];\n \tstruct {\n \t\tu64\taddr;\n \t\tu64\tlength;\ndiff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h\nindex e7d6d86..1e37c3c 100644\n--- a/arch/powerpc/include/asm/ppc-opcode.h\n+++ b/arch/powerpc/include/asm/ppc-opcode.h\n@@ -86,7 +86,9 @@\n #define OP_TRAP_64 2\n \n #define OP_31_XOP_TRAP 4\n+#define OP_31_XOP_LDX 21\n #define OP_31_XOP_LWZX 23\n+#define OP_31_XOP_LDUX 53\n #define OP_31_XOP_DCBST 54\n #define OP_31_XOP_LWZUX 55\n #define OP_31_XOP_TRAP_64 68\n@@ -99,6 +101,7 @@\n #define OP_31_XOP_LHZX 279\n #define OP_31_XOP_LHZUX 311\n #define OP_31_XOP_MFSPR 339\n+#define OP_31_XOP_LWAX 341\n #define OP_31_XOP_LHAX 343\n #define OP_31_XOP_LHAUX 375\n #define OP_31_XOP_STHX 407\n@@ -108,10 +111,46 @@\n #define OP_31_XOP_LWBRX 534\n #define OP_31_XOP_TLBSYNC 566\n #define OP_31_XOP_STWBRX 662\n+#define OP_31_XOP_STFSX\t 663\n+#define OP_31_XOP_STFSUX 695\n+#define OP_31_XOP_STFDX 727\n+#define OP_31_XOP_STFDUX 759\n #define OP_31_XOP_LHBRX 790\n #define OP_31_XOP_STHBRX 918\n+#define OP_31_XOP_STFIWX 983\n+\n+/* VSX Scalar Load Instructions */\n+#define OP_31_XOP_LXSDX 588\n+#define OP_31_XOP_LXSSPX 524\n+#define OP_31_XOP_LXSIWAX 76\n+#define OP_31_XOP_LXSIWZX 12\n+\n+/* VSX Scalar Store Instructions */\n+#define OP_31_XOP_STXSDX 716\n+#define OP_31_XOP_STXSSPX 652\n+#define OP_31_XOP_STXSIWX 140\n+\n+/* VSX Vector Load Instructions */\n+#define OP_31_XOP_LXVD2X 844\n+#define OP_31_XOP_LXVW4X 780\n+\n+/* VSX Vector Load and Splat Instruction */\n+#define OP_31_XOP_LXVDSX 332\n+\n+/* VSX Vector Store Instructions */\n+#define OP_31_XOP_STXVD2X 972\n+#define OP_31_XOP_STXVW4X 908\n+\n+#define OP_31_XOP_LFSX 535\n+#define OP_31_XOP_LFSUX 567\n+#define OP_31_XOP_LFDX 599\n+#define OP_31_XOP_LFDUX\t\t631\n \n #define OP_LWZ 32\n+#define OP_STFS 52\n+#define OP_STFSU 53\n+#define OP_STFD 54\n+#define OP_STFDU 55\n #define OP_LD 58\n #define OP_LWZU 33\n #define OP_LBZ 34\n@@ -127,6 +166,17 @@\n #define OP_LHAU 43\n #define OP_STH 44\n #define OP_STHU 45\n+#define OP_LMW 46\n+#define OP_STMW 47\n+#define OP_LFS 48\n+#define OP_LFSU 49\n+#define OP_LFD 50\n+#define OP_LFDU 51\n+#define OP_STFS 52\n+#define OP_STFSU 53\n+#define OP_STFD 54\n+#define OP_STFDU 55\n+#define OP_LQ 56\n \n /* sorted alphabetically */\n #define PPC_INST_BHRBE\t\t\t0x7c00025c\ndiff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile\nindex b87ccde..23dcb18 100644\n--- a/arch/powerpc/kvm/Makefile\n+++ b/arch/powerpc/kvm/Makefile\n@@ -17,6 +17,7 @@ CFLAGS_emulate.o := -I.\n CFLAGS_emulate_loadstore.o := -I.\n \n common-objs-y += powerpc.o emulate_loadstore.o\n+common-objs-$(CONFIG_PPC_FPU) += fpu.o\n obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o\n obj-$(CONFIG_KVM_BOOK3S_HANDLER) += book3s_exports.o\n \n@@ -101,7 +102,6 @@ kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs)\n kvm-book3s_32-objs := \\\n \t$(common-objs-y) \\\n \temulate.o \\\n-\tfpu.o \\\n \tbook3s_paired_singles.o \\\n \tbook3s.o \\\n \tbook3s_pr.o \\\ndiff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c\nindex 6d3c0ee..9cda1b9 100644\n--- a/arch/powerpc/kvm/emulate_loadstore.c\n+++ b/arch/powerpc/kvm/emulate_loadstore.c\n@@ -34,6 +34,30 @@\n #include \"timing.h\"\n #include \"trace.h\"\n \n+#ifdef CONFIG_PPC_FPU\n+static bool kvmppc_check_fp_disabled(struct kvm_vcpu *vcpu)\n+{\n+\tif (!(kvmppc_get_msr(vcpu) & MSR_FP)) {\n+\t\tkvmppc_core_queue_fpunavail(vcpu);\n+\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+#endif /* CONFIG_PPC_FPU */\n+\n+#ifdef CONFIG_VSX\n+static bool kvmppc_check_vsx_disabled(struct kvm_vcpu *vcpu)\n+{\n+\tif (!(kvmppc_get_msr(vcpu) & MSR_VSX)) {\n+\t\tkvmppc_core_queue_vsx_unavail(vcpu);\n+\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+#endif /* CONFIG_VSX */\n+\n /* XXX to do:\n * lhax\n * lhaux\n@@ -66,6 +90,19 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)\n \trs = get_rs(inst);\n \trt = get_rt(inst);\n \n+\t/*\n+\t * if mmio_vsx_tx_sx_enabled == 0, copy data between\n+\t * VSR[0..31] and memory\n+\t * if mmio_vsx_tx_sx_enabled == 1, copy data between\n+\t * VSR[32..63] and memory\n+\t */\n+\tvcpu->arch.mmio_vsx_tx_sx_enabled = get_tx_or_sx(inst);\n+\tvcpu->arch.mmio_vsx_copy_nums = 0;\n+\tvcpu->arch.mmio_vsx_offset = 0;\n+\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_NONE;\n+\tvcpu->arch.mmio_sp64_extend = 0;\n+\tvcpu->arch.mmio_sign_extend = 0;\n+\n \tswitch (get_op(inst)) {\n \tcase 31:\n \t\tswitch (get_xop(inst)) {\n@@ -157,6 +194,230 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)\n \t\t\t 2, 0);\n \t\t\tbreak;\n \n+\t\tcase OP_31_XOP_LDX:\n+\t\t\temulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LDUX:\n+\t\t\temulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);\n+\t\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LWAX:\n+\t\t\temulated = kvmppc_handle_loads(run, vcpu, rt, 4, 1);\n+\t\t\tbreak;\n+\n+#ifdef CONFIG_PPC_FPU\n+\t\tcase OP_31_XOP_LFSX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\t\temulated = kvmppc_handle_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_FPR|rt, 4, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LFSUX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\t\temulated = kvmppc_handle_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_FPR|rt, 4, 1);\n+\t\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LFDX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\temulated = kvmppc_handle_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_FPR|rt, 8, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LFDUX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\temulated = kvmppc_handle_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_FPR|rt, 8, 1);\n+\t\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STFSX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\t\tVCPU_FPR(vcpu, rs), 4, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STFSUX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\t\tVCPU_FPR(vcpu, rs), 4, 1);\n+\t\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STFDX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\t\tVCPU_FPR(vcpu, rs),\n+\t\t 8, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STFDUX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\t\tVCPU_FPR(vcpu, rs),\n+\t\t 8, 1);\n+\t\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STFIWX:\n+\t\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\t\tVCPU_FPR(vcpu, rs),\n+\t\t 4, 1);\n+\t\t\tbreak;\n+#endif\n+\n+#ifdef CONFIG_VSX\n+\t\tcase OP_31_XOP_LXSDX:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;\n+\t\t\temulated = kvmppc_handle_vsx_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_VSX|rt, 8, 1, 0);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LXSSPX:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;\n+\t\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\t\temulated = kvmppc_handle_vsx_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_VSX|rt, 4, 1, 0);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LXSIWAX:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;\n+\t\t\temulated = kvmppc_handle_vsx_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_VSX|rt, 4, 1, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LXSIWZX:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;\n+\t\t\temulated = kvmppc_handle_vsx_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_VSX|rt, 4, 1, 0);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LXVD2X:\n+\t\t/*\n+\t\t * In this case, the official load/store process is like this:\n+\t\t * Step1, exit from vm by page fault isr, then kvm save vsr.\n+\t\t * Please see guest_exit_cont->store_fp_state->SAVE_32VSRS\n+\t\t * as reference.\n+\t\t *\n+\t\t * Step2, copy data between memory and VCPU\n+\t\t * Notice: for LXVD2X/STXVD2X/LXVW4X/STXVW4X, we use\n+\t\t * 2copies*8bytes or 4copies*4bytes\n+\t\t * to simulate one copy of 16bytes.\n+\t\t * Also there is an endian issue here, we should notice the\n+\t\t * layout of memory.\n+\t\t * Please see MARCO of LXVD2X_ROT/STXVD2X_ROT as more reference.\n+\t\t * If host is little-endian, kvm will call XXSWAPD for\n+\t\t * LXVD2X_ROT/STXVD2X_ROT.\n+\t\t * So, if host is little-endian,\n+\t\t * the postion of memeory should be swapped.\n+\t\t *\n+\t\t * Step3, return to guest, kvm reset register.\n+\t\t * Please see kvmppc_hv_entry->load_fp_state->REST_32VSRS\n+\t\t * as reference.\n+\t\t */\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 2;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;\n+\t\t\temulated = kvmppc_handle_vsx_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_VSX|rt, 8, 1, 0);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LXVW4X:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 4;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_WORD;\n+\t\t\temulated = kvmppc_handle_vsx_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_VSX|rt, 4, 1, 0);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_LXVDSX:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type =\n+\t\t\t\t KVMPPC_VSX_COPY_DWORD_LOAD_DUMP;\n+\t\t\temulated = kvmppc_handle_vsx_load(run, vcpu,\n+\t\t\t\tKVM_MMIO_REG_VSX|rt, 8, 1, 0);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STXSDX:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;\n+\t\t\temulated = kvmppc_handle_vsx_store(run, vcpu,\n+\t\t\t\t\t\t rs, 8, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STXSSPX:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;\n+\t\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\t\temulated = kvmppc_handle_vsx_store(run, vcpu,\n+\t\t\t\t\t\t rs, 4, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STXSIWX:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_offset = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 1;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_WORD;\n+\t\t\temulated = kvmppc_handle_vsx_store(run, vcpu,\n+\t\t\t\t\t\t\t rs, 4, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STXVD2X:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 2;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;\n+\t\t\temulated = kvmppc_handle_vsx_store(run, vcpu,\n+\t\t\t\t\t\t\t rs, 8, 1);\n+\t\t\tbreak;\n+\n+\t\tcase OP_31_XOP_STXVW4X:\n+\t\t\tif (kvmppc_check_vsx_disabled(vcpu))\n+\t\t\t\treturn EMULATE_DONE;\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums = 4;\n+\t\t\tvcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_WORD;\n+\t\t\temulated = kvmppc_handle_vsx_store(run, vcpu,\n+\t\t\t\t\t\t\t rs, 4, 1);\n+\t\t\tbreak;\n+#endif /* CONFIG_VSX */\n \t\tdefault:\n \t\t\temulated = EMULATE_FAIL;\n \t\t\tbreak;\n@@ -167,7 +428,45 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)\n \t\temulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);\n \t\tbreak;\n \n-\t/* TBD: Add support for other 64 bit load variants like ldu, ldux, ldx etc. */\n+#ifdef CONFIG_PPC_FPU\n+\tcase OP_STFS:\n+\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\treturn EMULATE_DONE;\n+\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\tVCPU_FPR(vcpu, rs),\n+\t\t\t4, 1);\n+\t\tbreak;\n+\n+\tcase OP_STFSU:\n+\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\treturn EMULATE_DONE;\n+\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\tVCPU_FPR(vcpu, rs),\n+\t\t\t4, 1);\n+\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\tbreak;\n+\n+\tcase OP_STFD:\n+\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\treturn EMULATE_DONE;\n+\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\tVCPU_FPR(vcpu, rs),\n+\t 8, 1);\n+\t\tbreak;\n+\n+\tcase OP_STFDU:\n+\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\treturn EMULATE_DONE;\n+\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\tVCPU_FPR(vcpu, rs),\n+\t 8, 1);\n+\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\tbreak;\n+#endif\n+\n+\t/* TBD: Add support for other 64 bit load variants like ldu etc. */\n \tcase OP_LD:\n \t\trt = get_rt(inst);\n \t\temulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);\n@@ -252,6 +551,40 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)\n \t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n \t\tbreak;\n \n+#ifdef CONFIG_PPC_FPU\n+\tcase OP_LFS:\n+\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\treturn EMULATE_DONE;\n+\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\temulated = kvmppc_handle_load(run, vcpu,\n+\t\t\tKVM_MMIO_REG_FPR|rt, 4, 1);\n+\t\tbreak;\n+\n+\tcase OP_LFSU:\n+\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\treturn EMULATE_DONE;\n+\t\tvcpu->arch.mmio_sp64_extend = 1;\n+\t\temulated = kvmppc_handle_load(run, vcpu,\n+\t\t\tKVM_MMIO_REG_FPR|rt, 4, 1);\n+\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\tbreak;\n+\n+\tcase OP_LFD:\n+\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\treturn EMULATE_DONE;\n+\t\temulated = kvmppc_handle_load(run, vcpu,\n+\t\t\tKVM_MMIO_REG_FPR|rt, 8, 1);\n+\t\tbreak;\n+\n+\tcase OP_LFDU:\n+\t\tif (kvmppc_check_fp_disabled(vcpu))\n+\t\t\treturn EMULATE_DONE;\n+\t\temulated = kvmppc_handle_load(run, vcpu,\n+\t\t\tKVM_MMIO_REG_FPR|rt, 8, 1);\n+\t\tkvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);\n+\t\tbreak;\n+#endif\n+\n \tdefault:\n \t\temulated = EMULATE_FAIL;\n \t\tbreak;\ndiff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c\nindex 95c91a9..21c9aff 100644\n--- a/arch/powerpc/kvm/powerpc.c\n+++ b/arch/powerpc/kvm/powerpc.c\n@@ -37,6 +37,8 @@\n #include <asm/cputhreads.h>\n #include <asm/irqflags.h>\n #include <asm/iommu.h>\n+#include <asm/kvm_fpu.h>\n+#include <asm/switch_to.h>\n #include \"timing.h\"\n #include \"irq.h\"\n #include \"../mm/mmu_decl.h\"\n@@ -806,6 +808,127 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,\n \t\tkvm->arch.kvm_ops->irq_bypass_del_producer(cons, prod);\n }\n \n+#ifdef CONFIG_VSX\n+static inline int kvmppc_get_vsr_dword_offset(int index)\n+{\n+\tint offset;\n+\n+\tif ((index != 0) && (index != 1))\n+\t\treturn -1;\n+\n+#ifdef __BIG_ENDIAN\n+\toffset = index;\n+#else\n+\toffset = 1 - index;\n+#endif\n+\n+\treturn offset;\n+}\n+\n+static inline int kvmppc_get_vsr_word_offset(int index)\n+{\n+\tint offset;\n+\n+\tif ((index > 3) || (index < 0))\n+\t\treturn -1;\n+\n+#ifdef __BIG_ENDIAN\n+\toffset = index;\n+#else\n+\toffset = 3 - index;\n+#endif\n+\treturn offset;\n+}\n+\n+static inline void kvmppc_set_vsr_dword(struct kvm_vcpu *vcpu,\n+\tu64 gpr)\n+{\n+\tunion kvmppc_one_reg val;\n+\tint offset = kvmppc_get_vsr_dword_offset(vcpu->arch.mmio_vsx_offset);\n+\tint index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;\n+\n+\tif (offset == -1)\n+\t\treturn;\n+\n+\tif (vcpu->arch.mmio_vsx_tx_sx_enabled) {\n+\t\tval.vval = VCPU_VSX_VR(vcpu, index);\n+\t\tval.vsxval[offset] = gpr;\n+\t\tVCPU_VSX_VR(vcpu, index) = val.vval;\n+\t} else {\n+\t\tVCPU_VSX_FPR(vcpu, index, offset) = gpr;\n+\t}\n+}\n+\n+static inline void kvmppc_set_vsr_dword_dump(struct kvm_vcpu *vcpu,\n+\tu64 gpr)\n+{\n+\tunion kvmppc_one_reg val;\n+\tint index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;\n+\n+\tif (vcpu->arch.mmio_vsx_tx_sx_enabled) {\n+\t\tval.vval = VCPU_VSX_VR(vcpu, index);\n+\t\tval.vsxval[0] = gpr;\n+\t\tval.vsxval[1] = gpr;\n+\t\tVCPU_VSX_VR(vcpu, index) = val.vval;\n+\t} else {\n+\t\tVCPU_VSX_FPR(vcpu, index, 0) = gpr;\n+\t\tVCPU_VSX_FPR(vcpu, index, 1) = gpr;\n+\t}\n+}\n+\n+static inline void kvmppc_set_vsr_word(struct kvm_vcpu *vcpu,\n+\tu32 gpr32)\n+{\n+\tunion kvmppc_one_reg val;\n+\tint offset = kvmppc_get_vsr_word_offset(vcpu->arch.mmio_vsx_offset);\n+\tint index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;\n+\tint dword_offset, word_offset;\n+\n+\tif (offset == -1)\n+\t\treturn;\n+\n+\tif (vcpu->arch.mmio_vsx_tx_sx_enabled) {\n+\t\tval.vval = VCPU_VSX_VR(vcpu, index);\n+\t\tval.vsx32val[offset] = gpr32;\n+\t\tVCPU_VSX_VR(vcpu, index) = val.vval;\n+\t} else {\n+\t\tdword_offset = offset / 2;\n+\t\tword_offset = offset % 2;\n+\t\tval.vsxval[0] = VCPU_VSX_FPR(vcpu, index, dword_offset);\n+\t\tval.vsx32val[word_offset] = gpr32;\n+\t\tVCPU_VSX_FPR(vcpu, index, dword_offset) = val.vsxval[0];\n+\t}\n+}\n+#endif /* CONFIG_VSX */\n+\n+#ifdef CONFIG_PPC_FPU\n+static inline u64 sp_to_dp(u32 fprs)\n+{\n+\tu64 fprd;\n+\n+\tpreempt_disable();\n+\tenable_kernel_fp();\n+\tkvm_cvt_fd(&fprs, &fprd);\n+\tpreempt_enable();\n+\treturn fprd;\n+}\n+\n+static inline u32 dp_to_sp(u64 fprd)\n+{\n+\tu32 fprs;\n+\n+\tpreempt_disable();\n+\tenable_kernel_fp();\n+\tkvm_cvt_df(&fprd, &fprs);\n+\tpreempt_enable();\n+\treturn fprs;\n+}\n+\n+#else\n+#define sp_to_dp(x)\t(x)\n+#define dp_to_sp(x)\t(x)\n+#endif /* CONFIG_PPC_FPU */\n+\n static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,\n struct kvm_run *run)\n {\n@@ -832,6 +955,10 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,\n \t\t}\n \t}\n \n+\t/* conversion between single and double precision */\n+\tif ((vcpu->arch.mmio_sp64_extend) && (run->mmio.len == 4))\n+\t\tgpr = sp_to_dp(gpr);\n+\n \tif (vcpu->arch.mmio_sign_extend) {\n \t\tswitch (run->mmio.len) {\n #ifdef CONFIG_PPC64\n@@ -848,8 +975,6 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,\n \t\t}\n \t}\n \n-\tkvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);\n-\n \tswitch (vcpu->arch.io_gpr & KVM_MMIO_REG_EXT_MASK) {\n \tcase KVM_MMIO_REG_GPR:\n \t\tkvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);\n@@ -866,6 +991,17 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,\n \t\tvcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;\n \t\tbreak;\n #endif\n+#ifdef CONFIG_VSX\n+\tcase KVM_MMIO_REG_VSX:\n+\t\tif (vcpu->arch.mmio_vsx_copy_type == KVMPPC_VSX_COPY_DWORD)\n+\t\t\tkvmppc_set_vsr_dword(vcpu, gpr);\n+\t\telse if (vcpu->arch.mmio_vsx_copy_type == KVMPPC_VSX_COPY_WORD)\n+\t\t\tkvmppc_set_vsr_word(vcpu, gpr);\n+\t\telse if (vcpu->arch.mmio_vsx_copy_type ==\n+\t\t\t\tKVMPPC_VSX_COPY_DWORD_LOAD_DUMP)\n+\t\t\tkvmppc_set_vsr_dword_dump(vcpu, gpr);\n+\t\tbreak;\n+#endif\n \tdefault:\n \t\tBUG();\n \t}\n@@ -932,6 +1068,35 @@ int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,\n \treturn __kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian, 1);\n }\n \n+#ifdef CONFIG_VSX\n+int kvmppc_handle_vsx_load(struct kvm_run *run, struct kvm_vcpu *vcpu,\n+\t\t\tunsigned int rt, unsigned int bytes,\n+\t\t\tint is_default_endian, int mmio_sign_extend)\n+{\n+\tenum emulation_result emulated = EMULATE_DONE;\n+\n+\t/* Currently, mmio_vsx_copy_nums only allowed to be less than 4 */\n+\tif ( (vcpu->arch.mmio_vsx_copy_nums > 4) ||\n+\t\t(vcpu->arch.mmio_vsx_copy_nums < 0) ) {\n+\t\treturn EMULATE_FAIL;\n+\t}\n+\n+\twhile (vcpu->arch.mmio_vsx_copy_nums) {\n+\t\temulated = __kvmppc_handle_load(run, vcpu, rt, bytes,\n+\t\t\tis_default_endian, mmio_sign_extend);\n+\n+\t\tif (emulated != EMULATE_DONE)\n+\t\t\tbreak;\n+\n+\t\tvcpu->arch.paddr_accessed += run->mmio.len;\n+\n+\t\tvcpu->arch.mmio_vsx_copy_nums--;\n+\t\tvcpu->arch.mmio_vsx_offset++;\n+\t}\n+\treturn emulated;\n+}\n+#endif /* CONFIG_VSX */\n+\n int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,\n \t\t\tu64 val, unsigned int bytes, int is_default_endian)\n {\n@@ -957,6 +1122,9 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,\n \tvcpu->mmio_needed = 1;\n \tvcpu->mmio_is_write = 1;\n \n+\tif ((vcpu->arch.mmio_sp64_extend) && (bytes == 4))\n+\t\tval = dp_to_sp(val);\n+\n \t/* Store the value at the lowest bytes in 'data'. */\n \tif (!host_swabbed) {\n \t\tswitch (bytes) {\n@@ -990,6 +1158,129 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,\n }\n EXPORT_SYMBOL_GPL(kvmppc_handle_store);\n \n+#ifdef CONFIG_VSX\n+static inline int kvmppc_get_vsr_data(struct kvm_vcpu *vcpu, int rs, u64 *val)\n+{\n+\tu32 dword_offset, word_offset;\n+\tunion kvmppc_one_reg reg;\n+\tint vsx_offset = 0;\n+\tint copy_type = vcpu->arch.mmio_vsx_copy_type;\n+\tint result = 0;\n+\n+\tswitch (copy_type) {\n+\tcase KVMPPC_VSX_COPY_DWORD:\n+\t\tvsx_offset =\n+\t\t\tkvmppc_get_vsr_dword_offset(vcpu->arch.mmio_vsx_offset);\n+\n+\t\tif (vsx_offset == -1) {\n+\t\t\tresult = -1;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (!vcpu->arch.mmio_vsx_tx_sx_enabled) {\n+\t\t\t*val = VCPU_VSX_FPR(vcpu, rs, vsx_offset);\n+\t\t} else {\n+\t\t\treg.vval = VCPU_VSX_VR(vcpu, rs);\n+\t\t\t*val = reg.vsxval[vsx_offset];\n+\t\t}\n+\t\tbreak;\n+\n+\tcase KVMPPC_VSX_COPY_WORD:\n+\t\tvsx_offset =\n+\t\t\tkvmppc_get_vsr_word_offset(vcpu->arch.mmio_vsx_offset);\n+\n+\t\tif (vsx_offset == -1) {\n+\t\t\tresult = -1;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (!vcpu->arch.mmio_vsx_tx_sx_enabled) {\n+\t\t\tdword_offset = vsx_offset / 2;\n+\t\t\tword_offset = vsx_offset % 2;\n+\t\t\treg.vsxval[0] = VCPU_VSX_FPR(vcpu, rs, dword_offset);\n+\t\t\t*val = reg.vsx32val[word_offset];\n+\t\t} else {\n+\t\t\treg.vval = VCPU_VSX_VR(vcpu, rs);\n+\t\t\t*val = reg.vsx32val[vsx_offset];\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\tresult = -1;\n+\t\tbreak;\n+\t}\n+\n+\treturn result;\n+}\n+\n+int kvmppc_handle_vsx_store(struct kvm_run *run, struct kvm_vcpu *vcpu,\n+\t\t\tint rs, unsigned int bytes, int is_default_endian)\n+{\n+\tu64 val;\n+\tenum emulation_result emulated = EMULATE_DONE;\n+\n+\tvcpu->arch.io_gpr = rs;\n+\n+\t/* Currently, mmio_vsx_copy_nums only allowed to be less than 4 */\n+\tif ( (vcpu->arch.mmio_vsx_copy_nums > 4) ||\n+\t\t(vcpu->arch.mmio_vsx_copy_nums < 0) ) {\n+\t\treturn EMULATE_FAIL;\n+\t}\n+\n+\twhile (vcpu->arch.mmio_vsx_copy_nums) {\n+\t\tif (kvmppc_get_vsr_data(vcpu, rs, &val) == -1)\n+\t\t\treturn EMULATE_FAIL;\n+\n+\t\temulated = kvmppc_handle_store(run, vcpu,\n+\t\t\t val, bytes, is_default_endian);\n+\n+\t\tif (emulated != EMULATE_DONE)\n+\t\t\tbreak;\n+\n+\t\tvcpu->arch.paddr_accessed += run->mmio.len;\n+\n+\t\tvcpu->arch.mmio_vsx_copy_nums--;\n+\t\tvcpu->arch.mmio_vsx_offset++;\n+\t}\n+\n+\treturn emulated;\n+}\n+\n+static int kvmppc_emulate_mmio_vsx_loadstore(struct kvm_vcpu *vcpu,\n+\t\t\tstruct kvm_run *run)\n+{\n+\tenum emulation_result emulated = EMULATE_FAIL;\n+\tint r;\n+\n+\tvcpu->arch.paddr_accessed += run->mmio.len;\n+\n+\tif (!vcpu->mmio_is_write) {\n+\t\temulated = kvmppc_handle_vsx_load(run, vcpu, vcpu->arch.io_gpr,\n+\t\t\t run->mmio.len, 1, vcpu->arch.mmio_sign_extend);\n+\t} else {\n+\t\temulated = kvmppc_handle_vsx_store(run, vcpu,\n+\t\t\t vcpu->arch.io_gpr, run->mmio.len, 1);\n+\t}\n+\n+\tswitch (emulated) {\n+\tcase EMULATE_DO_MMIO:\n+\t\trun->exit_reason = KVM_EXIT_MMIO;\n+\t\tr = RESUME_HOST;\n+\t\tbreak;\n+\tcase EMULATE_FAIL:\n+\t\tpr_info(\"KVM: MMIO emulation failed (VSX repeat)\\n\");\n+\t\trun->exit_reason = KVM_EXIT_INTERNAL_ERROR;\n+\t\trun->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;\n+\t\tr = RESUME_HOST;\n+\t\tbreak;\n+\tdefault:\n+\t\tr = RESUME_GUEST;\n+\t\tbreak;\n+\t}\n+\treturn r;\n+}\n+#endif /* CONFIG_VSX */\n+\n int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)\n {\n \tint r = 0;\n@@ -1092,13 +1383,24 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)\n \tint r;\n \tsigset_t sigsaved;\n \n-\tif (vcpu->sigset_active)\n-\t\tsigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);\n-\n \tif (vcpu->mmio_needed) {\n+\t\tvcpu->mmio_needed = 0;\n \t\tif (!vcpu->mmio_is_write)\n \t\t\tkvmppc_complete_mmio_load(vcpu, run);\n-\t\tvcpu->mmio_needed = 0;\n+#ifdef CONFIG_VSX\n+\t\tif (vcpu->arch.mmio_vsx_copy_nums > 0) {\n+\t\t\tvcpu->arch.mmio_vsx_copy_nums--;\n+\t\t\tvcpu->arch.mmio_vsx_offset++;\n+\t\t}\n+\n+\t\tif (vcpu->arch.mmio_vsx_copy_nums > 0) {\n+\t\t\tr = kvmppc_emulate_mmio_vsx_loadstore(vcpu, run);\n+\t\t\tif (r == RESUME_HOST) {\n+\t\t\t\tvcpu->mmio_needed = 1;\n+\t\t\t\treturn r;\n+\t\t\t}\n+\t\t}\n+#endif\n \t} else if (vcpu->arch.osi_needed) {\n \t\tu64 *gprs = run->osi.gprs;\n \t\tint i;\n@@ -1120,6 +1422,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)\n #endif\n \t}\n \n+\tif (vcpu->sigset_active)\n+\t\tsigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);\n+\n \tif (run->immediate_exit)\n \t\tr = -EINTR;\n \telse\n", "prefixes": [ "2/5" ] }