get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/831064/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 831064,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/831064/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/kvm-ppc/patch/1509079594-28977-7-git-send-email-paulus@ozlabs.org/",
    "project": {
        "id": 23,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/23/?format=api",
        "name": "KVM PowerPC development",
        "link_name": "kvm-ppc",
        "list_id": "kvm-ppc.vger.kernel.org",
        "list_email": "kvm-ppc@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1509079594-28977-7-git-send-email-paulus@ozlabs.org>",
    "list_archive_url": null,
    "date": "2017-10-27T04:46:34",
    "name": "[v2,6/6] KVM: PPC: Book3S HV: Run HPT guests on POWER9 radix hosts",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "791a29ba9bfd21672cb022d75ed54409ec30faa7",
    "submitter": {
        "id": 67079,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/67079/?format=api",
        "name": "Paul Mackerras",
        "email": "paulus@ozlabs.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/kvm-ppc/patch/1509079594-28977-7-git-send-email-paulus@ozlabs.org/mbox/",
    "series": [
        {
            "id": 10490,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/10490/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/kvm-ppc/list/?series=10490",
            "date": "2017-10-27T04:46:28",
            "name": "KVM: PPC: Book3S HV: Run HPT guests on radix hosts",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/10490/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/831064/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/831064/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<kvm-ppc-owner@vger.kernel.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=kvm-ppc-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"BH2TOe+l\";\n\tdkim-atps=neutral"
        ],
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3yNWYs4lzwz9t3F\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 27 Oct 2017 15:46:57 +1100 (AEDT)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751483AbdJ0Eqz (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tFri, 27 Oct 2017 00:46:55 -0400",
            "from ozlabs.org ([103.22.144.67]:46479 \"EHLO ozlabs.org\"\n\trhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP\n\tid S1751774AbdJ0Eqt (ORCPT <rfc822;kvm-ppc@vger.kernel.org>);\n\tFri, 27 Oct 2017 00:46:49 -0400",
            "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 3yNWYf0k8dz9t3H;\n\tFri, 27 Oct 2017 15:46:45 +1100 (AEDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; \n\tt=1509079607; bh=CFKOeJ+dt7wzVWcmvgPfoiz4ggSIwJEpUtUUJo66iww=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=BH2TOe+l8P0y6gIYiR+DmKPGZ0pi6hkg4TcFT+Dfrm0GFEXN/kAYe+oxBRjaA/3fR\n\tb56eRtDJbdo3KV7Dz8PzPeEZaOngwOu7h4btGw3VAq3jxrsBUg40NJyQFeAd0htKCM\n\tmeCr8AzVVIDNeioFJud+pQBmdzr9/VV6/YByprSyYHxUvKTHAInn1R4NgLETr8SiFP\n\tNyf+PGw2h6K169jDuOP43lRD+XG6+8A46RBwPawLx7/78dAQi5562jDWdoIRNl0Rzu\n\tK78WRHJ1lS5hPVrjhc6EqV56kQvH95njWpWPTif1Jtq84oL+D857mzDKkPvgsvnbFP\n\tBbiZDuM3qWFDw==",
        "From": "Paul Mackerras <paulus@ozlabs.org>",
        "To": "kvm@vger.kernel.org, kvm-ppc@vger.kernel.org",
        "Cc": "david@gibson.dropbear.id.au",
        "Subject": "[PATCH v2 6/6] KVM: PPC: Book3S HV: Run HPT guests on POWER9 radix\n\thosts",
        "Date": "Fri, 27 Oct 2017 15:46:34 +1100",
        "Message-Id": "<1509079594-28977-7-git-send-email-paulus@ozlabs.org>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1509079594-28977-1-git-send-email-paulus@ozlabs.org>",
        "References": "<1509079594-28977-1-git-send-email-paulus@ozlabs.org>",
        "Sender": "kvm-ppc-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<kvm-ppc.vger.kernel.org>",
        "X-Mailing-List": "kvm-ppc@vger.kernel.org"
    },
    "content": "This patch removes the restriction that a radix host can only run\nradix guests, allowing us to run HPT (hashed page table) guests as\nwell.  This is useful because it provides a way to run old guest\nkernels that know about POWER8 but not POWER9.\n\nUnfortunately, POWER9 currently has a restriction that all threads\nin a given code must either all be in HPT mode, or all in radix mode.\nThis means that when entering a HPT guest, we have to obtain control\nof all 4 threads in the core and get them to switch their LPIDR and\nLPCR registers, even if they are not going to run a guest.  On guest\nexit we also have to get all threads to switch LPIDR and LPCR back\nto host values.\n\nTo make this feasible, we require that KVM not be in the \"independent\nthreads\" mode, and that the CPU cores be in single-threaded mode from\nthe host kernel's perspective (only thread 0 online; threads 1, 2 and\n3 offline).  That allows us to use the same code as on POWER8 for\nobtaining control of the secondary threads.\n\nTo manage the LPCR/LPIDR changes required, we extend the kvm_split_info\nstruct to contain the information needed by the secondary threads.\nAll threads perform a barrier synchronization (where all threads wait\nfor every other thread to reach the synchronization point) on guest\nentry, both before and after loading LPCR and LPIDR.  On guest exit,\nthey all once again perform a barrier synchronization both before\nand after loading host values into LPCR and LPIDR.\n\nFinally, it is also currently necessary to flush the entire TLB every\ntime we enter a HPT guest on a radix host.  We do this on thread 0\nwith a loop of tlbiel instructions.\n\nSigned-off-by: Paul Mackerras <paulus@ozlabs.org>\n---\n arch/powerpc/include/asm/kvm_book3s_asm.h | 13 +++-\n arch/powerpc/kernel/asm-offsets.c         |  3 +\n arch/powerpc/kvm/book3s_hv.c              | 47 ++++++++++++---\n arch/powerpc/kvm/book3s_hv_builtin.c      | 99 ++++++++++++++++++++++++++++++-\n arch/powerpc/kvm/book3s_hv_rmhandlers.S   | 67 +++++++++++++++++++--\n 5 files changed, 212 insertions(+), 17 deletions(-)",
    "diff": "diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h\nindex 7cea76f..ab386af 100644\n--- a/arch/powerpc/include/asm/kvm_book3s_asm.h\n+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h\n@@ -82,6 +82,16 @@ struct kvm_split_mode {\n \tu8\t\tdo_nap;\n \tu8\t\tnapped[MAX_SMT_THREADS];\n \tstruct kvmppc_vcore *vc[MAX_SUBCORES];\n+\t/* Bits for changing lpcr on P9 */\n+\tunsigned long\tlpcr_req;\n+\tunsigned long\tlpidr_req;\n+\tunsigned long\thost_lpcr;\n+\tu32\t\tdo_set;\n+\tu32\t\tdo_restore;\n+\tunion {\n+\t\tu32\tallphases;\n+\t\tu8\tphase[4];\n+\t} lpcr_sync;\n };\n \n /*\n@@ -107,7 +117,8 @@ struct kvmppc_host_state {\n \tu8 hwthread_req;\n \tu8 hwthread_state;\n \tu8 host_ipi;\n-\tu8 ptid;\n+\tu8 ptid;\t\t/* thread number within subcore when split */\n+\tu8 tid;\t\t\t/* thread number within whole core */\n \tstruct kvm_vcpu *kvm_vcpu;\n \tstruct kvmppc_vcore *kvm_vcore;\n \tvoid __iomem *xics_phys;\ndiff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c\nindex 8cfb20e..519fad5 100644\n--- a/arch/powerpc/kernel/asm-offsets.c\n+++ b/arch/powerpc/kernel/asm-offsets.c\n@@ -642,6 +642,7 @@ int main(void)\n \tHSTATE_FIELD(HSTATE_SAVED_XIRR, saved_xirr);\n \tHSTATE_FIELD(HSTATE_HOST_IPI, host_ipi);\n \tHSTATE_FIELD(HSTATE_PTID, ptid);\n+\tHSTATE_FIELD(HSTATE_TID, tid);\n \tHSTATE_FIELD(HSTATE_MMCR0, host_mmcr[0]);\n \tHSTATE_FIELD(HSTATE_MMCR1, host_mmcr[1]);\n \tHSTATE_FIELD(HSTATE_MMCRA, host_mmcr[2]);\n@@ -667,6 +668,8 @@ int main(void)\n \tOFFSET(KVM_SPLIT_LDBAR, kvm_split_mode, ldbar);\n \tOFFSET(KVM_SPLIT_DO_NAP, kvm_split_mode, do_nap);\n \tOFFSET(KVM_SPLIT_NAPPED, kvm_split_mode, napped);\n+\tOFFSET(KVM_SPLIT_DO_SET, kvm_split_mode, do_set);\n+\tOFFSET(KVM_SPLIT_DO_RESTORE, kvm_split_mode, do_restore);\n #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */\n \n #ifdef CONFIG_PPC_BOOK3S_64\ndiff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c\nindex b5fbf76..fff62fd 100644\n--- a/arch/powerpc/kvm/book3s_hv.c\n+++ b/arch/powerpc/kvm/book3s_hv.c\n@@ -2414,6 +2414,11 @@ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)\n \tif (!cpu_has_feature(CPU_FTR_ARCH_207S))\n \t\treturn false;\n \n+\t/* POWER9 currently requires all threads to be in the same MMU mode */\n+\tif (cpu_has_feature(CPU_FTR_ARCH_300) &&\n+\t    kvm_is_radix(vc->kvm) != kvm_is_radix(cip->vc[0]->kvm))\n+\t\treturn false;\n+\n \tif (n_threads < cip->max_subcore_threads)\n \t\tn_threads = cip->max_subcore_threads;\n \tif (!subcore_config_ok(cip->n_subcores + 1, n_threads))\n@@ -2452,9 +2457,6 @@ static void prepare_threads(struct kvmppc_vcore *vc)\n \tfor_each_runnable_thread(i, vcpu, vc) {\n \t\tif (signal_pending(vcpu->arch.run_task))\n \t\t\tvcpu->arch.ret = -EINTR;\n-\t\telse if (kvm_is_radix(vc->kvm) != radix_enabled())\n-\t\t\t/* can't actually run HPT guest on radix host yet... */\n-\t\t\tvcpu->arch.ret = -EINVAL;\n \t\telse if (vcpu->arch.vpa.update_pending ||\n \t\t\t vcpu->arch.slb_shadow.update_pending ||\n \t\t\t vcpu->arch.dtl.update_pending)\n@@ -2643,6 +2645,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)\n \tint controlled_threads;\n \tint trap;\n \tbool is_power8;\n+\tbool hpt_on_radix;\n \n \t/*\n \t * Remove from the list any threads that have a signal pending\n@@ -2671,9 +2674,13 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)\n \t * Make sure we are running on primary threads, and that secondary\n \t * threads are offline.  Also check if the number of threads in this\n \t * guest are greater than the current system threads per guest.\n+\t * On POWER9, we need to be not in independent-threads mode if\n+\t * this is a HPT guest on a radix host.\n \t */\n-\tif ((controlled_threads > 1) &&\n-\t    ((vc->num_threads > threads_per_subcore) || !on_primary_thread())) {\n+\thpt_on_radix = radix_enabled() && !kvm_is_radix(vc->kvm);\n+\tif (((controlled_threads > 1) &&\n+\t     ((vc->num_threads > threads_per_subcore) || !on_primary_thread())) ||\n+\t    (hpt_on_radix && vc->kvm->arch.threads_indep)) {\n \t\tfor_each_runnable_thread(i, vcpu, vc) {\n \t\t\tvcpu->arch.ret = -EBUSY;\n \t\t\tkvmppc_remove_runnable(vc, vcpu);\n@@ -2739,7 +2746,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)\n \tis_power8 = cpu_has_feature(CPU_FTR_ARCH_207S)\n \t\t&& !cpu_has_feature(CPU_FTR_ARCH_300);\n \n-\tif (split > 1) {\n+\tif (split > 1 || hpt_on_radix) {\n \t\tsip = &split_info;\n \t\tmemset(&split_info, 0, sizeof(split_info));\n \t\tfor (sub = 0; sub < core_info.n_subcores; ++sub)\n@@ -2761,13 +2768,24 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)\n \t\t\tsplit_info.subcore_size = subcore_size;\n \t\t} else {\n \t\t\tsplit_info.subcore_size = 1;\n+\t\t\tif (hpt_on_radix) {\n+\t\t\t\t/* Use the split_info for LPCR/LPIDR changes */\n+\t\t\t\tsplit_info.lpcr_req = vc->lpcr;\n+\t\t\t\tsplit_info.lpidr_req = vc->kvm->arch.lpid;\n+\t\t\t\tsplit_info.host_lpcr = vc->kvm->arch.host_lpcr;\n+\t\t\t\tsplit_info.do_set = 1;\n+\t\t\t}\n \t\t}\n \n \t\t/* order writes to split_info before kvm_split_mode pointer */\n \t\tsmp_wmb();\n \t}\n-\tfor (thr = 0; thr < controlled_threads; ++thr)\n+\n+\tfor (thr = 0; thr < controlled_threads; ++thr) {\n+\t\tpaca[pcpu + thr].kvm_hstate.tid = thr;\n+\t\tpaca[pcpu + thr].kvm_hstate.napping = 0;\n \t\tpaca[pcpu + thr].kvm_hstate.kvm_split_mode = sip;\n+\t}\n \n \t/* Initiate micro-threading (split-core) on POWER8 if required */\n \tif (cmd_bit) {\n@@ -2820,8 +2838,10 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)\n \t * When doing micro-threading, poke the inactive threads as well.\n \t * This gets them to the nap instruction after kvm_do_nap,\n \t * which reduces the time taken to unsplit later.\n+\t * For POWER9 HPT guest on radix host, we need all the secondary\n+\t * threads woken up so they can do the LPCR/LPIDR change.\n \t */\n-\tif (cmd_bit) {\n+\tif (cmd_bit || hpt_on_radix) {\n \t\tsplit_info.do_nap = 1;\t/* ask secondaries to nap when done */\n \t\tfor (thr = 1; thr < threads_per_subcore; ++thr)\n \t\t\tif (!(active & (1 << thr)))\n@@ -2879,8 +2899,17 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)\n \t\t\tcpu_relax();\n \t\t\t++loops;\n \t\t}\n-\t\tsplit_info.do_nap = 0;\n+\t} else if (hpt_on_radix) {\n+\t\t/* Wait for all threads to have seen final sync */\n+\t\tfor (thr = 1; thr < controlled_threads; ++thr) {\n+\t\t\twhile (paca[pcpu + thr].kvm_hstate.kvm_split_mode) {\n+\t\t\t\tHMT_low();\n+\t\t\t\tbarrier();\n+\t\t\t}\n+\t\t\tHMT_medium();\n+\t\t}\n \t}\n+\tsplit_info.do_nap = 0;\n \n \tkvmppc_set_host_core(pcpu);\n \ndiff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c\nindex 2791922..d77971b 100644\n--- a/arch/powerpc/kvm/book3s_hv_builtin.c\n+++ b/arch/powerpc/kvm/book3s_hv_builtin.c\n@@ -278,7 +278,8 @@ void kvmhv_commence_exit(int trap)\n \tstruct kvmppc_vcore *vc = local_paca->kvm_hstate.kvm_vcore;\n \tint ptid = local_paca->kvm_hstate.ptid;\n \tstruct kvm_split_mode *sip = local_paca->kvm_hstate.kvm_split_mode;\n-\tint me, ee, i;\n+\tint me, ee, i, t;\n+\tint cpu0;\n \n \t/* Set our bit in the threads-exiting-guest map in the 0xff00\n \t   bits of vcore->entry_exit_map */\n@@ -320,6 +321,22 @@ void kvmhv_commence_exit(int trap)\n \t\tif ((ee >> 8) == 0)\n \t\t\tkvmhv_interrupt_vcore(vc, ee);\n \t}\n+\n+\t/*\n+\t * On POWER9 when running a HPT guest on a radix host (sip != NULL),\n+\t * we have to interrupt inactive CPU threads to get them to\n+\t * restore the host LPCR value.\n+\t */\n+\tif (sip->lpcr_req) {\n+\t\tif (cmpxchg(&sip->do_restore, 0, 1) == 0) {\n+\t\t\tvc = local_paca->kvm_hstate.kvm_vcore;\n+\t\t\tcpu0 = vc->pcpu + ptid - local_paca->kvm_hstate.tid;\n+\t\t\tfor (t = 1; t < threads_per_core; ++t) {\n+\t\t\t\tif (sip->napped[t])\n+\t\t\t\t\tkvmhv_rm_send_ipi(cpu0 + t);\n+\t\t\t}\n+\t\t}\n+\t}\n }\n \n struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv;\n@@ -607,3 +624,83 @@ void kvmppc_bad_interrupt(struct pt_regs *regs)\n \tdie(\"Bad interrupt in KVM entry/exit code\", regs, SIGABRT);\n \tpanic(\"Bad KVM trap\");\n }\n+\n+/*\n+ * Functions used to switch LPCR HR and UPRT bits on all threads\n+ * when entering and exiting HPT guests on a radix host.\n+ */\n+\n+#define PHASE_REALMODE\t\t1\t/* in real mode */\n+#define PHASE_SET_LPCR\t\t2\t/* have set LPCR */\n+#define PHASE_OUT_OF_GUEST\t4\t/* have finished executing in guest */\n+#define PHASE_RESET_LPCR\t8\t/* have reset LPCR to host value */\n+\n+#define ALL(p)\t\t(((p) << 24) | ((p) << 16) | ((p) << 8) | (p))\n+\n+static void wait_for_sync(struct kvm_split_mode *sip, int phase)\n+{\n+\tint thr = local_paca->kvm_hstate.tid;\n+\n+\tsip->lpcr_sync.phase[thr] |= phase;\n+\tphase = ALL(phase);\n+\twhile ((sip->lpcr_sync.allphases & phase) != phase) {\n+\t\tHMT_low();\n+\t\tbarrier();\n+\t}\n+\tHMT_medium();\n+}\n+\n+void kvmhv_p9_set_lpcr(struct kvm_split_mode *sip)\n+{\n+\tunsigned long rb, set;\n+\n+\t/* wait for every other thread to get to real mode */\n+\twait_for_sync(sip, PHASE_REALMODE);\n+\n+\t/* Set LPCR and LPIDR */\n+\tmtspr(SPRN_LPCR, sip->lpcr_req);\n+\tmtspr(SPRN_LPID, sip->lpidr_req);\n+\tisync();\n+\n+\t/* Invalidate the TLB on thread 0 */\n+\tif (local_paca->kvm_hstate.tid == 0) {\n+\t\tsip->do_set = 0;\n+\t\tasm volatile(\"ptesync\" : : : \"memory\");\n+\t\tfor (set = 0; set < POWER9_TLB_SETS_RADIX; ++set) {\n+\t\t\trb = TLBIEL_INVAL_SET_LPID +\n+\t\t\t\t(set << TLBIEL_INVAL_SET_SHIFT);\n+\t\t\tasm volatile(PPC_TLBIEL(%0, %1, 0, 0, 0) : :\n+\t\t\t\t     \"r\" (rb), \"r\" (0));\n+\t\t}\n+\t\tasm volatile(\"ptesync\" : : : \"memory\");\n+\t}\n+\n+\t/* indicate that we have done so and wait for others */\n+\twait_for_sync(sip, PHASE_SET_LPCR);\n+\t/* order read of sip->lpcr_sync.allphases vs. sip->do_set */\n+\tsmp_rmb();\n+}\n+\n+/*\n+ * Called when a thread that has been in the guest needs\n+ * to reload the host LPCR value - but only on POWER9 when\n+ * running a HPT guest on a radix host.\n+ */\n+void kvmhv_p9_restore_lpcr(struct kvm_split_mode *sip)\n+{\n+\t/* we're out of the guest... */\n+\twait_for_sync(sip, PHASE_OUT_OF_GUEST);\n+\n+\tmtspr(SPRN_LPID, 0);\n+\tmtspr(SPRN_LPCR, sip->host_lpcr);\n+\tisync();\n+\n+\tif (local_paca->kvm_hstate.tid == 0) {\n+\t\tsip->do_restore = 0;\n+\t\tsmp_wmb();\t/* order store of do_restore vs. phase */\n+\t}\n+\n+\twait_for_sync(sip, PHASE_RESET_LPCR);\n+\tsmp_mb();\n+\tlocal_paca->kvm_hstate.kvm_split_mode = NULL;\n+}\ndiff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S\nindex ae6c616..7add189 100644\n--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S\n+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S\n@@ -82,6 +82,19 @@ _GLOBAL_TOC(kvmppc_hv_entry_trampoline)\n \tRFI\n \n kvmppc_call_hv_entry:\n+BEGIN_FTR_SECTION\n+\t/* On P9, do LPCR setting, if necessary */\n+\tld\tr3, HSTATE_SPLIT_MODE(r13)\n+\tcmpdi\tr3, 0\n+\tbeq\t46f\n+\tlwz\tr4, KVM_SPLIT_DO_SET(r3)\n+\tcmpwi\tr4, 0\n+\tbeq\t46f\n+\tbl\tkvmhv_p9_set_lpcr\n+\tnop\n+46:\n+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)\n+\n \tld\tr4, HSTATE_KVM_VCPU(r13)\n \tbl\tkvmppc_hv_entry\n \n@@ -385,10 +398,10 @@ kvm_secondary_got_guest:\n \tld\tr6, 0(r6)\n \tmtspr\tSPRN_HDEC, r6\n \t/* and set per-LPAR registers, if doing dynamic micro-threading */\n-BEGIN_FTR_SECTION\n \tld\tr6, HSTATE_SPLIT_MODE(r13)\n \tcmpdi\tr6, 0\n \tbeq\t63f\n+BEGIN_FTR_SECTION\n \tld\tr0, KVM_SPLIT_RPR(r6)\n \tmtspr\tSPRN_RPR, r0\n \tld\tr0, KVM_SPLIT_PMMAR(r6)\n@@ -396,7 +409,15 @@ BEGIN_FTR_SECTION\n \tld\tr0, KVM_SPLIT_LDBAR(r6)\n \tmtspr\tSPRN_LDBAR, r0\n \tisync\n-END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)\n+FTR_SECTION_ELSE\n+\t/* On P9 we use the split_info for coordinating LPCR changes */\n+\tlwz\tr4, KVM_SPLIT_DO_SET(r6)\n+\tcmpwi\tr4, 0\n+\tbeq\t63f\n+\tmr\tr3, r6\n+\tbl\tkvmhv_p9_set_lpcr\n+\tnop\n+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)\n 63:\n \t/* Order load of vcpu after load of vcore */\n \tlwsync\n@@ -467,6 +488,12 @@ kvm_no_guest:\n \tld\tr3, HSTATE_SPLIT_MODE(r13)\n \tcmpdi\tr3, 0\n \tbeq\tkvm_no_guest\n+\tlwz\tr0, KVM_SPLIT_DO_SET(r3)\n+\tcmpwi\tr0, 0\n+\tbne\tkvmhv_do_set\n+\tlwz\tr0, KVM_SPLIT_DO_RESTORE(r3)\n+\tcmpwi\tr0, 0\n+\tbne\tkvmhv_do_restore\n \tlbz\tr0, KVM_SPLIT_DO_NAP(r3)\n \tcmpwi\tr0, 0\n \tbeq\tkvm_no_guest\n@@ -479,6 +506,19 @@ kvm_no_guest:\n \tstb\tr0, HSTATE_HWTHREAD_STATE(r13)\n \tb\tkvm_no_guest\n \n+kvmhv_do_set:\n+\t/* Set LPCR, LPIDR etc. on P9 */\n+\tHMT_MEDIUM\n+\tbl\tkvmhv_p9_set_lpcr\n+\tnop\n+\tb\tkvm_no_guest\n+\n+kvmhv_do_restore:\n+\tHMT_MEDIUM\n+\tbl\tkvmhv_p9_restore_lpcr\n+\tnop\n+\tb\tkvm_no_guest\n+\n /*\n  * Here the primary thread is trying to return the core to\n  * whole-core mode, so we need to nap.\n@@ -516,8 +556,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)\n \t/* Set kvm_split_mode.napped[tid] = 1 */\n \tld\tr3, HSTATE_SPLIT_MODE(r13)\n \tli\tr0, 1\n-\tlhz\tr4, PACAPACAINDEX(r13)\n-\tclrldi\tr4, r4, 61\t/* micro-threading => P8 => 8 threads/core */\n+\tlbz\tr4, HSTATE_TID(r13)\n \taddi\tr4, r4, KVM_SPLIT_NAPPED\n \tstbx\tr0, r3, r4\n \t/* Check the do_nap flag again after setting napped[] */\n@@ -1911,10 +1950,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)\n 19:\tlis\tr8,0x7fff\t\t/* MAX_INT@h */\n \tmtspr\tSPRN_HDEC,r8\n \n-16:\tld\tr8,KVM_HOST_LPCR(r4)\n+16:\n+BEGIN_FTR_SECTION\n+\t/* On POWER9 with HPT-on-radix we need to wait for all other threads */\n+\tld\tr3, HSTATE_SPLIT_MODE(r13)\n+\tcmpdi\tr3, 0\n+\tbeq\t47f\n+\tlwz\tr8, KVM_SPLIT_DO_RESTORE(r3)\n+\tcmpwi\tr8, 0\n+\tbeq\t47f\n+\tstw\tr12, STACK_SLOT_TRAP(r1)\n+\tbl\tkvmhv_p9_restore_lpcr\n+\tnop\n+\tlwz\tr12, STACK_SLOT_TRAP(r1)\n+\tb\t48f\n+47:\n+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)\n+\tld\tr8,KVM_HOST_LPCR(r4)\n \tmtspr\tSPRN_LPCR,r8\n \tisync\n-\n+48:\n \t/* load host SLB entries */\n BEGIN_MMU_FTR_SECTION\n \tb\t0f\n",
    "prefixes": [
        "v2",
        "6/6"
    ]
}